使用 AspNet.Security.OpenIdConnect 分离身份验证和资源服务器 - 观众? [英] Separating Auth and Resource Servers with AspNet.Security.OpenIdConnect - the Audience?

查看:15
本文介绍了使用 AspNet.Security.OpenIdConnect 分离身份验证和资源服务器 - 观众?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

AspNet.Security.OpenIdConnect.Server 在我看来既像身份验证服务器又像资源服务器.我想把它们分开.我已经这样做了.

在身份验证服务器的 Startup.Config,我有以下设置:

app.UseOpenIdConnectServer(options => {options.AllowInsecureHttp = true;options.ApplicationCanDisplayErrors = true;options.AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme;options.Issuer = new System.Uri("http://localhost:61854");//这个认证服务器options.Provider = new AuthorizationProvider();options.TokenEndpointPath = new PathString("/token");options.UseCertificate(new X509Certificate2(env.ApplicationBasePath + "\mycertificate.pfx","mycertificate"));});

我编写了一个 AuthorizationProvider,但我认为它与我当前的问题无关(但可能相关).在其 GrantResourceOwnerCredentials 覆盖中,我对声明主体进行了硬编码,以便它对每个令牌请求进行验证:

public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsNotification context){var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);identity.AddClaim(ClaimTypes.Name, "me");identity.AddClaim(ClaimTypes.Email, "me@gmail.com");var claimPrincipal = new ClaimsPrincipal(identity);context.Validated(claimsPrincipal);return Task.FromResult(null);}

在资源服务器上,我的 Startup.config 中有以下内容:

