public void When_Client_Doesnt_Contain_RedirectionUri_Then_EmptyArray_Is_Returned()
        {
            // ARRANGE
            InitializeMockingObjects();

            // ACTS & ASSERTS
            Assert.Empty(_clientValidator.GetRedirectionUrls(null, null));
            Assert.Empty(_clientValidator.GetRedirectionUrls(new Core.Common.Models.Client(), null));
            Assert.Empty(_clientValidator.GetRedirectionUrls(new Core.Common.Models.Client(), "url"));
            Assert.Empty(_clientValidator.GetRedirectionUrls(new Core.Common.Models.Client
            {
                RedirectionUrls = new List <string>()
            }, "url"));
        }
        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);
        }
        /// <summary>
        /// Check the parameters based on the RFC : http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation
        /// </summary>
        /// <param name="authorizationCodeGrantTypeParameter"></param>
        /// <param name="authenticationHeaderValue"></param>
        /// <returns></returns>
        private async Task <ValidationResult> ValidateParameter(
            AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter,
            AuthenticationHeaderValue authenticationHeaderValue)
        {
            // 1. Authenticate the client
            var instruction = CreateAuthenticateInstruction(authorizationCodeGrantTypeParameter, authenticationHeaderValue);
            var authResult  = await _authenticateClient.AuthenticateAsync(instruction);

            var client = authResult.Client;

            if (client == null)
            {
                throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage);
            }

            var authorizationCode = await _authorizationCodeRepository.GetAsync(authorizationCodeGrantTypeParameter.Code);

            // 2. Check if the authorization code is valid
            if (authorizationCode == null)
            {
                throw new IdentityServerException(ErrorCodes.InvalidGrant,
                                                  ErrorDescriptions.TheAuthorizationCodeIsNotCorrect);
            }

            // 3. Check PKCE
            if (!_clientValidator.CheckPkce(client, authorizationCodeGrantTypeParameter.CodeVerifier, authorizationCode))
            {
                throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheCodeVerifierIsNotCorrect);
            }

            // 4. Ensure the authorization code was issued to the authenticated client.
            var authorizationClientId = authorizationCode.ClientId;

            if (authorizationClientId != client.ClientId)
            {
                throw new IdentityServerException(ErrorCodes.InvalidGrant,
                                                  string.Format(ErrorDescriptions.TheAuthorizationCodeHasNotBeenIssuedForTheGivenClientId,
                                                                client.ClientId));
            }

            if (authorizationCode.RedirectUri != authorizationCodeGrantTypeParameter.RedirectUri)
            {
                throw new IdentityServerException(ErrorCodes.InvalidGrant,
                                                  ErrorDescriptions.TheRedirectionUrlIsNotTheSame);
            }

            // 5. Ensure the authorization code is still valid.
            var authCodeValidity = await _configurationService.GetAuthorizationCodeValidityPeriodInSecondsAsync();

            var expirationDateTime = authorizationCode.CreateDateTime.AddSeconds(authCodeValidity);
            var currentDateTime    = DateTime.UtcNow;

            if (currentDateTime > expirationDateTime)
            {
                throw new IdentityServerException(ErrorCodes.InvalidGrant,
                                                  ErrorDescriptions.TheAuthorizationCodeIsObsolete);
            }

            // Ensure that the redirect_uri parameter value is identical to the redirect_uri parameter value.
            var redirectionUrl = _clientValidator.GetRedirectionUrls(client, authorizationCodeGrantTypeParameter.RedirectUri);

            if (!redirectionUrl.Any())
            {
                throw new IdentityServerException(
                          ErrorCodes.InvalidGrant,
                          string.Format(ErrorDescriptions.RedirectUrlIsNotValid, authorizationCodeGrantTypeParameter.RedirectUri));
            }

            return(new ValidationResult
            {
                Client = client,
                Code = authorizationCode
            });
        }
        public async Task <Client> ValidateAsync(AuthorizationParameter parameter)
        {
            // Check the required parameters. Read this RFC : http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
            if (string.IsNullOrWhiteSpace(parameter.Scope))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.MissingParameter, Constants.StandardAuthorizationRequestParameterNames.ScopeName),
                          parameter.State);
            }

            if (string.IsNullOrWhiteSpace(parameter.ClientId))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.MissingParameter, Constants.StandardAuthorizationRequestParameterNames.ClientIdName),
                          parameter.State);
            }

            if (string.IsNullOrWhiteSpace(parameter.RedirectUrl))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.MissingParameter, Constants.StandardAuthorizationRequestParameterNames.RedirectUriName),
                          parameter.State);
            }

            if (string.IsNullOrWhiteSpace(parameter.ResponseType))
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.MissingParameter, Constants.StandardAuthorizationRequestParameterNames.ResponseTypeName),
                          parameter.State);
            }

            ValidateResponseTypeParameter(parameter.ResponseType, parameter.State);
            ValidatePromptParameter(parameter.Prompt, parameter.State);

            // With this instruction
            // The redirect_uri is considered well-formed according to the RFC-3986
            var redirectUrlIsCorrect = Uri.IsWellFormedUriString(parameter.RedirectUrl, UriKind.Absolute);

            if (!redirectUrlIsCorrect)
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          ErrorDescriptions.TheRedirectionUriIsNotWellFormed,
                          parameter.State);
            }

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

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

            if (!_clientValidator.GetRedirectionUrls(client, parameter.RedirectUrl).Any())
            {
                throw new IdentityServerExceptionWithState(
                          ErrorCodes.InvalidRequestCode,
                          string.Format(ErrorDescriptions.RedirectUrlIsNotValid, parameter.RedirectUrl),
                          parameter.State);
            }

            return(client);
        }