/// <summary>
 /// Custom validation logic for the authorize request.
 /// </summary>
 /// <param name="request">The validated request.</param>
 /// <returns>
 /// The validation result
 /// </returns>
 public Task<ValidationResult> ValidateAuthorizeRequestAsync(ValidatedAuthorizeRequest request)
 {
     return Task.FromResult(new ValidationResult
     {
         IsError = false
     });
 }
        private async Task<AuthorizeResponse> CreateHybridFlowResponseAsync(ValidatedAuthorizeRequest request)
        {
            var code = await CreateCodeAsync(request);
            var response = await CreateImplicitFlowResponseAsync(request, code);
            response.Code = code;

            return response;
        }
        public async Task<AuthorizeRequestValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject = null)
        {
            Logger.Info("Start authorize request protocol validation");

            var request = new ValidatedAuthorizeRequest
            {
                Options = _options,
                Subject = subject ?? Principal.Anonymous
            };
            
            if (parameters == null)
            {
                Logger.Error("Parameters are null.");
                throw new ArgumentNullException("parameters");
            }

            request.Raw = parameters;

            // validate client_id and redirect_uri
            var clientResult = await ValidateClientAsync(request);
            if (clientResult.IsError)
            {
                return clientResult;
            }

            // state, response_type, response_mode
            var mandatoryResult = ValidateCoreParameters(request);
            if (mandatoryResult.IsError)
            {
                return mandatoryResult;
            }

            // scope, scope restrictions and plausability
            var scopeResult = await ValidateScopeAsync(request);
            if (scopeResult.IsError)
            {
                return scopeResult;
            }

            // nonce, prompt, acr_values, login_hint etc.
            var optionalResult = ValidateOptionalParameters(request);
            if (optionalResult.IsError)
            {
                return optionalResult;
            }

            // custom validator
            var customResult = await _customValidator.ValidateAuthorizeRequestAsync(request);

            if (customResult.IsError)
            {
                LogError("Error in custom validation: " + customResult.Error, request);
                return Invalid(request, customResult.ErrorType, customResult.Error);
            }

            LogSuccess(request);
            return Valid(request);
        }
        public async Task<AuthorizeResponse> CreateCodeFlowResponseAsync(ValidatedAuthorizeRequest request)
        {
            var code = await CreateCodeAsync(request);

            return new AuthorizeResponse
            {
                Request = request,
                RedirectUri = request.RedirectUri,
                Code = code,
                State = request.State
            };
        }
        public async Task Anonymous_User_must_SignIn()
        {
            var generator = new AuthorizeInteractionResponseGenerator(null, null, new DefaultLocalizationService());

            var request = new ValidatedAuthorizeRequest
            {
                ClientId = "foo"
            };

            var result = await generator.ProcessLoginAsync(request, Principal.Anonymous);

            result.IsLogin.Should().BeTrue();
        }
        public AuthorizeRequestValidator(IdentityServerOptions options, IClientStore clients, ICustomRequestValidator customValidator, IRedirectUriValidator uriValidator, ScopeValidator scopeValidator, IOwinContext context)
        {
            _options = options;
            _clients = clients;
            _customValidator = customValidator;
            _uriValidator = uriValidator;
            _scopeValidator = scopeValidator;

            _validatedRequest = new ValidatedAuthorizeRequest
            {
                Options = _options, 
                Environment = context.Environment
            };
        }
        public AuthorizeRequestValidator(IdentityServerOptions options, IClientStore clients, ICustomRequestValidator customValidator, IRedirectUriValidator uriValidator, ScopeValidator scopeValidator, SessionCookie sessionCookie)
        {
            _options = options;
            _clients = clients;
            _customValidator = customValidator;
            _uriValidator = uriValidator;
            _scopeValidator = scopeValidator;
            _sessionCookie = sessionCookie;

            _validatedRequest = new ValidatedAuthorizeRequest
            {
                Options = _options, 
            };
        }
        public async Task Authenticated_User_must_not_SignIn()
        {
            var users = new Mock<IUserService>();
            users.Setup(x => x.IsActiveAsync(It.IsAny<ClaimsPrincipal>())).Returns(Task.FromResult<bool>(true));

            var generator = new AuthorizeInteractionResponseGenerator(null, users.Object, new DefaultLocalizationService());

            var request = new ValidatedAuthorizeRequest
            {
                ClientId = "foo",
            };

            var principal = IdentityServerPrincipal.Create("123", "dom");
            var result = await generator.ProcessLoginAsync(request, principal);

            result.IsLogin.Should().BeFalse();
        }
        public AuthorizeRequestValidationLog(ValidatedAuthorizeRequest request)
        {
            Raw = request.Raw.ToDictionary();

            if (request.Client != null)
            {
                ClientId = request.Client.ClientId;
                ClientName = request.Client.ClientName;

                AllowedRedirectUris = request.Client.RedirectUris;
            }

            if (request.Subject != null)
            {
                var subjectClaim = request.Subject.FindFirst(Constants.ClaimTypes.Subject);
                if (subjectClaim != null)
                {
                    SubjectId = subjectClaim.Value;
                }
                else
                {
                    SubjectId = "unknown";
                }
            }

            if (request.AuthenticationContextReferenceClasses.Any())
            {
                AuthenticationContextReferenceClasses = request.AuthenticationContextReferenceClasses;
            }
                
            RedirectUri = request.RedirectUri;
            ResponseType = request.ResponseType;
            ResponseMode = request.ResponseMode;
            Flow = request.Flow;
            RequestedScopes = request.RequestedScopes.ToSpaceSeparatedString();
            State = request.State;
            UiLocales = request.UiLocales;
            Nonce = request.Nonce;
            
            DisplayMode = request.DisplayMode;
            PromptMode = request.PromptMode;
            LoginHint = request.LoginHint;
            MaxAge = request.MaxAge;
            SessionId = request.SessionId;
        }
        public async Task<AuthorizeResponse> CreateResponseAsync(ValidatedAuthorizeRequest request)
        {
            if (request.Flow == Flows.AuthorizationCode)
            {
                return await CreateCodeFlowResponseAsync(request);
            }
            if (request.Flow == Flows.Implicit)
            {
                return await CreateImplicitFlowResponseAsync(request);
            }
            if (request.Flow == Flows.Hybrid)
            {
                return await CreateHybridFlowResponseAsync(request);
            }

            Logger.Error("Unsupported flow: " + request.Flow.ToString());
            throw new InvalidOperationException("invalid flow: " + request.Flow.ToString());
        }
        public async Task<AuthorizeResponse> CreateCodeFlowResponseAsync(ValidatedAuthorizeRequest request)
        {
            var code = await CreateCodeAsync(request);

            var response = new AuthorizeResponse
            {
                Request = request,
                RedirectUri = request.RedirectUri,
                Code = code,
                State = request.State
            };

            if (request.IsOpenIdRequest)
            {
                response.SessionState = GenerateSessionStateValue(request);
            }

            return response;
        }
        private async Task<string> CreateCodeAsync(ValidatedAuthorizeRequest request)
        {
            var code = new AuthorizationCode
            {
                Client = request.Client,
                Subject = request.Subject,

                IsOpenId = request.IsOpenIdRequest,
                RequestedScopes = request.ValidatedScopes.GrantedScopes,
                RedirectUri = request.RedirectUri,
                Nonce = request.Nonce,

                WasConsentShown = request.WasConsentShown,
            };

            // store id token and access token and return authorization code
            var id = CryptoRandom.CreateUniqueId();
            await _authorizationCodes.StoreAsync(id, code);
            
            return id;
        }
 public void ProcessConsentAsync_NoPromptMode_ConsentServiceRequiresConsent_NoPriorConsent_ReturnsConsentResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         PromptMode = Constants.PromptModes.Consent
     };
     var result = subject.ProcessConsentAsync(request).Result;
     request.WasConsentShown.Should().BeFalse();
     result.IsConsent.Should().BeTrue();
     AssertUpdateConsentNotCalled();
 }
 public void ProcessConsentAsync_RequiresConsentButPromptModeIsNone_ReturnsErrorResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         PromptMode = Constants.PromptModes.None
     };
     var result = subject.ProcessConsentAsync(request).Result;
     request.WasConsentShown.Should().BeFalse();
     result.IsError.Should().BeTrue();
     result.Error.ErrorType.Should().Be(ErrorTypes.Client);
     result.Error.Error.Should().Be(Constants.AuthorizeErrors.InteractionRequired);
     AssertErrorReturnsRequestValues(result.Error, request);
     AssertUpdateConsentNotCalled();
 }
        public void ProcessConsentAsync_PromptModeIsSelectAccount_Throws()
        {
            RequiresConsent(true);
            var request = new ValidatedAuthorizeRequest()
            {
                ResponseMode = Constants.ResponseModes.Fragment,
                State = "12345",
                RedirectUri = "https://client.com/callback",
                PromptMode = Constants.PromptModes.SelectAccount
            };

            Func<Task> act = () => subject.ProcessConsentAsync(request);

            act.ShouldThrow<ArgumentException>()
                .And.Message.Should().Contain("PromptMode");
        }
 public void ProcessConsentAsync_AllowsNullConsent()
 {
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         PromptMode = Constants.PromptModes.Consent
     }; 
     var result = subject.ProcessConsentAsync(request, null).Result;
 }
        private void LogSuccess(ValidatedAuthorizeRequest request)
        {
            var validationLog = new AuthorizeRequestValidationLog(request);
            var json = LogSerializer.Serialize(validationLog);

            Logger.InfoFormat("{0}\n {1}", "Authorize request validation success", json);
        }
Exemplo n.º 18
0
        private AuthorizeRequestValidationResult ValidateCoreParameters(ValidatedAuthorizeRequest request)
        {
            //////////////////////////////////////////////////////////
            // check state
            //////////////////////////////////////////////////////////
            var state = request.Raw.Get(Constants.AuthorizeRequest.State);

            if (state.IsPresent())
            {
                request.State = state;
            }

            //////////////////////////////////////////////////////////
            // response_type must be present and supported
            //////////////////////////////////////////////////////////
            var responseType = request.Raw.Get(Constants.AuthorizeRequest.ResponseType);

            if (responseType.IsMissing())
            {
                LogError("Missing response_type", request);
                return(Invalid(request, ErrorTypes.Client, Constants.AuthorizeErrors.UnsupportedResponseType));
            }

            if (!Constants.SupportedResponseTypes.Contains(responseType))
            {
                LogError("Response type not supported: " + responseType, request);
                return(Invalid(request, ErrorTypes.Client, Constants.AuthorizeErrors.UnsupportedResponseType));
            }

            request.ResponseType = responseType;


            //////////////////////////////////////////////////////////
            // match response_type to flow
            //////////////////////////////////////////////////////////
            request.Flow = Constants.ResponseTypeToFlowMapping[request.ResponseType];


            //////////////////////////////////////////////////////////
            // check if flow is allowed at authorize endpoint
            //////////////////////////////////////////////////////////
            if (!Constants.AllowedFlowsForAuthorizeEndpoint.Contains(request.Flow))
            {
                LogError("Invalid flow", request);
                return(Invalid(request));
            }

            //////////////////////////////////////////////////////////
            // check response_mode parameter and set response_mode
            //////////////////////////////////////////////////////////

            // set default response mode for flow first
            request.ResponseMode = Constants.AllowedResponseModesForFlow[request.Flow].First();

            // check if response_mode parameter is present and valid
            var responseMode = request.Raw.Get(Constants.AuthorizeRequest.ResponseMode);

            if (responseMode.IsPresent())
            {
                if (Constants.SupportedResponseModes.Contains(responseMode))
                {
                    if (Constants.AllowedResponseModesForFlow[request.Flow].Contains(responseMode))
                    {
                        request.ResponseMode = responseMode;
                    }
                    else
                    {
                        LogError("Invalid response_mode for flow: " + responseMode, request);
                        return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnsupportedResponseType));
                    }
                }
                else
                {
                    LogError("Unsupported response_mode: " + responseMode, request);
                    return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnsupportedResponseType));
                }
            }


            //////////////////////////////////////////////////////////
            // check if flow is allowed for client
            //////////////////////////////////////////////////////////
            if (request.Flow != request.Client.Flow)
            {
                LogError("Invalid flow for client: " + request.Flow, request);
                return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnauthorizedClient));
            }

            return(Valid(request));
        }
Exemplo n.º 19
0
        public async Task <AuthorizeRequestValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject = null)
        {
            Logger.Info("Start authorize request protocol validation");

            var request = new ValidatedAuthorizeRequest
            {
                Options = _options,
                Subject = subject ?? Principal.Anonymous
            };

            if (parameters == null)
            {
                Logger.Error("Parameters are null.");
                throw new ArgumentNullException("parameters");
            }

            request.Raw = parameters;

            // validate client_id and redirect_uri
            var clientResult = await ValidateClientAsync(request);

            if (clientResult.IsError)
            {
                return(clientResult);
            }

            // state, response_type, response_mode
            var mandatoryResult = ValidateCoreParameters(request);

            if (mandatoryResult.IsError)
            {
                return(mandatoryResult);
            }

            // scope, scope restrictions and plausability
            var scopeResult = await ValidateScopeAsync(request);

            if (scopeResult.IsError)
            {
                return(scopeResult);
            }

            // nonce, prompt, acr_values, login_hint etc.
            var optionalResult = ValidateOptionalParameters(request);

            if (optionalResult.IsError)
            {
                return(optionalResult);
            }

            // custom validator
            var customResult = await _customValidator.ValidateAuthorizeRequestAsync(request);

            if (customResult.IsError)
            {
                LogError("Error in custom validation: " + customResult.Error, request);
                return(Invalid(request, customResult.ErrorType, customResult.Error));
            }

            LogSuccess(request);
            return(Valid(request));
        }
 private void AssertErrorReturnsRequestValues(AuthorizeError error, ValidatedAuthorizeRequest request)
 {
     error.ResponseMode.Should().Be(request.ResponseMode);
     error.ErrorUri.Should().Be(request.RedirectUri);
     error.State.Should().Be(request.State);
 }
 public async Task ProcessConsentAsync_PromptModeConsent_ConsentGranted_ScopesSelected_ReturnsConsentResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes())),
         Client = new Client {
             AllowRememberConsent = false
         }
     };
     await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" });
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = false,
         Scopes = new string[] { "read" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.ValidatedScopes.GrantedScopes.Count.Should().Be(1);
     "read".Should().Be(request.ValidatedScopes.GrantedScopes.First().Name);
     request.WasConsentShown.Should().BeTrue();
     result.IsConsent.Should().BeFalse();
     AssertUpdateConsentNotCalled();
 }
 public void ProcessConsentAsync_NoPromptMode_ConsentServiceRequiresConsent_ConsentNotGranted_ReturnsErrorResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
     };
     var consent = new UserConsent
     {
         Button = "no",
         RememberConsent = false,
         Scopes = new string[] { "read", "write" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.WasConsentShown.Should().BeTrue();
     result.IsError.Should().BeTrue();
     result.Error.ErrorType.Should().Be(ErrorTypes.Client);
     result.Error.Error.Should().Be(Constants.AuthorizeErrors.AccessDenied);
     AssertErrorReturnsRequestValues(result.Error, request);
     AssertUpdateConsentNotCalled();
 }
Exemplo n.º 23
0
        private async Task <AuthorizeRequestValidationResult> ValidateScopeAsync(ValidatedAuthorizeRequest request)
        {
            //////////////////////////////////////////////////////////
            // scope must be present
            //////////////////////////////////////////////////////////
            var scope = request.Raw.Get(Constants.AuthorizeRequest.Scope);

            if (scope.IsMissing())
            {
                LogError("scope is missing", request);
                return(Invalid(request, ErrorTypes.Client));
            }

            if (scope.Length > Constants.MaxScopeLength)
            {
                LogError("scopes too long.", request);
                return(Invalid(request, ErrorTypes.Client));
            }

            request.RequestedScopes = scope.FromSpaceSeparatedString().Distinct().ToList();

            if (request.RequestedScopes.Contains(Constants.StandardScopes.OpenId))
            {
                request.IsOpenIdRequest = true;
            }

            //////////////////////////////////////////////////////////
            // check scope vs response_type plausability
            //////////////////////////////////////////////////////////
            var requirement = Constants.ResponseTypeToScopeRequirement[request.ResponseType];

            if (requirement == Constants.ScopeRequirement.Identity ||
                requirement == Constants.ScopeRequirement.IdentityOnly)
            {
                if (request.IsOpenIdRequest == false)
                {
                    LogError("response_type requires the openid scope", request);
                    return(Invalid(request, ErrorTypes.Client));
                }
            }

            //////////////////////////////////////////////////////////
            // check if scopes are valid/supported and check for resource scopes
            //////////////////////////////////////////////////////////
            if (await _scopeValidator.AreScopesValidAsync(request.RequestedScopes) == false)
            {
                return(Invalid(request, ErrorTypes.Client, Constants.AuthorizeErrors.InvalidScope));
            }

            if (_scopeValidator.ContainsOpenIdScopes && !request.IsOpenIdRequest)
            {
                LogError("Identity related scope requests, but no openid scope", request);
                return(Invalid(request, ErrorTypes.Client, Constants.AuthorizeErrors.InvalidScope));
            }

            if (_scopeValidator.ContainsResourceScopes)
            {
                request.IsResourceRequest = true;
            }

            //////////////////////////////////////////////////////////
            // check scopes and scope restrictions
            //////////////////////////////////////////////////////////
            if (!_scopeValidator.AreScopesAllowed(request.Client, request.RequestedScopes))
            {
                return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnauthorizedClient));
            }

            request.ValidatedScopes = _scopeValidator;

            //////////////////////////////////////////////////////////
            // check id vs resource scopes and response types plausability
            //////////////////////////////////////////////////////////
            if (!_scopeValidator.IsResponseTypeValid(request.ResponseType))
            {
                return(Invalid(request, ErrorTypes.Client, Constants.AuthorizeErrors.InvalidScope));
            }

            return(Valid(request));
        }
 public void ProcessConsentAsync_NoPromptMode_ConsentServiceRequiresConsent_ConsentGranted_NoScopesSelected_ReturnsConsentResult()
 {
     RequiresConsent(true);
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(null),
         Client = new Client { }
     };
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = false,
         Scopes = new string[] {  }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     request.WasConsentShown.Should().BeTrue();
     result.IsConsent.Should().BeTrue();
     result.ConsentError.Should().Be(Messages.MustSelectAtLeastOnePermission);
     AssertUpdateConsentNotCalled();
 }
        private async Task<IHttpActionResult> CreateAuthorizeResponseAsync(ValidatedAuthorizeRequest request)
        {
            var response = await _responseGenerator.CreateResponseAsync(request);

            if (request.ResponseMode == Constants.ResponseModes.Query ||
                request.ResponseMode == Constants.ResponseModes.Fragment)
            {
                RaiseSuccessEvent();
                return new AuthorizeRedirectResult(response);
            }

            if (request.ResponseMode == Constants.ResponseModes.FormPost)
            {
                RaiseSuccessEvent();
                return new AuthorizeFormPostResult(response, Request);
            }

            Logger.Error("Unsupported response mode. Aborting.");
            throw new InvalidOperationException("Unsupported response mode");
        }
 public async Task ProcessConsentAsync_AllowConsentSelected_SavesConsent()
 {
     RequiresConsent(true);
     var client = new Client { AllowRememberConsent = true };
     var user = new ClaimsPrincipal();
     var request = new ValidatedAuthorizeRequest()
     {
         ResponseMode = Constants.ResponseModes.Fragment,
         State = "12345",
         RedirectUri = "https://client.com/callback",
         ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes())),
         Client = client,
         Subject = user
     };
     await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" });
     var consent = new UserConsent
     {
         Button = "yes",
         RememberConsent = true,
         Scopes = new string[] { "read" }
     };
     var result = subject.ProcessConsentAsync(request, consent).Result;
     AssertUpdateConsentCalled(client, user, "read");
 }
        IHttpActionResult AuthorizeError(ErrorTypes errorType, string error, ValidatedAuthorizeRequest request)
        {
            RaiseFailureEvent(error);

            // show error message to user
            if (errorType == ErrorTypes.User)
            {
                var env = Request.GetOwinEnvironment();
                var username = User.Identity.IsAuthenticated ? User.GetName() : (string)null;

                var errorModel = new ErrorViewModel
                {
                    RequestId = env.GetRequestId(),
                    SiteName = _options.SiteName,
                    SiteUrl = env.GetIdentityServerBaseUrl(),
                    CurrentUser = username,
                    ErrorMessage = LookupErrorMessage(error)
                };

                var errorResult = new ErrorActionResult(_viewService, errorModel);
                return errorResult;
            }

            // return error to client
            var response = new AuthorizeResponse
            {
                Request = request,

                IsError = true,
                Error = error,
                State = request.State,
                RedirectUri = request.RedirectUri
            };

            if (request.ResponseMode == Constants.ResponseModes.FormPost)
            {
                return new AuthorizeFormPostResult(response, Request);
            }
            else
            {
                return new AuthorizeRedirectResult(response);
            }
        }
        public async Task<ConsentInteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, UserConsent consent = null)
        {
            if (request == null) throw new ArgumentNullException("request");

            if (request.PromptMode != null && 
                request.PromptMode != Constants.PromptModes.None &&
                request.PromptMode != Constants.PromptModes.Consent)
            {
                throw new ArgumentException("Invalid PromptMode");
            }

            var consentRequired = await _consent.RequiresConsentAsync(request.Client, request.Subject, request.RequestedScopes);

            if (consentRequired && request.PromptMode == Constants.PromptModes.None)
            {
                Logger.Info("Prompt=none requested, but consent is required.");

                return new ConsentInteractionResponse
                {
                    Error = new AuthorizeError
                    {
                        ErrorType = ErrorTypes.Client,
                        Error = Constants.AuthorizeErrors.InteractionRequired,
                        ResponseMode = request.ResponseMode,
                        ErrorUri = request.RedirectUri,
                        State = request.State
                    }
                };
            }

            if (request.PromptMode == Constants.PromptModes.Consent || consentRequired)
            {
                var response = new ConsentInteractionResponse();

                // did user provide consent
                if (consent == null)
                {
                    // user was not yet shown conset screen
                    response.IsConsent = true;
                }
                else
                {
                    request.WasConsentShown = true;

                    // user was shown consent -- did they say yes or no
                    if (consent.WasConsentGranted == false)
                    {
                        // no need to show consent screen again
                        // build access denied error to return to client
                        response.Error = new AuthorizeError { 
                            ErrorType = ErrorTypes.Client,
                            Error = Constants.AuthorizeErrors.AccessDenied,
                            ResponseMode = request.ResponseMode,
                            ErrorUri = request.RedirectUri, 
                            State = request.State
                        };
                    }
                    else
                    {
                        // they said yes, set scopes they chose
                        request.ValidatedScopes.SetConsentedScopes(consent.ScopedConsented);

                        if (!request.ValidatedScopes.GrantedScopes.Any())
                        {
                            // they said yes, but didn't pick any scopes
                            // show consent again and provide error message
                            response.IsConsent = true;
                            response.ConsentError = _localizationService.GetMessage(MessageIds.MustSelectAtLeastOnePermission);
                        }
                        else if (request.Client.AllowRememberConsent)
                        {
                            // remember consent
                            var scopes = Enumerable.Empty<string>();
                            if (consent.RememberConsent)
                            {
                                // remember what user actually selected
                                scopes = request.ValidatedScopes.GrantedScopes.Select(x => x.Name);
                            }
                            
                            await _consent.UpdateConsentAsync(request.Client, request.Subject, scopes);
                        }
                    }
                }
                
                return response;
            }

            return new ConsentInteractionResponse();
        }
