public async Task <ActionResult> ProcessRedirection(
            AuthorizationParameter authorizationParameter,
            string code,
            string subject,
            List <Claim> claims, string issuerName)
        {
            if (authorizationParameter == null)
            {
                throw new ArgumentNullException(nameof(authorizationParameter));
            }

            var client = await _clientRepository.GetClientByIdAsync(authorizationParameter.ClientId);

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

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

            if (prompts != null &&
                prompts.Contains(PromptParameter.consent))
            {
                result = _actionResultFactory.CreateAnEmptyActionResultWithRedirection();
                result.RedirectInstruction.Action = IdentityServerEndPoints.ConsentIndex;
                result.RedirectInstruction.AddParameter("code", code);
                return(result);
            }

            var assignedConsent = await _consentHelper.GetConfirmedConsentsAsync(subject, authorizationParameter);

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

                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode == ResponseMode.None)
                {
                    var responseTypes     = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);
                    var authorizationFlow = GetAuthorizationFlow(responseTypes, authorizationParameter.State);
                    responseMode = GetResponseMode(authorizationFlow);
                }

                result.RedirectInstruction.ResponseMode = responseMode;
                return(result);
            }

            // If there's no consent & there's no consent prompt then redirect to the consent screen.
            result = _actionResultFactory.CreateAnEmptyActionResultWithRedirection();
            result.RedirectInstruction.Action = IdentityServerEndPoints.ConsentIndex;
            result.RedirectInstruction.AddParameter("code", code);
            return(result);
        }
        public async Task <ActionResult> GetAuthorization(AuthorizationParameter parameter, IPrincipal claimsPrincipal)
        {
            var processId = Guid.NewGuid().ToString();

            _eventPublisher.Publish(new AuthorizationRequestReceived(Guid.NewGuid().ToString(), processId, _payloadSerializer.GetPayload(parameter), 0));
            try
            {
                var client = await _authorizationCodeGrantTypeParameterValidator.ValidateAsync(parameter);

                ActionResult actionResult = null;
                _simpleIdentityServerEventSource.StartAuthorization(parameter.ClientId,
                                                                    parameter.ResponseType,
                                                                    parameter.Scope,
                                                                    parameter.Claims == null ? string.Empty : parameter.Claims.ToString());
                if (client.RequirePkce && (string.IsNullOrWhiteSpace(parameter.CodeChallenge) || parameter.CodeChallengeMethod == null))
                {
                    throw new IdentityServerException(ErrorCodes.InvalidRequestCode, string.Format(ErrorDescriptions.TheClientRequiresPkce, parameter.ClientId));
                }

                var responseTypes     = _parameterParserHelper.ParseResponseTypes(parameter.ResponseType);
                var authorizationFlow = _authorizationFlowHelper.GetAuthorizationFlow(responseTypes, parameter.State);
                switch (authorizationFlow)
                {
                case AuthorizationFlow.AuthorizationCodeFlow:
                    actionResult = await _getAuthorizationCodeOperation.Execute(parameter, claimsPrincipal, client);

                    break;

                case AuthorizationFlow.ImplicitFlow:
                    actionResult = await _getTokenViaImplicitWorkflowOperation.Execute(parameter, claimsPrincipal, client);

                    break;

                case AuthorizationFlow.HybridFlow:
                    actionResult = await _getAuthorizationCodeAndTokenViaHybridWorkflowOperation.Execute(parameter, claimsPrincipal, client);

                    break;
                }

                if (actionResult != null)
                {
                    var actionTypeName = Enum.GetName(typeof(TypeActionResult), actionResult.Type);
                    var actionName     = string.Empty;
                    if (actionResult.Type == TypeActionResult.RedirectToAction)
                    {
                        var actionEnum = actionResult.RedirectInstruction.Action;
                        actionName = Enum.GetName(typeof(IdentityServerEndPoints), actionEnum);
                    }

                    var serializedParameters = actionResult.RedirectInstruction == null || actionResult.RedirectInstruction.Parameters == null ? String.Empty :
                                               actionResult.RedirectInstruction.Parameters.SerializeWithJavascript();
                    _simpleIdentityServerEventSource.EndAuthorization(actionTypeName,
                                                                      actionName,
                                                                      serializedParameters);
                }

                _eventPublisher.Publish(new AuthorizationGranted(Guid.NewGuid().ToString(), processId, _payloadSerializer.GetPayload(actionResult), 1));
                actionResult.ProcessId = processId;
                return(actionResult);
            }
            catch (IdentityServerException ex)
            {
                _eventPublisher.Publish(new OpenIdErrorReceived(Guid.NewGuid().ToString(), processId, ex.Code, ex.Message, 1));
                throw;
            }
        }
