Esempio n. 1
0
        public async Task <EndpointResult> ProcessRedirection(
            AuthorizationParameter authorizationParameter,
            string?code,
            string subject,
            Claim[] claims,
            string?issuerName,
            CancellationToken cancellationToken)
        {
            var client = authorizationParameter.ClientId == null
                ? null
                : await _clientRepository.GetById(authorizationParameter.ClientId, cancellationToken)
                         .ConfigureAwait(false);

            if (client == null)
            {
                throw new InvalidOperationException(SharedStrings.TheClientDoesntExist);
            }

            // Redirect to the consent page if the prompt parameter contains "consent"
            EndpointResult result;
            var            prompts = authorizationParameter.Prompt.ParsePrompts();

            if (prompts.Contains(PromptParameters.Consent) && code != null)
            {
                return(EndpointResult.CreateAnEmptyActionResultWithRedirection(
                           SimpleAuthEndPoints.ConsentIndex,
                           new Parameter("code", code)));
            }

            var assignedConsent = await _consentRepository
                                  .GetConfirmedConsents(subject, authorizationParameter, cancellationToken)
                                  .ConfigureAwait(false);

            // If there's already one consent then redirect to the callback
            if (assignedConsent != null)
            {
                var claimsIdentity  = new ClaimsIdentity(claims, "SimpleAuth");
                var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
                result = await _generateAuthorizationResponse.Generate(
                    EndpointResult.CreateAnEmptyActionResultWithRedirectionToCallBackUrl(),
                    authorizationParameter,
                    claimsPrincipal,
                    client,
                    issuerName,
                    cancellationToken)
                         .ConfigureAwait(false);

                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode != ResponseModes.None)
                {
                    return(result with
                    {
                        RedirectInstruction = result.RedirectInstruction !with {
                            ResponseMode = responseMode
                        }
                    });
                }

                var responseTypes     = authorizationParameter.ResponseType.ParseResponseTypes();
                var authorizationFlow = GetAuthorizationFlow(authorizationParameter.State, responseTypes);
                switch (authorizationFlow)
                {
                case Option <AuthorizationFlow> .Error e:
                    return(EndpointResult.CreateBadRequestResult(e.Details));

                case Option <AuthorizationFlow> .Result r:
                    responseMode = GetResponseMode(r.Item);
                    break;
                }

                return(result with
                {
                    RedirectInstruction = result.RedirectInstruction !with {
                        ResponseMode = responseMode
                    }
                });
            }

            // If there's no consent & there's no consent prompt then redirect to the consent screen.
            return(EndpointResult.CreateAnEmptyActionResultWithRedirection(
                       SimpleAuthEndPoints.ConsentIndex,
                       new Parameter("code", code ?? "")));
        }
Esempio n. 2
0
        /// <summary>
        /// Fetch the scopes and client name from the ClientRepository and the parameter
        /// Those information are used to create the consent screen.
        /// </summary>
        /// <param name="authorizationParameter">Authorization code grant type parameter.</param>
        /// <param name="claimsPrincipal"></param>
        /// <param name="issuerName"></param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the async operation.</param>
        /// <returns>Action resultKind.</returns>
        public async Task <DisplayContentResult> Execute(
            AuthorizationParameter authorizationParameter,
            ClaimsPrincipal claimsPrincipal,
            string issuerName,
            CancellationToken cancellationToken)
        {
            var client = authorizationParameter.ClientId == null
                ? null
                : await _clientRepository.GetById(authorizationParameter.ClientId, cancellationToken)
                         .ConfigureAwait(false);

            if (client == null)
            {
                return(new DisplayContentResult(
                           EndpointResult.CreateBadRequestResult(
                               new ErrorDetails
                {
                    Title = ErrorCodes.InvalidRequest,
                    Detail = string.Format(Strings.ClientIsNotValid, authorizationParameter.ClientId),
                    Status = HttpStatusCode.BadRequest
                })));
            }

            EndpointResult endpointResult;
            var            subject         = claimsPrincipal.GetSubject() !;
            var            assignedConsent = await _consentRepository
                                             .GetConfirmedConsents(subject, authorizationParameter, cancellationToken)
                                             .ConfigureAwait(false);

            // If there's already a consent then redirect to the callback
            if (assignedConsent != null)
            {
                endpointResult = await _generateAuthorizationResponse.Generate(
                    EndpointResult.CreateAnEmptyActionResultWithRedirectionToCallBackUrl(),
                    authorizationParameter,
                    claimsPrincipal,
                    client,
                    issuerName,
                    cancellationToken)
                                 .ConfigureAwait(false);

                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode == ResponseModes.None)
                {
                    var responseTypes     = authorizationParameter.ResponseType.ParseResponseTypes();
                    var authorizationFlow = GetAuthorizationFlow(responseTypes, authorizationParameter.State);
                    switch (authorizationFlow)
                    {
                    case Option <AuthorizationFlow> .Error e:
                        return(new DisplayContentResult(EndpointResult.CreateBadRequestResult(e.Details)));

                    case Option <AuthorizationFlow> .Result r:
                        responseMode = GetResponseMode(r.Item);
                        break;
                    }
                }

                endpointResult = endpointResult with {
                    RedirectInstruction = endpointResult.RedirectInstruction !with {
                        ResponseMode = responseMode
                    }
                };
                return(new DisplayContentResult(endpointResult));
            }

            ICollection <string> allowedClaims = Array.Empty <string>();
            ICollection <Scope>  allowedScopes = Array.Empty <Scope>();
            var claimsParameter = authorizationParameter.Claims;

            if (claimsParameter.IsAnyIdentityTokenClaimParameter() || claimsParameter.IsAnyUserInfoClaimParameter())
            {
                allowedClaims = claimsParameter.GetClaimNames();
            }
            else
            {
                allowedScopes =
                    (await GetScopes(authorizationParameter.Scope !, cancellationToken).ConfigureAwait(false))
                    .Where(s => s.IsDisplayedInConsent)
                    .ToList();
            }

            endpointResult = EndpointResult.CreateAnEmptyActionResultWithOutput();
            return(new DisplayContentResult(client, allowedScopes, allowedClaims, endpointResult));
        }
