Esempio n. 1
0
        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));
        }