private async Task <Option <GrantedToken> > HandleApprovedRequest(
            string issuerName,
            DeviceAuthorizationData authRequest,
            CancellationToken cancellationToken)
        {
            var scopes       = string.Join(" ", authRequest.Scopes);
            var grantedToken = await _tokenStore.GetValidGrantedToken(_jwksStore, scopes, authRequest.ClientId, cancellationToken)
                               //idTokenJwsPayload: result.AuthCode.IdTokenPayload,
                               //userInfoJwsPayload: result.AuthCode.UserInfoPayLoad)
                               .ConfigureAwait(false);

            if (grantedToken == null)
            {
                var client = await _clientStore.GetById(authRequest.ClientId, cancellationToken).ConfigureAwait(false);

                grantedToken = await client !.GenerateToken(
                    _jwksStore,
                    authRequest.Scopes,
                    issuerName,
                    //result.AuthCode.UserInfoPayLoad,
                    //result.AuthCode.IdTokenPayload,
                    cancellationToken: cancellationToken
                    //result.AuthCode.IdTokenPayload?.Claims.Where(
                    //        c => result.Client.UserClaimsToIncludeInAuthToken.Any(r => r.IsMatch(c.Type)))
                    //    .ToArray()
                    //?? Array.Empty<Claim>())
                    )
                               .ConfigureAwait(false);
                await _eventPublisher.Publish(
                    new TokenGranted(
                        Id.Create(),
                        grantedToken.UserInfoPayLoad?.Sub,
                        authRequest.ClientId,
                        string.Join(" ", authRequest.Scopes),
                        GrantTypes.AuthorizationCode,
                        DateTimeOffset.UtcNow))
                .ConfigureAwait(false);

                // Fill-in the id-token
                if (grantedToken.IdTokenPayLoad != null)
                {
                    grantedToken = grantedToken with
                    {
                        IdTokenPayLoad = JwtGenerator.UpdatePayloadDate(grantedToken.IdTokenPayLoad, client !.TokenLifetime),
                        IdToken        = await client.GenerateIdToken(grantedToken.IdTokenPayLoad, _jwksStore, cancellationToken)
                                         .ConfigureAwait(false)
                    };
                }

                await _tokenStore.AddToken(grantedToken !, cancellationToken).ConfigureAwait(false);
            }

            return(grantedToken !);
        }
    }
示例#2
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));
        }
        public async Task <Option <GrantedToken> > Execute(
            AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter,
            AuthenticationHeaderValue?authenticationHeaderValue,
            X509Certificate2?certificate,
            string issuerName,
            CancellationToken cancellationToken)
        {
            var option = await ValidateParameter(
                authorizationCodeGrantTypeParameter,
                authenticationHeaderValue,
                certificate,
                issuerName,
                cancellationToken)
                         .ConfigureAwait(false);

            if (option is Option <ValidationResult> .Error e)
            {
                return(e.Details);
            }

            var result = ((Option <ValidationResult> .Result)option).Item;

            // 1. Invalidate the authorization code by removing it !
            await _authorizationCodeStore.Remove(result.AuthCode.Code, cancellationToken).ConfigureAwait(false);

            var grantedToken = await _tokenStore.GetValidGrantedToken(
                _jwksStore,
                result.AuthCode.Scopes,
                result.AuthCode.ClientId,
                cancellationToken,
                idTokenJwsPayload : result.AuthCode.IdTokenPayload,
                userInfoJwsPayload : result.AuthCode.UserInfoPayLoad)
                               .ConfigureAwait(false);

            if (grantedToken == null)
            {
                grantedToken = await result.Client.GenerateToken(
                    _jwksStore,
                    result.AuthCode.Scopes.Split(' '),
                    issuerName,
                    result.AuthCode.UserInfoPayLoad,
                    result.AuthCode.IdTokenPayload,
                    cancellationToken,
                    result.AuthCode.IdTokenPayload?.Claims.Where(
                        c => result.Client.UserClaimsToIncludeInAuthToken.Any(r => r.IsMatch(c.Type)))
                    .ToArray()
                    ?? Array.Empty <Claim>())
                               .ConfigureAwait(false);

                await _eventPublisher.Publish(
                    new TokenGranted(
                        Id.Create(),
                        grantedToken.UserInfoPayLoad?.Sub,
                        result.AuthCode.ClientId,
                        result.AuthCode.Scopes,
                        GrantTypes.AuthorizationCode,
                        DateTimeOffset.UtcNow))
                .ConfigureAwait(false);

                // Fill-in the id-token
                if (grantedToken.IdTokenPayLoad != null)
                {
                    grantedToken = grantedToken with
                    {
                        IdTokenPayLoad =
                            JwtGenerator.UpdatePayloadDate(
                                grantedToken.IdTokenPayLoad,
                                result.Client.TokenLifetime),
                        IdToken = await result !.Client.GenerateIdToken(
                            grantedToken.IdTokenPayLoad,
                            _jwksStore,
                            cancellationToken)
                                  .ConfigureAwait(false)
                    };
                }

                await _tokenStore.AddToken(grantedToken !, cancellationToken).ConfigureAwait(false);
            }

            return(grantedToken !);
        }