public ConsentActionResult(IViewService viewSvc, ConsentViewModel model, ValidatedAuthorizeRequest validatedRequest) : base(async () => await viewSvc.Consent(model, validatedRequest)) { if (viewSvc == null) throw new ArgumentNullException("viewSvc"); if (model == null) throw new ArgumentNullException("model"); if (validatedRequest == null) throw new ArgumentNullException("validatedRequest"); }
/// <summary> /// Custom validation logic for the authorize request. /// </summary> /// <param name="request">The validated request.</param> /// <returns> /// The validation result /// </returns> public Task<AuthorizeRequestValidationResult> ValidateAuthorizeRequestAsync(ValidatedAuthorizeRequest request) { return Task.FromResult(new AuthorizeRequestValidationResult { IsError = false }); }
/// <summary> /// /// </summary> /// <param name="request"></param> /// <returns></returns> public async Task<AuthorizeRequestValidationResult> ValidateAuthorizeRequestAsync(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // client_id must be present ///////////////////////////////////////////////////////// var clientId = request.Raw.Get(Constants.AuthorizeRequest.ClientId); if (clientId.IsMissingOrTooLong(_options.InputLengthRestrictions.ClientId)) { 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(_options.InputLengthRestrictions.RedirectUri)) { 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); }
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 async Task<AuthorizeResponse> CreateHybridFlowResponseAsync(ValidatedAuthorizeRequest request) { Logger.Info("Creating Hybrid Flow response."); var code = await CreateCodeAsync(request); var response = await CreateImplicitFlowResponseAsync(request, code); response.Code = code; return response; }
public async Task Anonymous_User_must_SignIn() { var generator = new AuthorizeInteractionResponseGenerator(options, null, null, new DefaultLocalizationService()); var request = new ValidatedAuthorizeRequest { ClientId = "foo" }; var result = await generator.ProcessLoginAsync(request, Principal.Anonymous); result.IsLogin.Should().BeTrue(); }
public async Task Authenticated_User_must_not_SignIn() { var users = new Mock<IUserService>(); var generator = new AuthorizeInteractionResponseGenerator(options, null, users.Object, new DefaultLocalizationService()); var request = new ValidatedAuthorizeRequest { ClientId = "foo", Client = new Client() }; 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; CodeChallengeMethod = request.CodeChallengeMethod; }
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) { Logger.Info("Creating Authorization Code Flow response."); 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<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 > _options.InputLengthRestrictions.Scope) { 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); }
private AuthorizeRequestValidationResult ValidateOptionalParameters(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // check nonce ////////////////////////////////////////////////////////// var nonce = request.Raw.Get(Constants.AuthorizeRequest.Nonce); if (nonce.IsPresent()) { if (nonce.Length > _options.InputLengthRestrictions.Nonce) { LogError("Nonce too long", request); return Invalid(request, ErrorTypes.Client); } request.Nonce = nonce; } else { if (request.Flow == Flows.Implicit || request.Flow == Flows.Hybrid) { // only openid requests require nonce if (request.IsOpenIdRequest) { LogError("Nonce required for implicit and hybrid 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 > _options.InputLengthRestrictions.UiLocale) { 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 > _options.InputLengthRestrictions.LoginHint) { 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 > _options.InputLengthRestrictions.AcrValues) { LogError("Acr values too long", request); return Invalid(request, ErrorTypes.Client); } request.AuthenticationContextReferenceClasses = acrValues.FromSpaceSeparatedString().Distinct().ToList(); } ////////////////////////////////////////////////////////// // check session cookie ////////////////////////////////////////////////////////// if (_options.Endpoints.EnableCheckSessionEndpoint && request.Subject.Identity.IsAuthenticated) { var sessionId = _sessionCookie.GetSessionId(); if (sessionId.IsPresent()) { request.SessionId = sessionId; } else { LogError("Check session endpoint enabled, but SessionId is missing", request); } } return Valid(request); }
/// <summary> /// Loads the HTML for the user consent page. /// </summary> /// <param name="model">The model.</param> /// <param name="authorizeRequest">The validated authorize request.</param> /// <returns> /// Stream for the HTML /// </returns> public virtual Task<Stream> Consent(ConsentViewModel model, ValidatedAuthorizeRequest authorizeRequest) { return Render(model, ConsentView); }
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.User, Constants.AuthorizeErrors.UnsupportedResponseType); } if (!Constants.SupportedResponseTypes.Contains(responseType)) { LogError("Response type not supported: " + responseType, request); return Invalid(request, ErrorTypes.User, 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); }
public async Task<AuthorizeResponse> CreateImplicitFlowResponseAsync(ValidatedAuthorizeRequest request, string authorizationCode = null) { Logger.Info("Creating Implicit Flow response."); string accessTokenValue = null; int accessTokenLifetime = 0; var responseTypes = request.ResponseType.FromSpaceSeparatedString(); if (responseTypes.Contains(Constants.ResponseTypes.Token)) { var tokenRequest = new TokenCreationRequest { Subject = request.Subject, Client = request.Client, Scopes = request.ValidatedScopes.GrantedScopes, ValidatedRequest = request }; var accessToken = await _tokenService.CreateAccessTokenAsync(tokenRequest); accessTokenLifetime = accessToken.Lifetime; accessTokenValue = await _tokenService.CreateSecurityTokenAsync(accessToken); } string jwt = null; if (responseTypes.Contains(Constants.ResponseTypes.IdToken)) { var tokenRequest = new TokenCreationRequest { ValidatedRequest = request, Subject = request.Subject, Client = request.Client, Scopes = request.ValidatedScopes.GrantedScopes, Nonce = request.Raw.Get(Constants.AuthorizeRequest.Nonce), IncludeAllIdentityClaims = !request.AccessTokenRequested, AccessTokenToHash = accessTokenValue, AuthorizationCodeToHash = authorizationCode }; var idToken = await _tokenService.CreateIdentityTokenAsync(tokenRequest); jwt = await _tokenService.CreateSecurityTokenAsync(idToken); } var response = new AuthorizeResponse { Request = request, RedirectUri = request.RedirectUri, AccessToken = accessTokenValue, AccessTokenLifetime = accessTokenLifetime, IdentityToken = jwt, State = request.State, Scope = request.ValidatedScopes.GrantedScopes.ToSpaceSeparatedString(), }; if (request.IsOpenIdRequest) { response.SessionState = GenerateSessionStateValue(request); } return response; }
public async Task Authenticated_User_with_allowed_current_Idp_must_not_SignIn() { var users = new Mock<IUserService>(); var generator = new AuthorizeInteractionResponseGenerator(options, null, users.Object, new DefaultLocalizationService()); var request = new ValidatedAuthorizeRequest { ClientId = "foo", Subject = IdentityServerPrincipal.Create("123", "dom"), Client = new Client { IdentityProviderRestrictions = new List<string> { Constants.BuiltInIdentityProvider } } }; var result = await generator.ProcessClientLoginAsync(request); result.IsLogin.Should().BeFalse(); }
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 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<Stream> Consent (ConsentViewModel model, ValidatedAuthorizeRequest authorizeRequest) { return await Render (model, "Consent"); }
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(); }
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); }
async Task<IHttpActionResult> AuthorizeErrorAsync(ErrorTypes errorType, string error, ValidatedAuthorizeRequest request) { await RaiseFailureEventAsync(error); // show error message to user if (errorType == ErrorTypes.User) { var env = Request.GetOwinEnvironment(); var errorModel = new ErrorViewModel { RequestId = env.GetRequestId(), SiteName = _options.SiteName, SiteUrl = env.GetIdentityServerBaseUrl(), CurrentUser = env.GetCurrentUserDisplayName(), LogoutUrl = env.GetIdentityServerLogoutUrl(), 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, _options); } }
private string GenerateSessionStateValue(ValidatedAuthorizeRequest request) { var sessionId = request.SessionId; if (sessionId.IsMissing()) return null; var salt = CryptoRandom.CreateUniqueId(); var clientId = request.ClientId; var uri = new Uri(request.RedirectUri); var origin = uri.Scheme + "://" + uri.Host; if (!uri.IsDefaultPort) { origin += ":" + uri.Port; } var bytes = Encoding.UTF8.GetBytes(clientId + origin + sessionId + salt); byte[] hash; using (var sha = SHA256.Create()) { hash = sha.ComputeHash(bytes); } return Base64Url.Encode(hash) + "." + salt; }
private AuthorizeRequestValidationResult Invalid(ValidatedAuthorizeRequest request, ErrorTypes errorType = ErrorTypes.User, string error = Constants.AuthorizeErrors.InvalidRequest) { var result = new AuthorizeRequestValidationResult { IsError = true, Error = error, ErrorType = errorType, ValidatedRequest = request }; return result; }
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)); }
private AuthorizeRequestValidationResult Valid(ValidatedAuthorizeRequest request) { var result = new AuthorizeRequestValidationResult { IsError = false, ValidatedRequest = request }; return result; }
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 || request.Flow == Flows.Hybrid) { // only openid requests require nonce if (request.IsOpenIdRequest) { LogError("Nonce required for implicit and hybrid 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 && request.Subject.Identity.IsAuthenticated) { 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 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.User, Constants.AuthorizeErrors.UnsupportedResponseType)); } if (!Constants.SupportedResponseTypes.Contains(responseType)) { LogError("Response type not supported: " + responseType, request); return(Invalid(request, ErrorTypes.User, 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)); }
private async Task<string> CreateCodeAsync(ValidatedAuthorizeRequest request) { var code = new AuthorizationCode { Client = request.Client, Subject = request.Subject, SessionId = request.SessionId, 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); await RaiseCodeIssuedEventAsync(id, code); return id; }
public Task<Stream> Consent(ConsentViewModel model, ValidatedAuthorizeRequest authorizeRequest) { return Task.FromResult(RunTemplate("consent", model, authorizeRequest.ClientId)); }
public async Task Authenticated_User_with_different_requested_Idp_must_SignIn() { var users = new Mock<IUserService>(); var generator = new AuthorizeInteractionResponseGenerator(options, null, users.Object, new DefaultLocalizationService()); var request = new ValidatedAuthorizeRequest { ClientId = "foo", Client = new Client(), AuthenticationContextReferenceClasses = new List<string>{ "idp:some_idp" }, }; var principal = IdentityServerPrincipal.Create("123", "dom"); var result = await generator.ProcessLoginAsync(request, principal); result.IsLogin.Should().BeTrue(); }
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()); }
public async Task Authenticated_User_with_local_Idp_must_SignIn_when_client_options_does_not_allow_local_logins() { options.AuthenticationOptions.EnableLocalLogin = true; var users = new Mock<IUserService>(); var generator = new AuthorizeInteractionResponseGenerator(options, null, users.Object, new DefaultLocalizationService()); var request = new ValidatedAuthorizeRequest { ClientId = "foo", Subject = IdentityServerPrincipal.Create("123", "dom"), Client = new Client { ClientId = "foo", EnableLocalLogin = false } }; var principal = IdentityServerPrincipal.Create("123", "dom"); var result = await generator.ProcessClientLoginAsync(request); result.IsLogin.Should().BeTrue(); }
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) { var isActiveCtx = new IsActiveContext(user, request.Client); await _users.IsActiveAsync(isActiveCtx); isActive = isActiveCtx.IsActive; 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(); }
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)); }