|
|
|
@ -543,24 +543,73 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken)) |
|
|
|
// To reduce the size of tokens, some of the private claims used by OpenIddict
|
|
|
|
// are mapped to their standard equivalent before being removed from the token.
|
|
|
|
// This handler is responsible of adding back the private claims to the principal
|
|
|
|
// when receiving the token (e.g "oi_prst" is resolved from the "scope" claim).
|
|
|
|
|
|
|
|
// In OpenIddict 3.0, the creation date of a token is stored in "oi_crt_dt".
|
|
|
|
// If the claim doesn't exist, try to infer it from the standard "iat" JWT claim.
|
|
|
|
if (!context.Principal.HasClaim(Claims.Private.CreationDate)) |
|
|
|
{ |
|
|
|
var date = context.Principal.GetClaim(Claims.IssuedAt); |
|
|
|
if (!string.IsNullOrEmpty(date) && |
|
|
|
long.TryParse(date, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) |
|
|
|
{ |
|
|
|
context.Principal.SetCreationDate(DateTimeOffset.FromUnixTimeSeconds(value)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// In OpenIddict 3.0, the expiration date of a token is stored in "oi_exp_dt".
|
|
|
|
// If the claim doesn't exist, try to infer it from the standard "exp" JWT claim.
|
|
|
|
if (!context.Principal.HasClaim(Claims.Private.ExpirationDate)) |
|
|
|
{ |
|
|
|
return default; |
|
|
|
var date = context.Principal.GetClaim(Claims.ExpiresAt); |
|
|
|
if (!string.IsNullOrEmpty(date) && |
|
|
|
long.TryParse(date, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) |
|
|
|
{ |
|
|
|
context.Principal.SetExpirationDate(DateTimeOffset.FromUnixTimeSeconds(value)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// In OpenIddict 3.0, the audiences allowed to receive a token are stored in "oi_aud".
|
|
|
|
// If no such claim exists, try to infer them from the standard "aud" JWT claims.
|
|
|
|
if (!context.Principal.HasAudience()) |
|
|
|
{ |
|
|
|
var audiences = context.Principal.GetClaims(Claims.Audience); |
|
|
|
if (audiences.Any()) |
|
|
|
{ |
|
|
|
context.Principal.SetAudiences(audiences); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Map the standardized "azp" and "scope" claims to their "oi_" equivalent so that
|
|
|
|
// the ClaimsPrincipal extensions exposed by OpenIddict return consistent results.
|
|
|
|
// In OpenIddict 3.0, the presenters allowed to use a token are stored in "oi_prst".
|
|
|
|
// If no such claim exists, try to infer them from the standard "azp" and "client_id" JWT claims.
|
|
|
|
//
|
|
|
|
// Note: in previous OpenIddict versions, the presenters were represented in JWT tokens
|
|
|
|
// using the "azp" claim (defined by OpenID Connect), for which a single value could be
|
|
|
|
// specified. To ensure presenters stored in JWT tokens created by OpenIddict 1.x/2.x
|
|
|
|
// can still be read with OpenIddict 3.0, the presenter is automatically inferred from
|
|
|
|
// the "azp" or "client_id" claim if no "oi_prst" claim was found in the principal.
|
|
|
|
if (!context.Principal.HasPresenter()) |
|
|
|
{ |
|
|
|
context.Principal.SetPresenters(context.Principal.GetClaims(Claims.AuthorizedParty)); |
|
|
|
var presenter = context.Principal.GetClaim(Claims.AuthorizedParty) ?? |
|
|
|
context.Principal.GetClaim(Claims.ClientId); |
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(presenter)) |
|
|
|
{ |
|
|
|
context.Principal.SetPresenters(presenter); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// In OpenIddict 3.0, the scopes granted to an application are stored in "oi_scp".
|
|
|
|
//
|
|
|
|
// Note: in previous OpenIddict versions, scopes were represented as a JSON array
|
|
|
|
// and deserialized as multiple claims. In OpenIddict 3.0, the public "scope" claim
|
|
|
|
// is formatted as a unique space-separated string containing all the granted scopes.
|
|
|
|
// To ensure access tokens generated by previous versions are still correctly handled,
|
|
|
|
// both formats (unique space-separated string or multiple scope claims) must be supported.
|
|
|
|
// Visit https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-03 for more information.
|
|
|
|
// Visit https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-04 for more information.
|
|
|
|
if (!context.Principal.HasScope()) |
|
|
|
{ |
|
|
|
var scopes = context.Principal.GetClaims(Claims.Scope); |
|
|
|
@ -569,7 +618,10 @@ namespace OpenIddict.Server |
|
|
|
scopes = scopes[0].Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries).ToImmutableArray(); |
|
|
|
} |
|
|
|
|
|
|
|
context.Principal.SetScopes(scopes); |
|
|
|
if (scopes.Any()) |
|
|
|
{ |
|
|
|
context.Principal.SetScopes(scopes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return default; |
|
|
|
@ -634,8 +686,8 @@ namespace OpenIddict.Server |
|
|
|
context.Principal = context.Principal |
|
|
|
.SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) |
|
|
|
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) |
|
|
|
.SetInternalAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token)) |
|
|
|
.SetInternalTokenId(await _tokenManager.GetIdAsync(token)) |
|
|
|
.SetAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token)) |
|
|
|
.SetTokenId(await _tokenManager.GetIdAsync(token)) |
|
|
|
.SetTokenType(await _tokenManager.GetTypeAsync(token)); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -771,7 +823,7 @@ namespace OpenIddict.Server |
|
|
|
// Extract the token identifier from the authentication principal.
|
|
|
|
// If no token identifier can be found, this indicates that the token
|
|
|
|
// has no backing database entry (e.g an access token or an identity token).
|
|
|
|
var identifier = context.Principal.GetInternalTokenId(); |
|
|
|
var identifier = context.Principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -816,7 +868,7 @@ namespace OpenIddict.Server |
|
|
|
await _tokenManager.TryRevokeAsync(token); |
|
|
|
|
|
|
|
// Then, try to revoke the authorization and the associated token entries.
|
|
|
|
await TryRevokeAuthorizationChainAsync(context.Principal.GetInternalAuthorizationId()); |
|
|
|
await TryRevokeAuthorizationChainAsync(context.Principal.GetAuthorizationId()); |
|
|
|
|
|
|
|
context.Logger.LogError("The token '{Identifier}' has already been redeemed.", identifier); |
|
|
|
|
|
|
|
@ -897,8 +949,8 @@ namespace OpenIddict.Server |
|
|
|
// Restore the creation/expiration dates/identifiers from the token entry metadata.
|
|
|
|
context.Principal.SetCreationDate(await _tokenManager.GetCreationDateAsync(token)) |
|
|
|
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token)) |
|
|
|
.SetInternalAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token)) |
|
|
|
.SetInternalTokenId(await _tokenManager.GetIdAsync(token)) |
|
|
|
.SetAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token)) |
|
|
|
.SetTokenId(await _tokenManager.GetIdAsync(token)) |
|
|
|
.SetTokenType(await _tokenManager.GetTypeAsync(token)); |
|
|
|
|
|
|
|
async ValueTask TryRevokeAuthorizationChainAsync(string identifier) |
|
|
|
@ -919,7 +971,7 @@ namespace OpenIddict.Server |
|
|
|
await foreach (var token in _tokenManager.FindByAuthorizationIdAsync(identifier)) |
|
|
|
{ |
|
|
|
// Don't change the status of the token used in the token request.
|
|
|
|
if (string.Equals(context.Principal.GetInternalTokenId(), |
|
|
|
if (string.Equals(context.Principal.GetTokenId(), |
|
|
|
await _tokenManager.GetIdAsync(token), StringComparison.Ordinal)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
@ -969,7 +1021,7 @@ namespace OpenIddict.Server |
|
|
|
throw new ArgumentNullException(nameof(context)); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = context.Principal.GetInternalAuthorizationId(); |
|
|
|
var identifier = context.Principal.GetAuthorizationId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -1286,7 +1338,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("The authentication context cannot be found."); |
|
|
|
|
|
|
|
// Extract the device code identifier from the authentication principal.
|
|
|
|
var identifier = notification.Principal.GetInternalTokenId(); |
|
|
|
var identifier = notification.Principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -1741,7 +1793,7 @@ namespace OpenIddict.Server |
|
|
|
} |
|
|
|
|
|
|
|
// If an authorization identifier was explicitly specified, don't create an ad-hoc authorization.
|
|
|
|
if (!string.IsNullOrEmpty(context.Principal.GetInternalAuthorizationId())) |
|
|
|
if (!string.IsNullOrEmpty(context.Principal.GetAuthorizationId())) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
@ -1791,7 +1843,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Attach the unique identifier of the ad hoc authorization to the authentication principal
|
|
|
|
// so that it is attached to all the derived tokens, allowing batched revocations support.
|
|
|
|
context.Principal.SetInternalAuthorizationId(identifier); |
|
|
|
context.Principal.SetAuthorizationId(identifier); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -1893,10 +1945,11 @@ namespace OpenIddict.Server |
|
|
|
principal.SetExpirationDate(principal.GetCreationDate() + lifetime.Value); |
|
|
|
} |
|
|
|
|
|
|
|
// Set the public audiences collection using the private resource claims stored in the principal.
|
|
|
|
// Set the audiences based on the resource claims stored in the principal.
|
|
|
|
principal.SetAudiences(context.Principal.GetResources()); |
|
|
|
|
|
|
|
// Store the client_id as a public client_id claim, if available.
|
|
|
|
// Store the client identifier in the public client_id claim, if available.
|
|
|
|
// See https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-04 for more information.
|
|
|
|
principal.SetClaim(Claims.ClientId, context.ClientId); |
|
|
|
|
|
|
|
// When receiving a grant_type=refresh_token request, determine whether the client application
|
|
|
|
@ -2271,6 +2324,10 @@ namespace OpenIddict.Server |
|
|
|
principal.SetAudiences(context.ClientId); |
|
|
|
} |
|
|
|
|
|
|
|
// Use the client_id as the authorized party, if available.
|
|
|
|
// See https://openid.net/specs/openid-connect-core-1_0.html#IDToken for more information.
|
|
|
|
principal.SetClaim(Claims.AuthorizedParty, context.ClientId); |
|
|
|
|
|
|
|
// If a nonce was present in the authorization request, it MUST be included in the id_token generated
|
|
|
|
// by the token endpoint. For that, OpenIddict simply flows the nonce as an authorization code claim.
|
|
|
|
// See http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation for more information.
|
|
|
|
@ -2278,6 +2335,7 @@ namespace OpenIddict.Server |
|
|
|
{ |
|
|
|
OpenIddictServerEndpointType.Authorization => context.Request.Nonce, |
|
|
|
OpenIddictServerEndpointType.Token => context.Principal.GetClaim(Claims.Private.Nonce), |
|
|
|
|
|
|
|
_ => null |
|
|
|
}); |
|
|
|
|
|
|
|
@ -2428,7 +2486,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Extract the token identifier from the authentication principal.
|
|
|
|
// If no token identifier can be found, this indicates that the token has no backing database entry.
|
|
|
|
var identifier = context.Principal.GetInternalTokenId(); |
|
|
|
var identifier = context.Principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -2517,7 +2575,7 @@ namespace OpenIddict.Server |
|
|
|
// If the operation fails, silently ignore the error and keep processing the request:
|
|
|
|
// this may indicate that one of the revoked tokens was modified by a concurrent request.
|
|
|
|
|
|
|
|
var identifier = context.Principal.GetInternalAuthorizationId(); |
|
|
|
var identifier = context.Principal.GetAuthorizationId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -2526,7 +2584,7 @@ namespace OpenIddict.Server |
|
|
|
await foreach (var token in _tokenManager.FindByAuthorizationIdAsync(identifier)) |
|
|
|
{ |
|
|
|
// Don't change the status of the token used in the token request.
|
|
|
|
if (string.Equals(context.Principal.GetInternalTokenId(), |
|
|
|
if (string.Equals(context.Principal.GetTokenId(), |
|
|
|
await _tokenManager.GetIdAsync(token), StringComparison.Ordinal)) |
|
|
|
{ |
|
|
|
continue; |
|
|
|
@ -2590,7 +2648,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Extract the token identifier from the authentication principal.
|
|
|
|
// If no token identifier can be found, this indicates that the token has no backing database entry.
|
|
|
|
var identifier = context.Principal.GetInternalTokenId(); |
|
|
|
var identifier = context.Principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -2670,12 +2728,12 @@ namespace OpenIddict.Server |
|
|
|
var principal = context.AccessTokenPrincipal; |
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -2705,7 +2763,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for access token '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -2746,55 +2804,78 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Copy the principal and exclude the presenters/scopes private claims,
|
|
|
|
// that are manually mapped to public standard azp/scope JWT claims.
|
|
|
|
var principal = context.AccessTokenPrincipal.Clone(claim => claim.Type switch |
|
|
|
// Clone the principal and exclude the private claims mapped to standard JWT claims.
|
|
|
|
var principal = context.AccessTokenPrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.Presenter => false, |
|
|
|
Claims.Private.Scope => false, |
|
|
|
Claims.Private.Audience => false, |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.Scope => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
// Set the authorized party using the first presenter (typically the client identifier), if available.
|
|
|
|
principal.SetClaim(Claims.AuthorizedParty, context.AccessTokenPrincipal.GetPresenters().FirstOrDefault()); |
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var claims = new Dictionary<string, object>(StringComparer.Ordinal); |
|
|
|
|
|
|
|
// Set the public audience claims using the private audience claims from the principal.
|
|
|
|
// Note: when there's a single audience, represent it as a unique string claim.
|
|
|
|
var audiences = context.AccessTokenPrincipal.GetAudiences(); |
|
|
|
if (audiences.Any()) |
|
|
|
{ |
|
|
|
claims.Add(Claims.Audience, audiences.Length switch |
|
|
|
{ |
|
|
|
1 => audiences.ElementAt(0), |
|
|
|
_ => audiences |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// Set the public scope claim using the private scope claims from the principal.
|
|
|
|
// Note: scopes are deliberately formatted as a single space-separated
|
|
|
|
// string to respect the usual representation of the standard scope claim.
|
|
|
|
// See https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-02.
|
|
|
|
principal.SetClaim(Claims.Scope, string.Join(" ", context.AccessTokenPrincipal.GetScopes())); |
|
|
|
// See https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-04.
|
|
|
|
var scopes = context.AccessTokenPrincipal.GetScopes(); |
|
|
|
if (scopes.Any()) |
|
|
|
{ |
|
|
|
claims.Add(Claims.Scope, string.Join(" ", scopes)); |
|
|
|
} |
|
|
|
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(new SecurityTokenDescriptor |
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.AccessToken |
|
|
|
}, |
|
|
|
Claims = claims, |
|
|
|
Expires = context.AccessTokenPrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.AccessTokenPrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(credentials => |
|
|
|
credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First(), |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
if (!context.Options.DisableAccessTokenEncryption) |
|
|
|
{ |
|
|
|
token = context.Options.JsonWebTokenHandler.EncryptToken(token, |
|
|
|
context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
encryptingCredentials: context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
credentials => credentials.Key is SymmetricSecurityKey) ?? |
|
|
|
context.Options.EncryptionCredentials.First(), |
|
|
|
new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.AccessToken |
|
|
|
}); |
|
|
|
additionalHeaderClaims: descriptor.AdditionalHeaderClaims); |
|
|
|
} |
|
|
|
|
|
|
|
context.Response.AccessToken = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The access token '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.AccessTokenPrincipal.GetClaim(Claims.JwtId), |
|
|
|
context.Response.AccessToken, principal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
@ -2857,7 +2938,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = principal.GetInternalTokenId(); |
|
|
|
var identifier = principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -2954,7 +3035,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -2984,7 +3065,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for authorization code '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -3025,20 +3106,37 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Clone the principal and exclude the claim mapped to standard JWT claims.
|
|
|
|
var principal = context.AuthorizationCodePrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.AuthorizationCode |
|
|
|
}, |
|
|
|
Expires = context.AuthorizationCodePrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.AuthorizationCodePrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(credentials => |
|
|
|
credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First(), |
|
|
|
Subject = (ClaimsIdentity) context.AuthorizationCodePrincipal.Identity |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}; |
|
|
|
|
|
|
|
// Attach claims destinations to the JWT claims collection.
|
|
|
|
var destinations = context.AuthorizationCodePrincipal.GetDestinations(); |
|
|
|
var destinations = principal.GetDestinations(); |
|
|
|
if (destinations.Count != 0) |
|
|
|
{ |
|
|
|
descriptor.Claims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
@ -3049,21 +3147,18 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Sign and encrypt the authorization code.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
token = context.Options.JsonWebTokenHandler.EncryptToken(token, |
|
|
|
context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
encryptingCredentials: context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
credentials => credentials.Key is SymmetricSecurityKey) ?? |
|
|
|
context.Options.EncryptionCredentials.First(), |
|
|
|
new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.AuthorizationCode |
|
|
|
}); |
|
|
|
additionalHeaderClaims: descriptor.AdditionalHeaderClaims); |
|
|
|
|
|
|
|
context.Response.Code = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The authorization code '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.AuthorizationCodePrincipal.GetClaim(Claims.JwtId), token, |
|
|
|
context.AuthorizationCodePrincipal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
@ -3126,7 +3221,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = principal.GetInternalTokenId(); |
|
|
|
var identifier = principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -3228,7 +3323,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -3258,7 +3353,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for device code '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -3299,20 +3394,37 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Clone the principal and exclude the claim mapped to standard JWT claims.
|
|
|
|
var principal = context.DeviceCodePrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.DeviceCode |
|
|
|
}, |
|
|
|
Expires = context.DeviceCodePrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.DeviceCodePrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(credentials => |
|
|
|
credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First(), |
|
|
|
Subject = (ClaimsIdentity) context.DeviceCodePrincipal.Identity |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}; |
|
|
|
|
|
|
|
// Attach claims destinations to the JWT claims collection.
|
|
|
|
var destinations = context.DeviceCodePrincipal.GetDestinations(); |
|
|
|
var destinations = principal.GetDestinations(); |
|
|
|
if (destinations.Count != 0) |
|
|
|
{ |
|
|
|
descriptor.Claims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
@ -3323,21 +3435,18 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Sign and encrypt the device code.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
token = context.Options.JsonWebTokenHandler.EncryptToken(token, |
|
|
|
context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
encryptingCredentials: context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
credentials => credentials.Key is SymmetricSecurityKey) ?? |
|
|
|
context.Options.EncryptionCredentials.First(), |
|
|
|
new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.DeviceCode |
|
|
|
}); |
|
|
|
additionalHeaderClaims: descriptor.AdditionalHeaderClaims); |
|
|
|
|
|
|
|
context.Response.DeviceCode = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The device code '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.DeviceCodePrincipal.GetClaim(Claims.JwtId), token, |
|
|
|
context.DeviceCodePrincipal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
@ -3405,7 +3514,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = principal.GetInternalTokenId(); |
|
|
|
var identifier = principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -3598,7 +3707,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -3628,7 +3737,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for refresh token '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -3669,20 +3778,37 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Clone the principal and exclude the claim mapped to standard JWT claims.
|
|
|
|
var principal = context.RefreshTokenPrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.RefreshToken |
|
|
|
}, |
|
|
|
Expires = context.RefreshTokenPrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.RefreshTokenPrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(credentials => |
|
|
|
credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First(), |
|
|
|
Subject = (ClaimsIdentity) context.RefreshTokenPrincipal.Identity |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}; |
|
|
|
|
|
|
|
// Attach claims destinations to the JWT claims collection.
|
|
|
|
var destinations = context.RefreshTokenPrincipal.GetDestinations(); |
|
|
|
var destinations = principal.GetDestinations(); |
|
|
|
if (destinations.Count != 0) |
|
|
|
{ |
|
|
|
descriptor.Claims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
@ -3693,21 +3819,18 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
// Sign and encrypt the refresh token.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
token = context.Options.JsonWebTokenHandler.EncryptToken(token, |
|
|
|
context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
encryptingCredentials: context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
credentials => credentials.Key is SymmetricSecurityKey) ?? |
|
|
|
context.Options.EncryptionCredentials.First(), |
|
|
|
new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.RefreshToken |
|
|
|
}); |
|
|
|
additionalHeaderClaims: descriptor.AdditionalHeaderClaims); |
|
|
|
|
|
|
|
context.Response.RefreshToken = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The refresh token '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.RefreshTokenPrincipal.GetClaim(Claims.JwtId), token, |
|
|
|
context.RefreshTokenPrincipal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
@ -3770,7 +3893,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = principal.GetInternalTokenId(); |
|
|
|
var identifier = principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -3844,7 +3967,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = context.DeviceCodePrincipal.GetInternalTokenId(); |
|
|
|
var identifier = context.DeviceCodePrincipal.GetTokenId(); |
|
|
|
if (!string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
principal.SetClaim(Claims.Private.DeviceCodeId, identifier); |
|
|
|
@ -3913,7 +4036,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -3943,7 +4066,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for user code '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -3984,34 +4107,49 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Sign and encrypt the user code.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(new SecurityTokenDescriptor |
|
|
|
// Clone the principal and exclude the claim mapped to standard JWT claims.
|
|
|
|
var principal = context.UserCodePrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.UserCode |
|
|
|
}, |
|
|
|
Expires = context.UserCodePrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.UserCodePrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.FirstOrDefault(credentials => |
|
|
|
credentials.Key is SymmetricSecurityKey) ?? context.Options.SigningCredentials.First(), |
|
|
|
Subject = (ClaimsIdentity) context.UserCodePrincipal.Identity |
|
|
|
}); |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}; |
|
|
|
|
|
|
|
// Sign and encrypt the user code.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
token = context.Options.JsonWebTokenHandler.EncryptToken(token, |
|
|
|
context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
encryptingCredentials: context.Options.EncryptionCredentials.FirstOrDefault( |
|
|
|
credentials => credentials.Key is SymmetricSecurityKey) ?? |
|
|
|
context.Options.EncryptionCredentials.First(), |
|
|
|
new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.Private.UserCode |
|
|
|
}); |
|
|
|
additionalHeaderClaims: descriptor.AdditionalHeaderClaims); |
|
|
|
|
|
|
|
context.Response.UserCode = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The user code '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.UserCodePrincipal.GetClaim(Claims.JwtId), token, |
|
|
|
context.UserCodePrincipal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
@ -4074,7 +4212,7 @@ namespace OpenIddict.Server |
|
|
|
throw new InvalidOperationException("A token entry cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var identifier = principal.GetInternalTokenId(); |
|
|
|
var identifier = principal.GetTokenId(); |
|
|
|
if (string.IsNullOrEmpty(identifier)) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("The token identifier cannot be extracted from the principal."); |
|
|
|
@ -4315,7 +4453,7 @@ namespace OpenIddict.Server |
|
|
|
|
|
|
|
var descriptor = new OpenIddictTokenDescriptor |
|
|
|
{ |
|
|
|
AuthorizationId = principal.GetInternalAuthorizationId(), |
|
|
|
AuthorizationId = principal.GetAuthorizationId(), |
|
|
|
CreationDate = principal.GetCreationDate(), |
|
|
|
ExpirationDate = principal.GetExpirationDate(), |
|
|
|
Principal = principal, |
|
|
|
@ -4345,7 +4483,7 @@ namespace OpenIddict.Server |
|
|
|
var identifier = await _tokenManager.GetIdAsync(token); |
|
|
|
|
|
|
|
// Attach the token identifier to the principal so that it can be stored in the token.
|
|
|
|
principal.SetInternalTokenId(identifier); |
|
|
|
principal.SetTokenId(identifier); |
|
|
|
|
|
|
|
context.Logger.LogTrace("The token entry for identity token '{Identifier}' was successfully created.", identifier); |
|
|
|
} |
|
|
|
@ -4386,23 +4524,59 @@ namespace OpenIddict.Server |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
// Sign and attach the identity token.
|
|
|
|
context.Response.IdToken = context.Options.JsonWebTokenHandler.CreateToken(new SecurityTokenDescriptor |
|
|
|
// Clone the principal and exclude the claim mapped to standard JWT claims.
|
|
|
|
var principal = context.IdentityTokenPrincipal?.Clone(claim => claim.Type switch |
|
|
|
{ |
|
|
|
Claims.Private.Audience => false, |
|
|
|
Claims.Private.CreationDate => false, |
|
|
|
Claims.Private.ExpirationDate => false, |
|
|
|
Claims.Private.TokenType => false, |
|
|
|
|
|
|
|
_ => true |
|
|
|
}); |
|
|
|
|
|
|
|
if (principal == null) |
|
|
|
{ |
|
|
|
throw new InvalidOperationException("A token cannot be created from a null principal."); |
|
|
|
} |
|
|
|
|
|
|
|
var claims = new Dictionary<string, object>(StringComparer.Ordinal); |
|
|
|
|
|
|
|
// Set the public audience claims using the private audience claims from the principal.
|
|
|
|
// Note: when there's a single audience, represent it as a unique string claim.
|
|
|
|
var audiences = context.IdentityTokenPrincipal.GetAudiences(); |
|
|
|
if (audiences.Any()) |
|
|
|
{ |
|
|
|
claims.Add(Claims.Audience, audiences.Length switch |
|
|
|
{ |
|
|
|
1 => audiences.ElementAt(0), |
|
|
|
_ => audiences |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
var descriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
AdditionalHeaderClaims = new Dictionary<string, object>(StringComparer.Ordinal) |
|
|
|
{ |
|
|
|
[JwtHeaderParameterNames.Typ] = JsonWebTokenTypes.IdentityToken |
|
|
|
}, |
|
|
|
Claims = claims, |
|
|
|
Expires = context.IdentityTokenPrincipal.GetExpirationDate()?.UtcDateTime, |
|
|
|
IssuedAt = context.IdentityTokenPrincipal.GetCreationDate()?.UtcDateTime, |
|
|
|
Issuer = context.Issuer?.AbsoluteUri, |
|
|
|
SigningCredentials = context.Options.SigningCredentials.First(credentials => |
|
|
|
credentials.Key is AsymmetricSecurityKey), |
|
|
|
Subject = (ClaimsIdentity) context.IdentityTokenPrincipal.Identity |
|
|
|
}); |
|
|
|
Subject = (ClaimsIdentity) principal.Identity |
|
|
|
}; |
|
|
|
|
|
|
|
// Sign and attach the identity token.
|
|
|
|
var token = context.Options.JsonWebTokenHandler.CreateToken(descriptor); |
|
|
|
|
|
|
|
context.Response.IdToken = token; |
|
|
|
|
|
|
|
context.Logger.LogTrace("The identity token '{Identifier}' was successfully created: {Payload}. " + |
|
|
|
"The principal used to create the token contained the following claims: {Claims}.", |
|
|
|
context.IdentityTokenPrincipal.GetClaim(Claims.JwtId), |
|
|
|
context.Response.IdToken, context.IdentityTokenPrincipal.Claims); |
|
|
|
principal.GetClaim(Claims.JwtId), token, principal.Claims); |
|
|
|
|
|
|
|
return default; |
|
|
|
} |
|
|
|
|