/// <summary> /// Invoked when a token is to be validated, before final processing. /// </summary> public virtual Task ValidateToken(ValidateTokenContext context) => OnValidateToken(context);
protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { var context = new RetrieveTokenContext(Context, Options); await Options.Events.RetrieveToken(context); if (context.Handled) { Logger.LogInformation("The default authentication handling was skipped from user code."); return(context.Ticket); } var token = context.Token; if (string.IsNullOrEmpty(token)) { // Try to retrieve the access token from the authorization header. var header = Request.Headers[OAuthValidationConstants.Headers.Authorization]; if (string.IsNullOrEmpty(header)) { Logger.LogDebug("Authentication was skipped because no bearer token was received."); return(null); } // Ensure that the authorization header contains the mandatory "Bearer" scheme. // See https://tools.ietf.org/html/rfc6750#section-2.1 if (!header.StartsWith(OAuthValidationConstants.Schemes.Bearer + ' ', StringComparison.OrdinalIgnoreCase)) { Logger.LogDebug("Authentication was skipped because an incompatible " + "scheme was used in the 'Authorization' header."); return(null); } // Extract the token from the authorization header. token = header.Substring(OAuthValidationConstants.Schemes.Bearer.Length + 1).Trim(); if (string.IsNullOrEmpty(token)) { Logger.LogDebug("Authentication was skipped because the bearer token " + "was missing from the 'Authorization' header."); return(null); } } // Try to unprotect the token and return an error // if the ticket can't be decrypted or validated. var ticket = await CreateTicketAsync(token); if (ticket == null) { Logger.LogError("Authentication failed because the access token was invalid."); Context.Set(typeof(OAuthValidationError).FullName, new OAuthValidationError { Error = OAuthValidationConstants.Errors.InvalidToken, ErrorDescription = "The access token is not valid." }); return(null); } // Ensure that the authentication ticket is still valid. if (ticket.Properties.ExpiresUtc.HasValue && ticket.Properties.ExpiresUtc.Value < Options.SystemClock.UtcNow) { Logger.LogError("Authentication failed because the access token was expired."); Context.Set(typeof(OAuthValidationError).FullName, new OAuthValidationError { Error = OAuthValidationConstants.Errors.InvalidToken, ErrorDescription = "The access token is no longer valid." }); return(null); } // Ensure that the access token was issued // to be used with this resource server. if (!ValidateAudience(ticket)) { Logger.LogError("Authentication failed because the access token " + "was not valid for this resource server."); Context.Set(typeof(OAuthValidationError).FullName, new OAuthValidationError { Error = OAuthValidationConstants.Errors.InvalidToken, ErrorDescription = "The access token is not valid for this resource server." }); return(null); } var notification = new ValidateTokenContext(Context, Options, ticket); await Options.Events.ValidateToken(notification); // Allow the application code to replace the ticket // reference from the ValidateToken event. return(notification.Ticket); }