简体   繁体   English

.NET Core OpenId Connect Server:跨多个应用程序共享相同的令牌

[英].NET Core OpenId Connect Server: Sharing same token across multiple applications

I have two apis written in .NET Core and targeting 4.6.1: 我有两个用.NET Core编写的api,目标是4.6.1:

  1. myAuthApi ( http://localhost:8496 ): which verifies credentials and issues tokens to clients. myAuthApi( http:// localhost:8496 ):用于验证凭据并向客户端发送令牌。 It also have an endpoint /api/values/1 (with an Authorize attribute on this action, used to validate tokens) 它还有一个端点/ api / values / 1(此操作的Authorize属性,用于验证令牌)
  2. myPublicApi( http://localhost:8497 ): which receives tokens from the client on /api/values/1 (with an Authorize attribute on this action, also used to validate tokens). myPublicApi( http:// localhost:8497 ):从/ api / values / 1上的客户端接收令牌(此操作的Authorize属性,也用于验证令牌)。 myPublicApi does not have any tokens endpoint and is meant to be a resource server. myPublicApi没有任何令牌端点,并且是资源服务器。

I am using AspNet.Security.OpenIdConnect.Server 1.0.0. 我正在使用AspNet.Security.OpenIdConnect.Server 1.0.0。 Both APIs are Service.Fabric Stateless Services 这两个API都是Service.Fabric无状态服务

I can successfully get the token with the following request format to http://localhost:8496/connect/token 我可以使用以下请求格式成功获取带有http:// localhost:8496 / connect / token的令牌

client_id=XX&client_secret=XXX&grant_type=password&username=XXX&password=XXX

When validating the token against myAuthApi ( http://localhost:8496/api/values/1 ) it works. 在针对myAuthApi( http:// localhost:8496 / api / values / 1 )验证令牌时,它可以正常工作。 However, when using that same token against myPublicApi( http://localhost:8497/api/values/1 ) it does not. 但是,当对myPublicApi( http:// localhost:8497 / api / values / 1 )使用相同的令牌时,它不会。

In both APIs, in the Startup.cs, I have 在两个API中,在Startup.cs中,我有

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Connect to Redis database.
        var redis = ConnectionMultiplexer.Connect(ConnectionHelper.GetRedisConnectionString(Configuration));
        services.AddDataProtection()
            .PersistKeysToRedis(redis, "DataProtection-Keys")
            .ProtectKeysWithCertificate(CertificateHandler.GetX509Certificate2(Configuration));

        // Add framework services.
        services.AddMvc().AddJsonOptions(opts =>
        {
            // we set the json serializer to follow camelCaseConventions when 
            // receiving /replying to JSON requests
            opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        });
        // we add authentication for the oAuth middleware to be registered in the DI container
        services.AddAuthentication();
    }

In myPublicApi I have: 在myPublicApi中我有:

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {

        // Add a new middleware validating access tokens.
        app.UseOAuthValidation(options =>
        {
            // Automatic authentication must be enabled
            // for SignalR to receive the access token.
            options.AutomaticAuthenticate = true;
            options.Events = new OAuthValidationEvents
            {
                // Note: for SignalR connections, the default Authorization header does not work,
                // because the WebSockets JS API doesn't allow setting custom parameters.
                // To work around this limitation, the access token is retrieved from the query string.
                OnRetrieveToken = context =>
                {
                    // Note: when the token is missing from the query string,
                    // context.Token is null and the JWT bearer middleware will
                    // automatically try to retrieve it from the Authorization header.
                    context.Token = context.Request.Query["access_token"];

                    return Task.FromResult(0);
                }
            };
        });

        app.UseMvc();
    }

In myAuthApi I have: 在myAuthApi中我有:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // Add a new middleware validating access tokens.
        app.UseOAuthValidation(options =>
        {
            // Automatic authentication must be enabled
            // for SignalR to receive the access token.
            options.AutomaticAuthenticate = true;
            options.Events = new OAuthValidationEvents
            {
                // Note: for SignalR connections, the default Authorization header does not work,
                // because the WebSockets JS API doesn't allow setting custom parameters.
                // To work around this limitation, the access token is retrieved from the query string.
                OnRetrieveToken = context =>
                {
                    // Note: when the token is missing from the query string,
                    // context.Token is null and the JWT bearer middleware will
                    // automatically try to retrieve it from the Authorization header.
                    context.Token = context.Request.Query["access_token"];

                    return Task.FromResult(0);
                }
            };
        });

        // Add a new middleware issuing access tokens.
        app.UseOpenIdConnectServer(options =>
        {
            options.Provider = new AuthenticationProvider();
            // Enable the logout, token and userinfo endpoints.
            options.LogoutEndpointPath = "/connect/logout";
            options.TokenEndpointPath = "/connect/token";
            options.UserinfoEndpointPath = "/connect/userinfo";
            CertificateHandler.SetupCommonAuthServerOptions(options, Configuration);
        });

        app.UseMvc();
    }

As you can see, my data protection provider is storing keys in Redis, and I am protecting keys with a certificate which I am sharing across the 2 applications. 正如您所看到的,我的数据保护提供程序正在将密钥存储在Redis中,而我正在使用我在2个应用程序中共享的证书来保护密钥。 The resource server does not have any authentication provider configured and does not have UseOpenIdConnectServer in startup. 资源服务器未配置任何身份验证提供程序,并且在启动时没有UseOpenIdConnectServer。 In asp.net Web API 2, the token decryption used to be managed across the apps using shared machine keys. 在asp.net Web API 2中,令牌解密过去是使用共享机器密钥在应用程序之间进行管理的。

How can I successfully validate the token issued by myAuthApi across all other apps using oAuthValidation? 如何使用oAuthValidation成功验证myAuthApi在所有其他应用程序中发出的令牌?

EDIT, some logs can be seen here: https://pastebin.com/ACDz1fam 编辑,这里可以看到一些日志: https//pastebin.com/ACDz1fam

EDIT2 : After reading the logs thoroughly, I saw that the unprotection of the token was using the same Data Protection Provider, but different purposes: 编辑2:彻底阅读日志后,我发现令牌的不受保护是使用相同的数据保护提供程序,但目的不同:

"Performing unprotect operation to key {4406cfa7-a588-44ba-b73a-e25817d982d9} with purposes ('C:\SfDevCluster\Data\_App\_Node_4\TestMicroServicesType_App22\PublicApiPkg.Code.1.0.1', 'OpenIdConnectServerHandler', 'AccessTokenFormat', 'ASOS')."
"Performing unprotect operation to key {4406cfa7-a588-44ba-b73a-e25817d982d9} with purposes ('C:\SfDevCluster\Data\_App\_Node_3\TestMicroServicesType_App22\AuthApiPkg.Code.1.0.1', 'OpenIdConnectServerHandler', 'AccessTokenFormat', 'ASOS')."

To fix this, @PinpointTownes suggested to setup the data protection provider like so: 要解决这个问题,@ PinpointTownes建议设置数据保护提供程序,如下所示:

    var redis = ConnectionMultiplexer.Connect(ConnectionHelper.GetRedisConnectionString(Configuration));
    services.AddDataProtection()
             // set the application name to a common value in all apps 
             // to have the same purpose and share the token across apps
            .SetApplicationName("MyTestMicroServices")
            .PersistKeysToRedis(redis, "DataProtection-Keys")
            .ProtectKeysWithCertificate(CertificateHandler.GetX509Certificate2(Configuration)); 

调用services.AddDataProtection().SetApplicationName("[your application name]")以确保您的两个API使用相同的鉴别器(用于派生加密密钥),它应该工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 OpenID-Connect 身份验证服务器的登录页面中是否需要 CSRF 令牌? - Is CSRF token necessary in the login page of an OpenID-Connect authentication server? 与2个Rails应用程序共享OAuth令牌 - Sharing an OAuth token with 2 Rails Applications 在OpenID Connect中,是否可以将id令牌而不是访问令牌传递给资源服务器进行授权? - In OpenID Connect, is it okay to pass an id token instead of an access token to a resource server for authorization? 跨多个应用程序的 Identityserver4 授权(Grafana、.net API) - Identityserver4 authorization across multiple applications (Grafana, .net API) 数据库架构允许同一帐户的多个登录机会(Facebook-Connect,Oauth,OpenID等) - Database Schema allowing for multiple login opportunities (Facebook-Connect, Oauth, OpenID, etc.) for the same account openId Connect + OAuth的独立授权和资源服务器 - Seperate Authorisation and resource server for openId Connect + OAuth OAuth 和 OpenID Connect - 何时使用刷新令牌以及选择哪条路线 - OAuth & OpenID Connect - When To Use Refresh Token & Which Route To Choose 如何在 OpenID 连接中将 ID 或访问令牌从前端发送到后端 - How to send the ID or access token from frontend to backend in OpenID connect 生成自己的 JWT Bearer 是否与 OAuth/OpenID Connect 相同? - Is generating your own JWT Bearer the same as OAuth/OpenID Connect? 适用于多种应用程序的OWIN Authentication Server - OWIN Authentication Server for multiple applications
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM