public void Init() { _context = IdentityServerContextHelper.Create(); _validatedAuthorizeRequest = new ValidatedAuthorizeRequest() { RedirectUri = "http://client/callback", State = "123", ResponseMode = "fragment", ClientId = "client", Client = new Client { ClientId = "client", ClientName = "Test Client" }, Raw = _params, Subject = _user }; _stubAuthorizeRequestValidator.Result.IsError = false; _stubAuthorizeRequestValidator.Result.ValidatedRequest = _validatedAuthorizeRequest; _subject = new AuthorizeEndpoint( _mockEventService, _fakeLogger, _context, _stubAuthorizeRequestValidator, _stubInteractionGenerator, _stubResultFactory, _mockSignInResponseStore, _mockUserConsentResponseMessageStore); }
/// <summary> /// Custom validation logic for the authorize request. /// </summary> /// <param name="request">The validated request.</param> /// <returns> /// The validation result /// </returns> // todo public Task<AuthorizeRequestValidationResult> ValidateAuthorizeRequestAsync(ValidatedAuthorizeRequest request) { return Task.FromResult(new AuthorizeRequestValidationResult { IsError = false }); }
public async Task<AuthorizeRequestValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject = null) { _logger.LogInformation("Start authorize request protocol validation"); var request = new ValidatedAuthorizeRequest { Options = _options, Subject = subject ?? Principal.Anonymous }; if (parameters == null) { _logger.LogError("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.LogInformation("Creating Hybrid Flow response."); var code = await CreateCodeAsync(request); var response = await CreateImplicitFlowResponseAsync(request, code); response.Code = code; return response; }
public async Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { var result = await ProcessLoginAsync(request); if (result.IsLogin || result.IsError) { return result; } return await ProcessConsentAsync(request, consent); }
public async Task<IEndpointResult> CreateLoginResultAsync(ValidatedAuthorizeRequest request) { var signin = new SignInRequest(); // 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; } // look for well-known acr value -- idp var idp = request.GetIdP(); if (idp.IsPresent()) { signin.IdP = idp; } // look for well-known acr value -- tenant var tenant = request.GetTenant(); if (tenant.IsPresent()) { signin.Tenant = tenant; } // process acr values var acrValues = request.GetAcrValues(); if (acrValues.Any()) { signin.AcrValues = acrValues; } var message = new Message<SignInRequest>(signin) { ResponseUrl = _context.GetIdentityServerBaseUrl().EnsureTrailingSlash() + Constants.RoutePaths.Oidc.AuthorizeAfterLogin, AuthorizeRequestParameters = request.Raw.ToDictionary() }; await _signInRequestStore.WriteAsync(message); return new LoginPageResult(message.Id); }
public async Task Anonymous_User_must_SignIn() { var request = new ValidatedAuthorizeRequest { ClientId = "foo", Subject = Principal.Anonymous }; var result = await _subject.ProcessLoginAsync(request); result.IsLogin.Should().BeTrue(); }
public async Task Authenticated_User_must_not_SignIn() { var request = new ValidatedAuthorizeRequest { ClientId = "foo", Client = new Client(), Subject = IdentityServerPrincipal.Create("123", "dom") }; var result = await _subject.ProcessInteractionAsync(request); 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(JwtClaimTypes.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; GrantType = request.GrantType; 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.LogError("Unsupported flow: " + request.Flow.ToString()); throw new InvalidOperationException("invalid flow: " + request.Flow.ToString()); }
public async Task Authenticated_User_with_allowed_current_Idp_must_not_SignIn() { var request = new ValidatedAuthorizeRequest { ClientId = "foo", Subject = IdentityServerPrincipal.Create("123", "dom"), Client = new Client { IdentityProviderRestrictions = new List<string> { Constants.BuiltInIdentityProvider } } }; var result = await _subject.ProcessLoginAsync(request); result.IsLogin.Should().BeFalse(); }
public async Task<AuthorizeResponse> CreateCodeFlowResponseAsync(ValidatedAuthorizeRequest request) { _logger.LogInformation("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<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; }
async Task <AuthorizeRequestValidationResult> ValidateClientAsync(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)); }
private AuthorizeRequestValidationResult ValidateOptionalParameters(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // check nonce ////////////////////////////////////////////////////////// var nonce = request.Raw.Get(OidcConstants.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(OidcConstants.AuthorizeRequest.Prompt); if (prompt.IsPresent()) { if (Constants.SupportedPromptModes.Contains(prompt)) { request.PromptMode = prompt; } else { _logger.LogInformation("Unsupported prompt mode - ignored: " + prompt); } } ////////////////////////////////////////////////////////// // check ui locales ////////////////////////////////////////////////////////// var uilocales = request.Raw.Get(OidcConstants.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(OidcConstants.AuthorizeRequest.Display); if (display.IsPresent()) { if (Constants.SupportedDisplayModes.Contains(display)) { request.DisplayMode = display; } _logger.LogInformation("Unsupported display mode - ignored: " + display); } ////////////////////////////////////////////////////////// // check max_age ////////////////////////////////////////////////////////// var maxAge = request.Raw.Get(OidcConstants.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(OidcConstants.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(OidcConstants.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); }
private async Task<AuthorizeRequestValidationResult> ValidateScopeAsync(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // scope must be present ////////////////////////////////////////////////////////// var scope = request.Raw.Get(OidcConstants.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, OidcConstants.AuthorizeErrors.InvalidScope); } if (_scopeValidator.ContainsOpenIdScopes && !request.IsOpenIdRequest) { LogError("Identity related scope requests, but no openid scope", request); return Invalid(request, ErrorTypes.Client, OidcConstants.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, OidcConstants.AuthorizeErrors.UnauthorizedClient); } request.ValidatedScopes = _scopeValidator; ////////////////////////////////////////////////////////// // check id vs resource scopes and response types plausability ////////////////////////////////////////////////////////// if (!_scopeValidator.IsResponseTypeValid(request.ResponseType)) { return Invalid(request, ErrorTypes.Client, OidcConstants.AuthorizeErrors.InvalidScope); } 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<IEndpointResult> CreateAuthorizeResultAsync(ValidatedAuthorizeRequest request) { var response = await _responseGenerator.CreateResponseAsync(request); return await CreateAuthorizeResultAsync(response); }
public async Task<IEndpointResult> CreateConsentResultAsync(ValidatedAuthorizeRequest request) { var consent = new ConsentRequest() { ClientId = request.ClientId, ScopesRequested = request.RequestedScopes.ToArray(), DisplayMode = request.DisplayMode, UiLocales = request.UiLocales }; var message = new Message<ConsentRequest>(consent) { ResponseUrl = _context.GetIdentityServerBaseUrl().EnsureTrailingSlash() + Constants.RoutePaths.Oidc.AuthorizeAfterConsent, AuthorizeRequestParameters = request.Raw.ToDictionary() }; await _consentRequestStore.WriteAsync(message); return new ConsentPageResult(message.Id); }
private void LogError(string message, ValidatedAuthorizeRequest request) { var validationLog = new AuthorizeRequestValidationLog(request); var json = LogSerializer.Serialize(validationLog); _logger.LogError("{0}\n {1}", message, json); }
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)); }
public async Task <AuthorizeRequestValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject = null) { _logger.LogInformation("Start authorize request protocol validation"); var request = new ValidatedAuthorizeRequest { Options = _options, Subject = subject ?? Principal.Anonymous }; if (parameters == null) { _logger.LogError("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 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.LogInformation("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.LogInformation("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)); }
public async Task ProcessConsentAsync_PromptModeConsent_ConsentGranted_ScopesSelected_ReturnsConsentResult() { RequiresConsent(true); var request = new ValidatedAuthorizeRequest() { ResponseMode = OidcConstants.ResponseModes.Fragment, State = "12345", RedirectUri = "https://client.com/callback", ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes()), new FakeLoggerFactory()), Client = new Client { AllowRememberConsent = false } }; await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" }); var consent = new ConsentResponse { RememberConsent = false, ScopesConsented = 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(); }
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; }
public async Task<AuthorizeResponse> CreateImplicitFlowResponseAsync(ValidatedAuthorizeRequest request, string authorizationCode = null) { _logger.LogInformation("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; }
private AuthorizeRequestValidationResult Invalid(ValidatedAuthorizeRequest request, ErrorTypes errorType = ErrorTypes.User, string error = OidcConstants.AuthorizeErrors.InvalidRequest) { var result = new AuthorizeRequestValidationResult { IsError = true, Error = error, ErrorType = errorType, ValidatedRequest = request }; return result; }
public Task<AuthorizeResponse> CreateResponseAsync(ValidatedAuthorizeRequest request) { return Task.FromResult(Response); }
private AuthorizeRequestValidationResult Valid(ValidatedAuthorizeRequest request) { var result = new AuthorizeRequestValidationResult { IsError = false, ValidatedRequest = request }; return result; }
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 void LogSuccess(ValidatedAuthorizeRequest request) { var validationLog = new AuthorizeRequestValidationLog(request); var json = LogSerializer.Serialize(validationLog); _logger.LogInformation("{0}\n {1}", "Authorize request validation success", json); }
async Task<AuthorizeRequestValidationResult> ValidateClientAsync(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // client_id must be present ///////////////////////////////////////////////////////// var clientId = request.Raw.Get(OidcConstants.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(OidcConstants.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, OidcConstants.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, OidcConstants.AuthorizeErrors.UnauthorizedClient); } return Valid(request); }
public async Task<IEndpointResult> CreateErrorResultAsync(ErrorTypes errorType, string error, ValidatedAuthorizeRequest request) { if (errorType == ErrorTypes.Client && request == null) { throw new ArgumentNullException(nameof(request), "Request must be passed when error type is Client."); } AuthorizeResponse response = null; if (errorType == ErrorTypes.Client) { response = new AuthorizeResponse { Request = request, IsError = true, Error = error, State = request.State, RedirectUri = request.RedirectUri }; // do some early checks to see if we will end up not generating an error page if (error == Constants.AuthorizeErrors.AccessDenied) { return await CreateAuthorizeResultAsync(response); } if (request.PromptMode == Constants.PromptModes.None && request.Client.AllowPromptNone == true && (error == Constants.AuthorizeErrors.LoginRequired || error == Constants.AuthorizeErrors.ConsentRequired || error == Constants.AuthorizeErrors.InteractionRequired) ) { // todo: verify these are the right conditions to allow // redirecting back to client // https://tools.ietf.org/html/draft-bradley-oauth-open-redirector-00 return await CreateAuthorizeResultAsync(response); } else { //_logger.LogWarning("Rendering error page due to prompt=none, client does not allow prompt mode none, response is query, and "); } } // we now know we must show error page var msg = _localizationService.GetMessage(error); if (msg.IsMissing()) { msg = error; } var errorModel = new ErrorMessage { RequestId = _context.GetRequestId(), ErrorCode = error, ErrorDescription = msg }; if (errorType == ErrorTypes.Client) { // if this is a client error, we need to build up the // response back to the client, and provide it in the // error view model so the UI can build the link/form errorModel.ReturnInfo = new ClientReturnInfo { ClientId = request.ClientId, }; if (request.ResponseMode == Constants.ResponseModes.Query || request.ResponseMode == Constants.ResponseModes.Fragment) { errorModel.ReturnInfo.Uri = request.RedirectUri = AuthorizeRedirectResult.BuildUri(response); } else if (request.ResponseMode == Constants.ResponseModes.FormPost) { errorModel.ReturnInfo.Uri = request.RedirectUri; errorModel.ReturnInfo.PostBody = AuthorizeFormPostResult.BuildFormBody(response); } else { _logger.LogError("Unsupported response mode."); throw new InvalidOperationException("Unsupported response mode"); } } var message = new Message<ErrorMessage>(errorModel); await _errorMessageStore.WriteAsync(message); return new ErrorPageResult(message.Id); }
private AuthorizeRequestValidationResult ValidateCoreParameters(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // check state ////////////////////////////////////////////////////////// var state = request.Raw.Get(OidcConstants.AuthorizeRequest.State); if (state.IsPresent()) { request.State = state; } ////////////////////////////////////////////////////////// // response_type must be present and supported ////////////////////////////////////////////////////////// var responseType = request.Raw.Get(OidcConstants.AuthorizeRequest.ResponseType); if (responseType.IsMissing()) { LogError("Missing response_type", request); return Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnsupportedResponseType); } if (!Constants.SupportedResponseTypes.Contains(responseType)) { LogError("Response type not supported: " + responseType, request); return Invalid(request, ErrorTypes.User, OidcConstants.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(OidcConstants.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, OidcConstants.AuthorizeErrors.UnsupportedResponseType); } } else { LogError("Unsupported response_mode: " + responseMode, request); return Invalid(request, ErrorTypes.User, OidcConstants.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, OidcConstants.AuthorizeErrors.UnauthorizedClient); } return Valid(request); }
private AuthorizeRequestValidationResult ValidateCoreParameters(ValidatedAuthorizeRequest request) { ////////////////////////////////////////////////////////// // check state ////////////////////////////////////////////////////////// var state = request.Raw.Get(OidcConstants.AuthorizeRequest.State); if (state.IsPresent()) { request.State = state; } ////////////////////////////////////////////////////////// // response_type must be present and supported ////////////////////////////////////////////////////////// var responseType = request.Raw.Get(OidcConstants.AuthorizeRequest.ResponseType); if (responseType.IsMissing()) { LogError("Missing response_type", request); return(Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnsupportedResponseType)); } if (!Constants.SupportedResponseTypes.Contains(responseType)) { LogError("Response type not supported: " + responseType, request); return(Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnsupportedResponseType)); } request.ResponseType = responseType; // todo ////////////////////////////////////////////////////////// // match response_type to flow ////////////////////////////////////////////////////////// //request.Flow = Constants.ResponseTypeToFlowMapping[request.ResponseType]; request.GrantType = Constants.ResponseTypeToGrantTypeMapping[request.ResponseType]; // todo ////////////////////////////////////////////////////////// // check if flow is allowed at authorize endpoint ////////////////////////////////////////////////////////// if (!Constants.AllowedGrantTypesForAuthorizeEndpoint.Contains(request.GrantType)) { LogError("Invalid grant type", request); return(Invalid(request)); } ////////////////////////////////////////////////////////// // check response_mode parameter and set response_mode ////////////////////////////////////////////////////////// // set default response mode for flow first request.ResponseMode = Constants.AllowedResponseModesForGrantType[request.GrantType].First(); // check if response_mode parameter is present and valid var responseMode = request.Raw.Get(OidcConstants.AuthorizeRequest.ResponseMode); if (responseMode.IsPresent()) { if (Constants.SupportedResponseModes.Contains(responseMode)) { if (Constants.AllowedResponseModesForGrantType[request.GrantType].Contains(responseMode)) { request.ResponseMode = responseMode; } else { LogError("Invalid response_mode for flow: " + responseMode, request); return(Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnsupportedResponseType)); } } else { LogError("Unsupported response_mode: " + responseMode, request); return(Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnsupportedResponseType)); } } ////////////////////////////////////////////////////////// // check if grant type is allowed for client ////////////////////////////////////////////////////////// if (!request.Client.AllowedGrantTypes.Contains(request.GrantType)) { LogError("Invalid grant type for client: " + request.GrantType, request); return(Invalid(request, ErrorTypes.User, OidcConstants.AuthorizeErrors.UnauthorizedClient)); } ////////////////////////////////////////////////////////// // check if response type contains an access token, // and if client is allowed to request access token via browser ////////////////////////////////////////////////////////// var responseTypes = responseType.FromSpaceSeparatedString(); if (responseTypes.Contains(OidcConstants.ResponseTypes.Token)) { if (!request.Client.AllowAccessTokensViaBrowser) { LogError("Client requested access token - but client is not configured to receive access tokens via browser", request); return(Invalid(request)); } } return(Valid(request)); }
public async Task ProcessConsentAsync_AllowConsentSelected_SavesConsent() { RequiresConsent(true); var client = new Client { AllowRememberConsent = true }; var user = new ClaimsPrincipal(); var request = new ValidatedAuthorizeRequest() { ResponseMode = OidcConstants.ResponseModes.Fragment, State = "12345", RedirectUri = "https://client.com/callback", ValidatedScopes = new ScopeValidator(new InMemoryScopeStore(GetScopes()), new FakeLoggerFactory()), Client = client, Subject = user }; await request.ValidatedScopes.AreScopesValidAsync(new string[] { "read", "write" }); var consent = new ConsentResponse { RememberConsent = true, ScopesConsented = new string[] { "read" } }; var result = _subject.ProcessConsentAsync(request, consent).Result; AssertUpdateConsentCalled(client, user, "read"); }