private async Task <AuthenticationTicket> DeserializeIdentityTokenAsync(string token, OpenIdConnectRequest request)
        {
            var notification = new DeserializeIdentityTokenContext(Context, Scheme, Options, request, token)
            {
                SecurityTokenHandler = Options.IdentityTokenHandler
            };

            // Note: ValidateAudience and ValidateLifetime are always set to false:
            // if necessary, the audience and the expiration can be validated
            // in InvokeIntrospectionEndpointAsync or InvokeTokenEndpointAsync.
            notification.TokenValidationParameters = new TokenValidationParameters
            {
                IssuerSigningKeys = Options.SigningCredentials.Select(credentials => credentials.Key)
                                    .Where(key => key is AsymmetricSecurityKey),

                NameClaimType    = OpenIdConnectConstants.Claims.Name,
                RoleClaimType    = OpenIdConnectConstants.Claims.Role,
                ValidIssuer      = Context.GetIssuer(Options),
                ValidateAudience = false,
                ValidateLifetime = false
            };

            await Provider.DeserializeIdentityToken(notification);

            if (notification.IsHandled || notification.Ticket != null)
            {
                notification.Ticket?.SetTokenUsage(OpenIdConnectConstants.TokenUsages.IdToken);

                return(notification.Ticket);
            }

            if (notification.SecurityTokenHandler == null)
            {
                throw new InvalidOperationException("A security token handler must be provided.");
            }

            SecurityToken   securityToken;
            ClaimsPrincipal principal;

            try
            {
                if (!notification.SecurityTokenHandler.CanReadToken(token))
                {
                    Logger.LogTrace("The identity token '{Token}' was rejected by the security token handler.", token);

                    return(null);
                }

                principal = notification.SecurityTokenHandler.ValidateToken(token, notification.TokenValidationParameters, out securityToken);
            }

            catch (Exception exception)
            {
                Logger.LogDebug("An exception occured while deserializing an identity token: {Exception}.", exception);

                return(null);
            }

            // Parameters stored in AuthenticationProperties are lost
            // when the identity token is serialized using a security token handler.
            // To mitigate that, they are inferred from the claims or the security token.
            var properties = new AuthenticationProperties
            {
                ExpiresUtc = securityToken.ValidTo,
                IssuedUtc  = securityToken.ValidFrom
            };

            var ticket = new AuthenticationTicket(principal, properties, Scheme.Name)
                         .SetAudiences(principal.FindAll(OpenIdConnectConstants.Claims.Audience).Select(claim => claim.Value))
                         .SetConfidentialityLevel(principal.GetClaim(OpenIdConnectConstants.Claims.ConfidentialityLevel))
                         .SetPresenters(principal.FindAll(OpenIdConnectConstants.Claims.AuthorizedParty).Select(claim => claim.Value))
                         .SetTokenId(principal.GetClaim(OpenIdConnectConstants.Claims.JwtId))
                         .SetTokenUsage(principal.GetClaim(OpenIdConnectConstants.Claims.TokenUsage));

            // Ensure that the received ticket is an identity token.
            if (!ticket.IsIdentityToken())
            {
                Logger.LogTrace("The received token was not an identity token: {Token}.", token);

                return(null);
            }

            Logger.LogTrace("The identity token '{Token}' was successfully validated using " +
                            "the specified security token handler: {Claims} ; {Properties}.",
                            token, ticket.Principal.Claims, ticket.Properties.Items);

            return(ticket);
        }
コード例 #2
0
 /// <summary>
 /// Represents an event called when deserializing an identity token.
 /// </summary>
 /// <param name="context">The context instance associated with this event.</param>
 /// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
 public virtual Task DeserializeIdentityToken(DeserializeIdentityTokenContext context)
 => OnDeserializeIdentityToken(context);