Esempio n. 3
0
        /// <summary>
        /// This method is executed when the user confirm the consent
        /// 1). If there's already consent confirmed in the past by the resource owner
        /// 1).* then we generate an authorization code and redirects to the callback.
        /// 2). If there's no consent then we insert it and the authorization code is returned
        ///  2°.* to the callback url.
        /// </summary>
        /// <param name="authorizationParameter">Authorization code grant-type</param>
        /// <param name="claimsPrincipal">Resource owner's claims</param>
        /// <param name="issuerName"></param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the async operation.</param>
        /// <returns>Redirects the authorization code to the callback.</returns>
        public async Task <EndpointResult> Execute(
            AuthorizationParameter authorizationParameter,
            ClaimsPrincipal claimsPrincipal,
            string issuerName,
            CancellationToken cancellationToken)
        {
            var client = authorizationParameter.ClientId == null
                ? null
                : await _clientRepository.GetById(authorizationParameter.ClientId, cancellationToken)
                         .ConfigureAwait(false);

            if (client == null)
            {
                throw new InvalidOperationException(
                          string.Format(
                              Strings.TheClientIdDoesntExist,
                              authorizationParameter.ClientId));
            }

            var subject         = claimsPrincipal.GetSubject() !;
            var assignedConsent = await _consentRepository
                                  .GetConfirmedConsents(subject, authorizationParameter, cancellationToken)
                                  .ConfigureAwait(false);

            // Insert a new consent.
            if (assignedConsent == null)
            {
                var claimsParameter = authorizationParameter.Claims;
                if (claimsParameter.IsAnyIdentityTokenClaimParameter() || claimsParameter.IsAnyUserInfoClaimParameter())
                {
                    // A consent can be given to a set of claims
                    assignedConsent = new Consent
                    {
                        Id         = Id.Create(),
                        ClientId   = client.ClientId,
                        ClientName = client.ClientName,
                        Subject    = subject,
                        Claims     = claimsParameter.GetClaimNames()
                    };
                }
                else
                {
                    // A consent can be given to a set of scopes
                    assignedConsent = new Consent
                    {
                        Id            = Id.Create(),
                        ClientId      = client.ClientId,
                        ClientName    = client.ClientName,
                        GrantedScopes =
                            authorizationParameter.Scope == null
                                ? Array.Empty <string>()
                                : (await GetScopes(authorizationParameter.Scope, cancellationToken)
                                   .ConfigureAwait(false)).ToArray(),
                        Subject = subject,
                    };
                }

                // A consent can be given to a set of claims
                await _consentRepository.Insert(assignedConsent, cancellationToken).ConfigureAwait(false);

                await _eventPublisher.Publish(
                    new ConsentAccepted(
                        Id.Create(),
                        subject,
                        client.ClientId,
                        assignedConsent.GrantedScopes,
                        DateTimeOffset.UtcNow))
                .ConfigureAwait(false);
            }

            var result = await _generateAuthorizationResponse.Generate(
                EndpointResult.CreateAnEmptyActionResultWithRedirectionToCallBackUrl(),
                authorizationParameter,
                claimsPrincipal,
                client,
                issuerName,
                cancellationToken)
                         .ConfigureAwait(false);

            // If redirect to the callback and the response mode has not been set.
            if (result.Type != ActionResultType.RedirectToCallBackUrl)
            {
                return(result);
            }

            var responseMode = authorizationParameter.ResponseMode;

            if (responseMode == ResponseModes.None)
            {
                var responseTypes     = authorizationParameter.ResponseType.ParseResponseTypes();
                var authorizationFlow = GetAuthorizationFlow(responseTypes, authorizationParameter.State);
                switch (authorizationFlow)
                {
                case Option <AuthorizationFlow> .Error e:
                    return(EndpointResult.CreateBadRequestResult(e.Details));

                case Option <AuthorizationFlow> .Result r:
                    responseMode = GetResponseMode(r.Item);
                    break;
                }
            }

            result = result with
            {
                RedirectInstruction = result.RedirectInstruction !with {
                    ResponseMode = responseMode
                }
            };

            return(result);
        }