我们有一个应用程序使用IdentityServer4 cookie授权方案进行用户登录,如下所示:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = <local IDP server with IdentityServer4>;
options.ClientId = <ClientId>;
options.ClientSecret = <secret>
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
})
IDP上的客户端如下所示:
new Client
{
ClientId = <ClientID>,
ClientName = <ClientName>,
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = true,
ClientSecrets = { new Secret(<secret>.Sha256()) },
AllowOfflineAccess = true,
RedirectUris = { "http://" + ip + "/signin-oidc" },
PostLogoutRedirectUris = { "http://" + ip + "/signout-callback-oidc" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
};
我们还有一个位于/ api /...
的WebAPI目标是将JWT Bearer Token授权添加到API。为此,我添加了以下代码:
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = <local IDP server with IdentityServer4>;
jwtOptions.Audience = <ClientID>
jwtOptions.SaveToken = true;
})
API受到
的保护 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
登录后,我将获得带有
的令牌 await HttpContext.GetTokenAsync("access_token");
但是,当我尝试使用该令牌访问API时,我收到以下错误:
身份验证失败:IDX10214:受众验证失败。观众:“http://localhost:50059/resources”。不匹配:validationParameters.ValidAudience:ClientID或validationParameters.ValidAudiences:'null'。
事实上,当我使用jwt.io解码令牌时,aud
设置为http://localhost:50059/resources
,而ClientID显示为新字段'client_id': '<ClientID>'
。
到目前为止我发现,aud
始终设置为<idp>/resources
来访问令牌,并且API访问权限是使用令牌内的范围声明来处理的。但是,我不明白如何正确设置它。
有人知道问题出在哪里以及如何解决问题?我将不胜感激。
答案 0 :(得分:4)
事实证明,解决方案非常简单。可疑,它与范围有关。我试图解决这个问题,但它一直在说&#34;无效的范围&#34; ...因为我从未创建过API资源,呃。
new ApiResource("api-name", "API Name")
client.AllowedScopes.Add("api-name")
options.Scopes.Add("api-name")
options.Audience = "api-name"
要么
options.ApiName = "api-name"
有了这个,我现在可以使用访问令牌来访问我的API。