app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>{branch.UseOAuthBearerAuthentication(options => {options.Audience = "http://localhost:54408";//这个资源服务器,我相信.options.Authority = "http://localhost:61854";//认证服务器options.AutomaticAuthentication = true;});});

在 Fiddler 上,我要一个令牌,我得到了一个:

POST/token HTTP/1.1主机:本地主机:61854内容类型:应用程序/x-www-form-urlencoded用户名=管理员&密码=aaa000&grant_type=密码

所以现在我使用该访问令牌从资源服务器访问受保护的资源:

GET/api/values HTTP/1.1主机:本地主机:54408内容类型:application/json;charset=utf-8授权:承载 eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI .....

我现在收到此错误 - 受众验证失败.观众:空".与validationParameters.ValidAudience: 'http://localhost:54408' 或validationParameters.ValidAudiences: 'null' 不匹配.

我认为原因是因为我从未在身份验证服务器上设置受众(在 app.UseOpenIdConnectServer(...)),所以我认为它没有将受众信息写入令牌.所以我需要在身份验证服务器上设置一个受众(就像在 IdentityServer3 中所做的那样),但是我在选项对象上找不到可以让我这样做的属性.

AspNet.Security.OpenIdConnect.Server 是否要求身份验证和资源位于同一服务器中?

在组合 ClaimsPrincipal 时是否设置了受众?如果是,如何设置?

我是否需要编写自定义受众验证器并将其连接到系统?(我当然希望答案是否定的.)

解决方案

AspNet.Security.OpenIdConnect.Server 是否要求身份验证和资源位于同一服务器中?

不,您当然可以将这两个角色分开.

正如您已经发现的那样,如果您不明确指定它,授权服务器将无法确定访问令牌的目的地/受众,该令牌是在没有aud 的情况下发布的OAuth2 承载中间件默认要求声明.

解决这个问题很容易:只需在创建身份验证票证时调用 ticket.SetResources(resources),授权服务器将确切知道它应该使用哪个值(即资源服务器/API)添加 aud 声明.

app.UseOpenIdConnectServer(options =>{//强制 OpenID Connect 服务器中间件使用 JWT 令牌//而不是默认使用的默认不透明/加密令牌格式.options.AccessTokenHandler = new JwtSecurityTokenHandler();});公共覆盖任务 HandleTokenRequest(HandleTokenRequestContext context){如果 (context.Request.IsPasswordGrantType()){var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);identity.AddClaim(OpenIdConnectConstants.Claims.Subject,唯一标识符");var 票证 = 新的 AuthenticationTicket(新的 ClaimsPrincipal(身份),新的身份验证属性(),context.Options.AuthenticationScheme);//使用资源服务器列表调用 SetResources//应为其颁发访问令牌.ticket.SetResources("resource_server_1");//使用您要授予的范围列表调用 SetScopes.ticket.SetScopes("profile", "offline_access");上下文.验证(票);}返回 Task.FromResult(0);}app.UseJwtBearerAuthentication(new JwtBearerOptions{自动身份验证 = 真,自动挑战 = 真,观众 = "resource_server_1",权限=http://localhost:61854"});

The example on the AspNet.Security.OpenIdConnect.Server looks to me like both an auth and resource server. I would like to separate those. I have done so.

At the auth server's Startup.Config, I have the following settings:

app.UseOpenIdConnectServer(options => {

    options.AllowInsecureHttp = true;
    options.ApplicationCanDisplayErrors = true;
    options.AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme;
    options.Issuer = new System.Uri("http://localhost:61854"); // This auth server
    options.Provider = new AuthorizationProvider();
    options.TokenEndpointPath = new PathString("/token");              
    options.UseCertificate(new X509Certificate2(env.ApplicationBasePath + "\mycertificate.pfx","mycertificate"));

});

I have an AuthorizationProvider written, but I don't think it's relevant to my current issue (but possibly relevant). At its GrantResourceOwnerCredentials override, I hard-code a claims principal so that it validates for every token request:

public override Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsNotification context)
{
    var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);

    identity.AddClaim(ClaimTypes.Name, "me");
    identity.AddClaim(ClaimTypes.Email, "me@gmail.com");
    var claimsPrincipal = new ClaimsPrincipal(identity);

    context.Validated(claimsPrincipal);
    return Task.FromResult<object>(null);
}

At the resource server, I have the following in its Startup.config:

app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
{
    branch.UseOAuthBearerAuthentication(options => {
        options.Audience = "http://localhost:54408"; // This resource server, I believe.
        options.Authority = "http://localhost:61854"; // The auth server
        options.AutomaticAuthentication = true;               
    });
});

On Fiddler, I ask for a token, and I get one:

POST /token HTTP/1.1
Host: localhost:61854
Content-Type: application/x-www-form-urlencoded

username=admin&password=aaa000&grant_type=password

So now I use that access token to access a protected resource from the resource server:

GET /api/values HTTP/1.1
Host: localhost:54408
Content-Type: application/json;charset=utf-8
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI.....

I now get this error - Audience validation failed. Audiences: 'empty'. Did not match validationParameters.ValidAudience: 'http://localhost:54408' or validationParameters.ValidAudiences: 'null'.

I think the reason why is because I never set an audience at the auth server (at app.UseOpenIdConnectServer(...)), so I don't think it wrote audience info to the token. So I need to set an audience at the auth server (as what is done in IdentityServer3), but I can't find a property on the options object that would let me do that.

Does AspNet.Security.OpenIdConnect.Server require the auth and resource to be in the same server?

Is setting the audience done when putting together the ClaimsPrincipal, and if so, how?

Would I need to write a custom Audience validator and hook it up to the system? (I sure hope the answer to this is no.)

解决方案

Does AspNet.Security.OpenIdConnect.Server require the auth and resource to be in the same server?

No, you can of course separate the two roles.

As you've already figured out, if you don't explicitly specify it, the authorization server has no way to determine the destination/audience of an access token, which is issued without the aud claim required by default by the OAuth2 bearer middleware.

Solving this issue is easy: just call ticket.SetResources(resources) when creating the authentication ticket and the authorization server will know exactly which value(s) (i.e resource servers/API) it should add in the aud claim(s).

app.UseOpenIdConnectServer(options =>
{
    // Force the OpenID Connect server middleware to use JWT tokens
    // instead of the default opaque/encrypted token format used by default.
    options.AccessTokenHandler = new JwtSecurityTokenHandler();
});

public override Task HandleTokenRequest(HandleTokenRequestContext context)
{
    if (context.Request.IsPasswordGrantType())
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
        identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "unique identifier");

        var ticket = new AuthenticationTicket(
            new ClaimsPrincipal(identity),
            new AuthenticationProperties(),
            context.Options.AuthenticationScheme);

        // Call SetResources with the list of resource servers
        // the access token should be issued for.
        ticket.SetResources("resource_server_1");

        // Call SetScopes with the list of scopes you want to grant.
        ticket.SetScopes("profile", "offline_access");

        context.Validate(ticket);
    }

    return Task.FromResult(0);
}     

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    Audience = "resource_server_1",
    Authority = "http://localhost:61854"
});

这篇关于使用 AspNet.Security.OpenIdConnect 分离身份验证和资源服务器 - 观众?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