Exemplo 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>
        /// <returns>Redirects the authorization code to the callback.</returns>
        public async Task <ActionResult> Execute(
            AuthorizationParameter authorizationParameter,
            ClaimsPrincipal claimsPrincipal)
        {
            if (authorizationParameter == null)
            {
                throw new ArgumentNullException(nameof(authorizationParameter));
            }

            if (claimsPrincipal == null ||
                claimsPrincipal.Identity == null)
            {
                throw new ArgumentNullException(nameof(claimsPrincipal));
            }

            var client = await _clientRepository.GetClientByIdAsync(authorizationParameter.ClientId);

            if (client == null)
            {
                throw new InvalidOperationException(string.Format("the client id {0} doesn't exist",
                                                                  authorizationParameter.ClientId));
            }

            var subject = claimsPrincipal.GetSubject();

            Common.Models.Consent assignedConsent = await _consentHelper.GetConfirmedConsentsAsync(subject, authorizationParameter);

            // 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 Common.Models.Consent
                    {
                        Client        = client,
                        ResourceOwner = await _authenticateResourceOwnerService.AuthenticateResourceOwnerAsync(subject),
                        Claims        = claimsParameter.GetClaimNames()
                    };
                }
                else
                {
                    // A consent can be given to a set of scopes
                    assignedConsent = new Common.Models.Consent
                    {
                        Client        = client,
                        GrantedScopes = (await GetScopes(authorizationParameter.Scope)).ToList(),
                        ResourceOwner = await _authenticateResourceOwnerService.AuthenticateResourceOwnerAsync(subject),
                    };
                }

                // A consent can be given to a set of claims
                await _consentRepository.InsertAsync(assignedConsent);

                _simpleIdentityServerEventSource.GiveConsent(subject,
                                                             authorizationParameter.ClientId,
                                                             assignedConsent.Id);
            }

            var result = _actionResultFactory.CreateAnEmptyActionResultWithRedirectionToCallBackUrl();
            await _generateAuthorizationResponse.ExecuteAsync(result, authorizationParameter, claimsPrincipal, client);

            // If redirect to the callback and the responde mode has not been set.
            if (result.Type == TypeActionResult.RedirectToCallBackUrl)
            {
                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode == ResponseMode.None)
                {
                    var responseTypes     = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);
                    var authorizationFlow = GetAuthorizationFlow(responseTypes, authorizationParameter.State);
                    responseMode = GetResponseMode(authorizationFlow);
                }

                result.RedirectInstruction.ResponseMode = responseMode;
            }

            return(result);
        }
        public async Task <ActionResult> ProcessAsync(AuthorizationParameter authorizationParameter, ClaimsPrincipal claimsPrincipal, Core.Common.Models.Client client, string issuerName)
        {
            if (authorizationParameter == null)
            {
                throw new ArgumentNullException(nameof(authorizationParameter));
            }

            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            var     endUserIsAuthenticated = IsAuthenticated(claimsPrincipal);
            Consent confirmedConsent       = null;

            if (endUserIsAuthenticated)
            {
                confirmedConsent = await GetResourceOwnerConsent(claimsPrincipal, authorizationParameter);
            }

            var serializedAuthorizationParameter = authorizationParameter.SerializeWithJavascript();

            _oauthEventSource.StartProcessingAuthorizationRequest(serializedAuthorizationParameter);
            ActionResult result  = null;
            var          prompts = _parameterParserHelper.ParsePrompts(authorizationParameter.Prompt);

            if (prompts == null || !prompts.Any())
            {
                prompts = new List <PromptParameter>();
                if (!endUserIsAuthenticated)
                {
                    prompts.Add(PromptParameter.login);
                }
                else
                {
                    if (confirmedConsent == null)
                    {
                        prompts.Add(PromptParameter.consent);
                    }
                    else
                    {
                        prompts.Add(PromptParameter.none);
                    }
                }
            }

            var redirectionUrls = _clientValidator.GetRedirectionUrls(client, authorizationParameter.RedirectUrl);

            if (!redirectionUrls.Any())
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.RedirectUrlIsNotValid, authorizationParameter.RedirectUrl),
                          authorizationParameter.State);
            }

            var scopeValidationResult = _scopeValidator.Check(authorizationParameter.Scope, client);

            if (!scopeValidationResult.IsValid)
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidScope,
                          scopeValidationResult.ErrorMessage,
                          authorizationParameter.State);
            }

            if (!scopeValidationResult.Scopes.Contains(Constants.StandardScopes.OpenId.Name))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidScope,
                          string.Format(ErrorDescriptions.TheScopesNeedToBeSpecified, Constants.StandardScopes.OpenId.Name),
                          authorizationParameter.State);
            }

            var responseTypes = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);

            if (!responseTypes.Any())
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.MissingParameter, Constants.StandardAuthorizationRequestParameterNames.ResponseTypeName),
                          authorizationParameter.State);
            }

            if (!_clientValidator.CheckResponseTypes(client, responseTypes.ToArray()))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.TheClientDoesntSupportTheResponseType,
                                        authorizationParameter.ClientId,
                                        string.Join(",", responseTypes)),
                          authorizationParameter.State);
            }

            // Check if the user connection is still valid.
            if (endUserIsAuthenticated && !authorizationParameter.MaxAge.Equals(default(double)))
            {
                var authenticationDateTimeClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.AuthenticationInstant);
                if (authenticationDateTimeClaim != null)
                {
                    var maxAge                 = authorizationParameter.MaxAge;
                    var currentDateTimeUtc     = DateTimeOffset.UtcNow.ConvertToUnixTimestamp();
                    var authenticationDateTime = long.Parse(authenticationDateTimeClaim.Value);
                    if (maxAge < currentDateTimeUtc - authenticationDateTime)
                    {
                        result = _actionResultFactory.CreateAnEmptyActionResultWithRedirection();
                        result.RedirectInstruction.Action = IdentityServerEndPoints.AuthenticateIndex;
                    }
                }
            }

            if (result == null)
            {
                result = ProcessPromptParameters(
                    prompts,
                    claimsPrincipal,
                    authorizationParameter,
                    confirmedConsent);

                await ProcessIdTokenHint(result,
                                         authorizationParameter,
                                         prompts,
                                         claimsPrincipal,
                                         issuerName);
            }

            var actionTypeName = Enum.GetName(typeof(TypeActionResult), result.Type);
            var actionName     = result.RedirectInstruction == null
                ? string.Empty
                : Enum.GetName(typeof(IdentityServerEndPoints), result.RedirectInstruction.Action);

            _oauthEventSource.EndProcessingAuthorizationRequest(
                serializedAuthorizationParameter,
                actionTypeName,
                actionName);

            return(result);
        }
        /// <returns>Action result.</returns>
        public async Task <DisplayContentResult> Execute(AuthorizationParameter authorizationParameter, string authenticatedSubject, string issuerName)
        {
            if (authorizationParameter == null)
            {
                throw new ArgumentNullException(nameof(authorizationParameter));
            }

            if (string.IsNullOrWhiteSpace(authenticatedSubject))
            {
                throw new ArgumentNullException(nameof(authenticatedSubject));
            }

            var client = await _clientRepository.GetClientByIdAsync(authorizationParameter.ClientId);

            if (client == null)
            {
                throw new IdentityServerExceptionWithState(ErrorCodes.InvalidRequestCode,
                                                           string.Format(ErrorDescriptions.ClientIsNotValid, authorizationParameter.ClientId),
                                                           authorizationParameter.State);
            }

            ActionResult actionResult;
            var          assignedConsent = await _consentHelper.GetConfirmedConsentsAsync(authenticatedSubject, authorizationParameter).ConfigureAwait(false);

            // If there's already a consent then redirect to the callback
            if (assignedConsent != null)
            {
                actionResult = _actionResultFactory.CreateAnEmptyActionResultWithRedirectionToCallBackUrl();
                await _generateAuthorizationResponse.ExecuteAsync(actionResult, authorizationParameter, client, issuerName, authenticatedSubject).ConfigureAwait(false);

                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode == ResponseMode.None)
                {
                    var responseTypes     = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);
                    var authorizationFlow = GetAuthorizationFlow(responseTypes, authorizationParameter.State);
                    responseMode = GetResponseMode(authorizationFlow);
                }

                actionResult.RedirectInstruction.ResponseMode = responseMode;
                return(new DisplayContentResult
                {
                    ActionResult = actionResult
                });
            }

            ICollection <string> allowedClaims = null;
            ICollection <Scope>  allowedScopes = null;
            var claimsParameter = authorizationParameter.Claims;

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

            actionResult = _actionResultFactory.CreateAnEmptyActionResultWithOutput();
            return(new DisplayContentResult
            {
                AllowedClaims = allowedClaims,
                Scopes = allowedScopes,
                ActionResult = actionResult,
                Client = client
            });
        }
        public async Task ExecuteAsync(ActionResult actionResult, AuthorizationParameter authorizationParameter, ClaimsPrincipal claimsPrincipal, Client client)
        {
            if (actionResult == null || actionResult.RedirectInstruction == null)
            {
                throw new ArgumentNullException(nameof(actionResult));
            }
            ;
            if (authorizationParameter == null)
            {
                throw new ArgumentNullException(nameof(authorizationParameter));
            }

            if (claimsPrincipal == null)
            {
                throw new ArgumentNullException(nameof(claimsPrincipal));
            }

            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }

            var               newAccessTokenGranted       = false;
            var               allowedTokenScopes          = string.Empty;
            GrantedToken      grantedToken                = null;
            var               newAuthorizationCodeGranted = false;
            AuthorizationCode authorizationCode           = null;

            _simpleIdentityServerEventSource.StartGeneratingAuthorizationResponseToClient(authorizationParameter.ClientId,
                                                                                          authorizationParameter.ResponseType);
            var responses      = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);
            var idTokenPayload = await GenerateIdTokenPayload(claimsPrincipal, authorizationParameter);

            var userInformationPayload = await GenerateUserInformationPayload(claimsPrincipal, authorizationParameter);

            if (responses.Contains(ResponseType.token)) // 1. Generate an access token.
            {
                if (!string.IsNullOrWhiteSpace(authorizationParameter.Scope))
                {
                    allowedTokenScopes = string.Join(" ", _parameterParserHelper.ParseScopes(authorizationParameter.Scope));
                }


                grantedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync(allowedTokenScopes, client.ClientId,
                                                                                   userInformationPayload, idTokenPayload);

                if (grantedToken == null)
                {
                    grantedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync(client, allowedTokenScopes,
                                                                                         userInformationPayload, idTokenPayload);

                    newAccessTokenGranted = true;
                }

                actionResult.RedirectInstruction.AddParameter(Constants.StandardAuthorizationResponseNames.AccessTokenName,
                                                              grantedToken.AccessToken);
            }

            if (responses.Contains(ResponseType.code)) // 2. Generate an authorization code.
            {
                var subject         = claimsPrincipal == null ? string.Empty : claimsPrincipal.GetSubject();
                var assignedConsent = await _consentHelper.GetConfirmedConsentsAsync(subject, authorizationParameter);

                if (assignedConsent != null)
                {
                    // Insert a temporary authorization code
                    // It will be used later to retrieve tha id_token or an access token.
                    authorizationCode = new AuthorizationCode
                    {
                        Code            = Guid.NewGuid().ToString(),
                        RedirectUri     = authorizationParameter.RedirectUrl,
                        CreateDateTime  = DateTime.UtcNow,
                        ClientId        = authorizationParameter.ClientId,
                        Scopes          = authorizationParameter.Scope,
                        IdTokenPayload  = idTokenPayload,
                        UserInfoPayLoad = userInformationPayload
                    };

                    newAuthorizationCodeGranted = true;
                    actionResult.RedirectInstruction.AddParameter(Constants.StandardAuthorizationResponseNames.AuthorizationCodeName,
                                                                  authorizationCode.Code);
                }
            }

            _jwtGenerator.FillInOtherClaimsIdentityTokenPayload(idTokenPayload,
                                                                authorizationCode == null ? string.Empty : authorizationCode.Code,
                                                                grantedToken == null ? string.Empty : grantedToken.AccessToken,
                                                                authorizationParameter, client);

            if (newAccessTokenGranted) // 3. Insert the stateful access token into the DB OR insert the access token into the caching.
            {
                await _tokenStore.AddToken(grantedToken);

                _simpleIdentityServerEventSource.GrantAccessToClient(authorizationParameter.ClientId,
                                                                     grantedToken.AccessToken,
                                                                     allowedTokenScopes);
            }

            if (newAuthorizationCodeGranted) // 4. Insert the authorization code into the caching.
            {
                if (client.RequirePkce)
                {
                    authorizationCode.CodeChallenge       = authorizationParameter.CodeChallenge;
                    authorizationCode.CodeChallengeMethod = authorizationParameter.CodeChallengeMethod;
                }

                await _authorizationCodeStore.AddAuthorizationCode(authorizationCode);

                _simpleIdentityServerEventSource.GrantAuthorizationCodeToClient(authorizationParameter.ClientId,
                                                                                authorizationCode.Code,
                                                                                authorizationParameter.Scope);
            }

            if (responses.Contains(ResponseType.id_token))
            {
                var idToken = await GenerateIdToken(idTokenPayload, authorizationParameter);

                actionResult.RedirectInstruction.AddParameter(Constants.StandardAuthorizationResponseNames.IdTokenName, idToken);
            }

            if (!string.IsNullOrWhiteSpace(authorizationParameter.State))
            {
                actionResult.RedirectInstruction.AddParameter(Constants.StandardAuthorizationResponseNames.StateName, authorizationParameter.State);
            }

            var sessionState = GetSessionState(authorizationParameter.ClientId, authorizationParameter.OriginUrl, authorizationParameter.SessionId);

            if (sessionState != null)
            {
                actionResult.RedirectInstruction.AddParameter(Constants.StandardAuthorizationResponseNames.SessionState, sessionState);
            }

            if (authorizationParameter.ResponseMode == ResponseMode.form_post)
            {
                actionResult.Type = TypeActionResult.RedirectToAction;
                actionResult.RedirectInstruction.Action = IdentityServerEndPoints.FormIndex;
                actionResult.RedirectInstruction.AddParameter("redirect_uri", authorizationParameter.RedirectUrl);
            }

            // Set the response mode
            if (actionResult.Type == TypeActionResult.RedirectToCallBackUrl)
            {
                var responseMode = authorizationParameter.ResponseMode;
                if (responseMode == ResponseMode.None)
                {
                    var responseTypes     = _parameterParserHelper.ParseResponseTypes(authorizationParameter.ResponseType);
                    var authorizationFlow = _authorizationFlowHelper.GetAuthorizationFlow(responseTypes,
                                                                                          authorizationParameter.State);
                    responseMode = GetResponseMode(authorizationFlow);
                }

                actionResult.RedirectInstruction.ResponseMode = responseMode;
            }

            _simpleIdentityServerEventSource.EndGeneratingAuthorizationResponseToClient(authorizationParameter.ClientId,
                                                                                        actionResult.RedirectInstruction.Parameters.SerializeWithJavascript());
        }