public async Task <EndpointResult> Generate( EndpointResult endpointResult, AuthorizationParameter authorizationParameter, ClaimsPrincipal claimsPrincipal, Client client, string?issuerName, CancellationToken cancellationToken) { var allowedTokenScopes = string.Empty; GrantedToken?grantedToken = null; var responses = authorizationParameter.ResponseType.ParseResponseTypes(); var generateIdToken = await GenerateIdTokenPayload( claimsPrincipal, authorizationParameter, issuerName, cancellationToken) .ConfigureAwait(false); if (generateIdToken is Option <JwtPayload> .Result p) { var idTokenPayload = p.Item; var payload = await GenerateUserInformationPayload( claimsPrincipal, authorizationParameter, cancellationToken) .ConfigureAwait(false); if (payload is Option <JwtPayload> .Error er) { return(EndpointResult.CreateBadRequestResult(er.Details)); } var userInformationPayload = (payload as Option <JwtPayload> .Result) !.Item; if (responses.Contains(ResponseTypeNames.Token)) { // 1. Generate an access token. var tokenScopes = authorizationParameter.Scope.ParseScopes(); allowedTokenScopes = string.Join(' ', tokenScopes); grantedToken = await _tokenStore.GetValidGrantedToken( _jwksStore, allowedTokenScopes, client.ClientId, cancellationToken, idTokenJwsPayload : userInformationPayload, userInfoJwsPayload : idTokenPayload) .ConfigureAwait(false) ?? await client.GenerateToken( _jwksStore, tokenScopes, issuerName, userInformationPayload, idTokenPayload, cancellationToken : cancellationToken, claimsPrincipal.Claims.Where( c => client.UserClaimsToIncludeInAuthToken.Any( r => r.IsMatch(c.Type))) .ToArray()) .ConfigureAwait(false); endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( StandardAuthorizationResponseNames.AccessTokenName, grantedToken.AccessToken) }; } AuthorizationCode?authorizationCode = null; var authorizationParameterClientId = authorizationParameter.ClientId; if (responses.Contains(ResponseTypeNames.Code)) // 2. Generate an authorization code. { var subject = claimsPrincipal.GetSubject() !; var assignedConsent = await _consentRepository .GetConfirmedConsents(subject, authorizationParameter, cancellationToken) .ConfigureAwait(false); if (assignedConsent != null) { if (authorizationParameterClientId == null || authorizationParameter.RedirectUrl == null || authorizationParameter.Scope == null) { throw new ArgumentException(Strings.MissingValues, nameof(authorizationParameter)); } // Insert a temporary authorization code // It will be used later to retrieve tha id_token or an access token. authorizationCode = new AuthorizationCode { Code = Id.Create(), RedirectUri = authorizationParameter.RedirectUrl, CreateDateTime = DateTimeOffset.UtcNow, ClientId = authorizationParameterClientId, Scopes = authorizationParameter.Scope, IdTokenPayload = idTokenPayload, UserInfoPayLoad = userInformationPayload }; endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( StandardAuthorizationResponseNames.AuthorizationCodeName, authorizationCode.Code) }; } } _jwtGenerator.FillInOtherClaimsIdentityTokenPayload( idTokenPayload, authorizationCode == null ? string.Empty : authorizationCode.Code, grantedToken == null ? string.Empty : grantedToken.AccessToken, client); if (grantedToken != null) // 3. Insert the stateful access token into the DB OR insert the access token into the caching. { if (authorizationParameterClientId == null || authorizationParameter.ResponseType == null) { throw new ArgumentException(Strings.MissingValues, nameof(authorizationParameter)); } await _tokenStore.AddToken(grantedToken, cancellationToken).ConfigureAwait(false); await _eventPublisher.Publish( new TokenGranted( Id.Create(), claimsPrincipal.GetSubject(), authorizationParameterClientId, allowedTokenScopes, authorizationParameter.ResponseType, DateTimeOffset.UtcNow)) .ConfigureAwait(false); } if (authorizationCode != null) // 4. Insert the authorization code into the caching. { if (client.RequirePkce) { authorizationCode = authorizationCode with { CodeChallenge = authorizationParameter.CodeChallenge ?? string.Empty, CodeChallengeMethod = authorizationParameter.CodeChallengeMethod ?? string.Empty }; } await _authorizationCodeStore.Add(authorizationCode, cancellationToken).ConfigureAwait(false); await _eventPublisher.Publish( new AuthorizationGranted( Id.Create(), claimsPrincipal.GetSubject(), authorizationParameterClientId !, DateTimeOffset.UtcNow)) .ConfigureAwait(false); } if (responses.Contains(ResponseTypeNames.IdToken)) { var idToken = await _clientStore.GenerateIdToken( authorizationParameterClientId !, idTokenPayload, _jwksStore, cancellationToken) .ConfigureAwait(false); endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( StandardAuthorizationResponseNames.IdTokenName, idToken) }; } if (!string.IsNullOrWhiteSpace(authorizationParameter.State)) { endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( StandardAuthorizationResponseNames.StateName, authorizationParameter.State) }; } var sessionState = GetSessionState( authorizationParameterClientId, authorizationParameter.OriginUrl, authorizationParameter.SessionId); if (sessionState != null) { endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( StandardAuthorizationResponseNames.SessionState, sessionState) }; } if (authorizationParameter.ResponseMode == ResponseModes.FormPost) { endpointResult = endpointResult with { Type = ActionResultType.RedirectToAction, RedirectInstruction = endpointResult.RedirectInstruction !.AddParameter( "redirect_uri", authorizationParameter.RedirectUrl?.AbsoluteUri) with { Action = SimpleAuthEndPoints.FormIndex } }; } // Set the response mode if (endpointResult.Type == ActionResultType.RedirectToCallBackUrl) { var responseMode = authorizationParameter.ResponseMode; if (responseMode == ResponseModes.None) { var responseTypes = authorizationParameter.ResponseType.ParseResponseTypes(); var authorizationFlow = responseTypes.GetAuthorizationFlow(authorizationParameter.State); switch (authorizationFlow) { case Option <AuthorizationFlow> .Error error: return(EndpointResult.CreateBadRequestResult(error.Details)); case Option <AuthorizationFlow> .Result r: responseMode = CoreConstants.MappingAuthorizationFlowAndResponseModes[r.Item]; break; } } endpointResult = endpointResult with { RedirectInstruction = endpointResult.RedirectInstruction !with { ResponseMode = responseMode } }; } return(endpointResult); } var e = generateIdToken as Option <JwtPayload> .Error; return(EndpointResult.CreateBadRequestResult(e !.Details)); }