之前我使用的是 OpenIddict 版本 3.1.1。 API 端的令牌验证突然遇到问题。虽然它是预览版,但我还是决定转向最新的 OpenIddict 4.3.0。 点是在以前的版本中,当登录后调用 Exchange 方法时,我从数据库中获取了一些自定义值,如登录用户 ID、tenentid 等。
[HttpPost("~/connect/token")]
...
...
else if (request.IsAuthorizationCodeGrantType())
{
// Note: the client credentials are automatically validated by OpenIddict:
// if client_id or client_secret are invalid, this action won't be invoked.
claimsPrincipal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;
var identity = new ClaimsIdentity(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
// Retrieve the user profile corresponding to the authorization code/refresh token.
var user = await _UserManager.FindByNameAsync(claimsPrincipal.GetClaim(Claims.Subject));
if (user is null)
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
}));
}
// Ensure the user is still allowed to sign in.
if (!await _SignInManager.CanSignInAsync(user))
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
}));
}
// Subject (sub) is a required field, we use the client id as the subject identifier here.
identity.AddClaim(OpenIddictConstants.Claims.Subject, request.ClientId ?? throw new InvalidOperationException());
**identity.AddClaim(OpenIddictConstants.Claims.Username, user.UserName);
identity.AddClaim("userid", user.Id);
identity.AddClaim(OpenIddictConstants.Claims.FamilyName, $"{user.FirstName} {user.LastName}");
identity.AddClaim("tenant", $"{user.CustomerID}");**
// Retrieve the claims principal stored in the authorization code
claimsPrincipal = new ClaimsPrincipal(identity);
claimsPrincipal.SetScopes(request.GetScopes());
...
...
// Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
return SignIn(claimsPrincipal, AuthProperties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
绝对在前端获取它(使用 Angular OIDC 客户端的前端)。
但是在迁移到 OpenIddict 4.3.0 之后,我没有得到这些自定义声明。根据 OpenIddict 4.3.0 的新变化,我也尝试过
identity.SetDestinations(static claim => claim.Type switch
{
// Allow the "name" claim to be stored in both the access and identity tokens
// when the "profile" scope was granted (by calling principal.SetScopes(...)).
Claims.Name when claim.Subject.HasScope(Scopes.Profile)
=> new[] { Destinations.AccessToken, Destinations.IdentityToken },
// Otherwise, only store the claim in the access tokens.
_ => new[] { Destinations.AccessToken }
});
如何在 Exchange 响应中获取这些自定义值?
在 OpenIdDict 3.1.1 预览版之前,我们得到了
{
"isAuthenticated": true,
"userData": {
"sub": "admin_local",
# ** "username": "Admin1",
# "userid": "7bcea554-97d7-47c2-9227-d4a6a71e166b",
# "family_name": "Admin One",
# "tenant": "fea5b4d2-928a-4f3e-a218-0cdc31bc22b0",**
"oi_au_id": "e496a220-2e9d-4cd4-8824-647e5d986505",
"azp": "portal_clientadmin_local",
"nonce": "66c5383d5242c179eb76505294a13b7aecxRMEZti",
"at_hash": "DisPfF50gKQ3PoVh0xqr8Q",
"oi_tkn_id": "21996ea9-f0a9-475b-81ed-d01d67890af5",
"aud": "portal_clientadmin_local",
"exp": 1683798041,
"iss": "http://192.168.0.11:9004/",
"iat": 1683796841
},
"accessToken": "<<SOME TOKEN VALUE>>",
"idToken": "<<SOME ID TOKEN VALUE>>",
"configId": "admin_local"
}
我期待与更新版本 OpenIDDict 4.3.0 相同的响应