Exemplo n.º 29
0
        private AuthorizeRequestValidationResult ValidateOptionalParameters(ValidatedAuthorizeRequest request)
        {
            //////////////////////////////////////////////////////////
            // check nonce
            //////////////////////////////////////////////////////////
            var nonce = request.Raw.Get(Constants.AuthorizeRequest.Nonce);

            if (nonce.IsPresent())
            {
                if (nonce.Length > Constants.MaxNonceLength)
                {
                    LogError("Nonce too long", request);
                    return(Invalid(request, ErrorTypes.Client));
                }

                request.Nonce = nonce;
            }
            else
            {
                if (request.Flow == Flows.Implicit)
                {
                    // only openid requests require nonce
                    if (request.IsOpenIdRequest)
                    {
                        LogError("Nonce required for implicit flow with openid scope", request);
                        return(Invalid(request, ErrorTypes.Client));
                    }
                }
            }


            //////////////////////////////////////////////////////////
            // check prompt
            //////////////////////////////////////////////////////////
            var prompt = request.Raw.Get(Constants.AuthorizeRequest.Prompt);

            if (prompt.IsPresent())
            {
                if (Constants.SupportedPromptModes.Contains(prompt))
                {
                    request.PromptMode = prompt;
                }
                else
                {
                    Logger.Info("Unsupported prompt mode - ignored: " + prompt);
                }
            }

            //////////////////////////////////////////////////////////
            // check ui locales
            //////////////////////////////////////////////////////////
            var uilocales = request.Raw.Get(Constants.AuthorizeRequest.UiLocales);

            if (uilocales.IsPresent())
            {
                if (uilocales.Length > Constants.MaxUiLocaleLength)
                {
                    LogError("UI locale too long", request);
                    return(Invalid(request, ErrorTypes.Client));
                }

                request.UiLocales = uilocales;
            }

            //////////////////////////////////////////////////////////
            // check display
            //////////////////////////////////////////////////////////
            var display = request.Raw.Get(Constants.AuthorizeRequest.Display);

            if (display.IsPresent())
            {
                if (Constants.SupportedDisplayModes.Contains(display))
                {
                    request.DisplayMode = display;
                }

                Logger.Info("Unsupported display mode - ignored: " + display);
            }

            //////////////////////////////////////////////////////////
            // check max_age
            //////////////////////////////////////////////////////////
            var maxAge = request.Raw.Get(Constants.AuthorizeRequest.MaxAge);

            if (maxAge.IsPresent())
            {
                int seconds;
                if (int.TryParse(maxAge, out seconds))
                {
                    if (seconds >= 0)
                    {
                        request.MaxAge = seconds;
                    }
                    else
                    {
                        LogError("Invalid max_age.", request);
                        return(Invalid(request, ErrorTypes.Client));
                    }
                }
                else
                {
                    LogError("Invalid max_age.", request);
                    return(Invalid(request, ErrorTypes.Client));
                }
            }

            //////////////////////////////////////////////////////////
            // check login_hint
            //////////////////////////////////////////////////////////
            var loginHint = request.Raw.Get(Constants.AuthorizeRequest.LoginHint);

            if (loginHint.IsPresent())
            {
                if (loginHint.Length > Constants.MaxLoginHintLength)
                {
                    LogError("Login hint too long", request);
                    return(Invalid(request, ErrorTypes.Client));
                }

                request.LoginHint = loginHint;
            }

            //////////////////////////////////////////////////////////
            // check acr_values
            //////////////////////////////////////////////////////////
            var acrValues = request.Raw.Get(Constants.AuthorizeRequest.AcrValues);

            if (acrValues.IsPresent())
            {
                if (acrValues.Length > Constants.MaxAcrValuesLength)
                {
                    LogError("Acr values too long", request);
                    return(Invalid(request, ErrorTypes.Client));
                }

                request.AuthenticationContextReferenceClasses = acrValues.FromSpaceSeparatedString().Distinct().ToList();
            }

            //////////////////////////////////////////////////////////
            // check session cookie
            //////////////////////////////////////////////////////////
            if (_options.Endpoints.EnableCheckSessionEndpoint)
            {
                var sessionId = _sessionCookie.GetSessionId();
                if (sessionId.IsPresent())
                {
                    request.SessionId = sessionId;
                }
                else
                {
                    LogError("Check session endpoint enabled, but SessionId is missing", request);
                }
            }

            return(Valid(request));
        }
        private IHttpActionResult CreateConsentResult(
            ValidatedAuthorizeRequest validatedRequest,
            UserConsent consent,
            NameValueCollection requestParameters,
            string errorMessage)
        {
            var env = Request.GetOwinEnvironment();
            var consentModel = new ConsentViewModel
            {
                RequestId = env.GetRequestId(),
                SiteName = _options.SiteName,
                SiteUrl = env.GetIdentityServerBaseUrl(),
                ErrorMessage = errorMessage,
                CurrentUser = User.GetName(),
                ClientName = validatedRequest.Client.ClientName,
                ClientUrl = validatedRequest.Client.ClientUri,
                ClientLogoUrl = validatedRequest.Client.LogoUri ?? null,
                IdentityScopes = validatedRequest.GetIdentityScopes(this._localizationService),
                ResourceScopes = validatedRequest.GetResourceScopes(this._localizationService),
                AllowRememberConsent = validatedRequest.Client.AllowRememberConsent,
                RememberConsent = consent != null ? consent.RememberConsent : true,
                LoginWithDifferentAccountUrl = Url.Route(Constants.RouteNames.Oidc.SwitchUser, null).AddQueryString(requestParameters.ToQueryString()),
                LogoutUrl = Url.Route(Constants.RouteNames.Oidc.EndSession, null),
                ConsentUrl = Url.Route(Constants.RouteNames.Oidc.Consent, null).AddQueryString(requestParameters.ToQueryString()),
                AntiForgery = _antiForgeryToken.GetAntiForgeryToken()
            };

            return new ConsentActionResult(_viewService, consentModel);
        }
        private AuthorizeRequestValidationResult Valid(ValidatedAuthorizeRequest request)
        {
            var result = new AuthorizeRequestValidationResult
            {
                IsError = false,
                ValidatedRequest = request
            };

            return result;
        }
        public Task<LoginInteractionResponse> ProcessClientLoginAsync(ValidatedAuthorizeRequest request)
        {
            // check idp restrictions
            var currentIdp = request.Subject.GetIdentityProvider();
            if (request.Client.IdentityProviderRestrictions != null && request.Client.IdentityProviderRestrictions.Any())
            {
                if (!request.Client.IdentityProviderRestrictions.Contains(currentIdp))
                {
                    var response = new LoginInteractionResponse
                    {
                        SignInMessage = _signIn
                    };

                    Logger.WarnFormat("User is logged in with idp: {0}, but idp not in client restriction list.", currentIdp); 
                    
                    return Task.FromResult(response);
                }
            }

            // check if idp is local and local logins are not allowed
            if (currentIdp == Constants.BuiltInIdentityProvider)
            {
                if (_options.AuthenticationOptions.EnableLocalLogin == false || 
                    request.Client.EnableLocalLogin == false)
                {
                    var response = new LoginInteractionResponse
                    {
                        SignInMessage = _signIn
                    };

                    Logger.Warn("User is logged in with local idp, but local logins not enabled.");
                    
                    return Task.FromResult(response);
                }
            }

            return Task.FromResult(new LoginInteractionResponse());
        }
        private void LogError(string message, ValidatedAuthorizeRequest request)
        {
            var validationLog = new AuthorizeRequestValidationLog(request);
            var json = LogSerializer.Serialize(validationLog);

            Logger.ErrorFormat("{0}\n {1}", message, json);
        }
        public async Task<LoginInteractionResponse> ProcessLoginAsync(ValidatedAuthorizeRequest request, ClaimsPrincipal user)
        {
            // let the login page know the client requesting authorization
            _signIn.ClientId = request.ClientId;

            // pass through display mode to signin service
            if (request.DisplayMode.IsPresent())
            {
                _signIn.DisplayMode = request.DisplayMode;
            }

            // pass through ui locales to signin service
            if (request.UiLocales.IsPresent())
            {
                _signIn.UiLocales = request.UiLocales;
            }

            // pass through login_hint
            if (request.LoginHint.IsPresent())
            {
                _signIn.LoginHint = request.LoginHint;
            }

            // process acr values
            var acrValues = request.AuthenticationContextReferenceClasses.Distinct().ToList();
            
            // look for well-known acr value -- idp
            var idp = acrValues.FirstOrDefault(x => x.StartsWith(Constants.KnownAcrValues.HomeRealm));
            if (idp.IsPresent())
            {
                _signIn.IdP = idp.Substring(Constants.KnownAcrValues.HomeRealm.Length);
                acrValues.Remove(idp);
            }

            // look for well-known acr value -- tenant
            var tenant = acrValues.FirstOrDefault(x => x.StartsWith(Constants.KnownAcrValues.Tenant));
            if (tenant.IsPresent())
            {
                _signIn.Tenant = tenant.Substring(Constants.KnownAcrValues.Tenant.Length);
                acrValues.Remove(tenant);
            }

            // pass through any remaining acr values
            if (acrValues.Any())
            {
                _signIn.AcrValues = acrValues;
            }

            if (request.PromptMode == Constants.PromptModes.Login)
            {
                // remove prompt so when we redirect back in from login page
                // we won't think we need to force a prompt again
                request.Raw.Remove(Constants.AuthorizeRequest.Prompt);

                Logger.Info("Redirecting to login page because of prompt=login");

                return new LoginInteractionResponse
                {
                    SignInMessage = _signIn
                };
            }

            // unauthenticated user
            var isAuthenticated = user.Identity.IsAuthenticated;
            if (!isAuthenticated) Logger.Info("User is not authenticated. Redirecting to login.");
            
            // user de-activated
            bool isActive = false;

            if (isAuthenticated)
            {
                isActive = await _users.IsActiveAsync(user);
                if (!isActive) Logger.Info("User is not active. Redirecting to login.");
            }

            if (!isAuthenticated || !isActive)
            {
                // prompt=none means user must be signed in already
                if (request.PromptMode == Constants.PromptModes.None)
                {
                    Logger.Info("prompt=none was requested. But user is not authenticated.");

                    return new LoginInteractionResponse
                    {
                        Error = new AuthorizeError
                        {
                            ErrorType = ErrorTypes.Client,
                            Error = Constants.AuthorizeErrors.LoginRequired,
                            ResponseMode = request.ResponseMode,
                            ErrorUri = request.RedirectUri,
                            State = request.State
                        }
                    };
                }

                return new LoginInteractionResponse
                {
                    SignInMessage = _signIn
                };
            }

            // check current idp
            var currentIdp = user.GetIdentityProvider();

            // check if idp login hint matches current provider
            if (_signIn.IdP.IsPresent())
            {
                if (_signIn.IdP != currentIdp)
                {
                    Logger.Info("Current IdP is not the requested IdP. Redirecting to login");
                    Logger.InfoFormat("Current: {0} -- Requested: {1}", currentIdp, _signIn.IdP);

                    return new LoginInteractionResponse
                    {
                        SignInMessage = _signIn
                    };
                }
            }

            // check authentication freshness
            if (request.MaxAge.HasValue)
            {
                var authTime = user.GetAuthenticationTime();
                if (DateTimeOffsetHelper.UtcNow > authTime.AddSeconds(request.MaxAge.Value))
                {
                    Logger.Info("Requested MaxAge exceeded. Redirecting to login");

                    return new LoginInteractionResponse
                    {
                        SignInMessage = _signIn
                    };
                }
            }

            return new LoginInteractionResponse();
        }
