private async Task <AuthenticationTicket> InvokeTokenEndpointAuthorizationCodeGrantAsync( OAuthValidateTokenRequestContext validatingContext, DateTimeOffset currentUtc) { TokenEndpointRequest tokenEndpointRequest = validatingContext.TokenRequest; var authorizationCodeContext = new AuthenticationTokenReceiveContext( Context, Options.AuthorizationCodeFormat, tokenEndpointRequest.AuthorizationCodeGrant.Code); await Options.AuthorizationCodeProvider.ReceiveAsync(authorizationCodeContext); AuthenticationTicket ticket = authorizationCodeContext.Ticket; if (ticket == null) { _logger.WriteError("invalid authorization code"); validatingContext.SetError(Constants.Errors.InvalidGrant); return(null); } if (!ticket.Properties.ExpiresUtc.HasValue || ticket.Properties.ExpiresUtc < currentUtc) { _logger.WriteError("expired authorization code"); validatingContext.SetError(Constants.Errors.InvalidGrant); return(null); } string clientId; if (!ticket.Properties.Dictionary.TryGetValue(Constants.Extra.ClientId, out clientId) || !String.Equals(clientId, validatingContext.ClientContext.ClientId, StringComparison.Ordinal)) { _logger.WriteError("authorization code does not contain matching client_id"); validatingContext.SetError(Constants.Errors.InvalidGrant); return(null); } string redirectUri; if (ticket.Properties.Dictionary.TryGetValue(Constants.Extra.RedirectUri, out redirectUri)) { ticket.Properties.Dictionary.Remove(Constants.Extra.RedirectUri); if (!String.Equals(redirectUri, tokenEndpointRequest.AuthorizationCodeGrant.RedirectUri, StringComparison.Ordinal)) { _logger.WriteError("authorization code does not contain matching redirect_uri"); validatingContext.SetError(Constants.Errors.InvalidGrant); return(null); } } await Options.Provider.ValidateTokenRequest(validatingContext); var grantContext = new OAuthGrantAuthorizationCodeContext( Context, Options, ticket); if (validatingContext.IsValidated) { await Options.Provider.GrantAuthorizationCode(grantContext); } return(ReturnOutcome( validatingContext, grantContext, grantContext.Ticket, Constants.Errors.InvalidGrant)); }
/// <summary> /// Called when a request to the Token endpoint arrives with a "grant_type" of "authorization_code". This occurs after the Authorize /// endpoint as redirected the user-agent back to the client with a "code" parameter, and the client is exchanging that for an "access_token". /// The claims and properties /// associated with the authorization code are present in the context.Ticket. The application must call context.Validated to instruct the Authorization /// Server middleware to issue an access token based on those claims and properties. The call to context.Validated may be given a different /// AuthenticationTicket or ClaimsIdentity in order to control which information flows from authorization code to access token. /// The default behavior when using the OAuthAuthorizationServerProvider is to flow information from the authorization code to /// the access token unmodified. /// See also http://tools.ietf.org/html/rfc6749#section-4.1.3 /// </summary> /// <param name="context">The context of the event carries information in and results out.</param> /// <returns>Task to enable asynchronous execution</returns> public virtual Task GrantAuthorizationCode(OAuthGrantAuthorizationCodeContext context) { return(OnGrantAuthorizationCode.Invoke(context)); }