因此,我正在构建一个新的安全令牌服务,以取代基于 IdentityServer3 的旧解决方案。我希望使用 PKCE 流进行身份验证,到目前为止,我已经为新服务配置了证书、身份资源、测试用户、API 资源和客户端。
身份资源
IEnumerable<IdentityResource> IdentityResources => new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource
{
Name = JwtClaimTypes.Role,
UserClaims = new List<string> { JwtClaimTypes.Role }
}
};
用户
List<TestUser> Users => new List<TestUser>
{
new TestUser
{
SubjectId = "1234",
Username = "asd",
Password = "asd",
Claims = new [] { new Claim(JwtClaimTypes.Role, "super") }
}
};
API 资源
IEnumerable<ApiResource> Apis => new List<ApiResource>
{
new ApiResource
{
Name = "api",
UserClaims = new List<string> { JwtClaimTypes.Role },
Scopes = new List<Scope> { new Scope("api") }
}
};
客户
IEnumerable<Client> Clients => new List<Client>
{
new Client
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.Code,
AllowAccessTokensViaBrowser = true,
RequirePkce = true,
RequireClientSecret = false,
RequireConsent = false,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
JwtClaimTypes.Role,
"api"
},
AllowedCorsOrigins = { "http://localhost:3005/" },
RedirectUris = { "http://localhost:3005/callback.html" },
PostLogoutRedirectUris = { "http://localhost:3005/index.html" }
}
};
AngularJS 客户端正在使用 oidc-client.js。这与我的令牌服务之间的通信似乎工作正常。我得到了从 IdentityServer4 返回的有效 JWT 令牌,其中包含我期望的数据。我的目标是将访问令牌中包含的用户 ID 传递给 API,因此它可以确保通过专门为检查用户是否具有“超级”角色而构建的外部库对用户进行身份验证,并使用用户 ID。
客户端像这样配置 OIDC UserManager:
return new Oidc.UserManager({
client_id: 'client',
response_type: 'code',
filterProtocolClaims: true,
loadUserInfo: true,
revokeAccessTokenOnSignout: true,
scope: 'openid profile role api',
authority: 'https://localhost:44300/',
redirect_uri: 'http://localhost:3005/callback.html',
post_logout_redirect_uri: 'http://localhost:3005/index.html'
});
现在,这是一个旧代码库 - 但在我看来,当从客户端调用 API 时 - 访问令牌被放入使用 $httpProvider.interceptors 的 push() 调用中的授权标头中,就像这样..
$httpProvider.interceptors.push(function (apiUrl, oidcManager, currentLanguage) {
return {
'request': function (config) {
if (isApiCall(config, apiUrl, oidcManager)) {
var userManager = oidcManager.getUserManager();
userManager.getUser().then(function (user) {
if (!user) {
userManager.signinRedirect();
}
config.headers.Authorization = 'Bearer ' + user.access_token;
});
}
return config;
}
};
});
在记录配置对象时,我可以验证 Authorization 标头是否确实包含我需要的访问令牌。但是,当使用没有必需输入参数的简单 GET 请求调用 API 时 - 受操作方法上的 [Authorize] 属性保护,我得到 401 Not Authorized 响应。API 是这样配置的,在 Startup 类中..
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions {
Authority = "https://localhost:44300/",
RequiredScopes = new[] { "api" }
}
);
现在,在控制器构造函数中为我试图命中的端点设置一个断点,我可以看到没有用户数据、声明等被拾取。我猜这与旧的 AngularJS 客户端如何构建和传递这些请求有关,但到目前为止我被困住了!
对此问题的任何见解和指导将不胜感激 - 并感谢您阅读我的长期混乱!