Exemplo n.º 35
0
        public async Task <AuthorizeRequestValidationResult> ValidateClientAsync(ValidatedAuthorizeRequest request)
        {
            //////////////////////////////////////////////////////////
            // client_id must be present
            /////////////////////////////////////////////////////////
            var clientId = request.Raw.Get(Constants.AuthorizeRequest.ClientId);

            if (clientId.IsMissingOrTooLong(Constants.MaxClientIdLength))
            {
                LogError("client_id is missing or too long", request);
                return(Invalid(request));
            }

            request.ClientId = clientId;


            //////////////////////////////////////////////////////////
            // redirect_uri must be present, and a valid uri
            //////////////////////////////////////////////////////////
            var redirectUri = request.Raw.Get(Constants.AuthorizeRequest.RedirectUri);

            if (redirectUri.IsMissingOrTooLong(Constants.MaxRedirectUriLength))
            {
                LogError("redirect_uri is missing or too long", request);
                return(Invalid(request));
            }

            Uri uri;

            if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out uri))
            {
                LogError("invalid redirect_uri: " + redirectUri, request);
                return(Invalid(request));
            }

            request.RedirectUri = redirectUri;


            //////////////////////////////////////////////////////////
            // check for valid client
            //////////////////////////////////////////////////////////
            var client = await _clients.FindClientByIdAsync(request.ClientId);

            if (client == null || client.Enabled == false)
            {
                LogError("Unknown client or not enabled: " + request.ClientId, request);
                return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnauthorizedClient));
            }

            request.Client = client;

            //////////////////////////////////////////////////////////
            // check if redirect_uri is valid
            //////////////////////////////////////////////////////////
            if (await _uriValidator.IsRedirectUriValidAsync(request.RedirectUri, request.Client) == false)
            {
                LogError("Invalid redirect_uri: " + request.RedirectUri, request);
                return(Invalid(request, ErrorTypes.User, Constants.AuthorizeErrors.UnauthorizedClient));
            }

            return(Valid(request));
        }