public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>(); // Retrieve the application details corresponding to the requested client_id. var application = await(from entity in database.Applications where entity.ApplicationID == context.ClientId select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: ensure that your client_id is correct"); return; } if (!string.IsNullOrEmpty(context.RedirectUri) && !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri"); return; } context.Validate(application.RedirectUri); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts authorization code or hybrid flow authorization requests // that don't result in an access token being returned directly from the authorization endpoint. // You may consider relaxing it to support the implicit flow. In this case, consider adding checks // rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() || context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only response_type=code and response_type=id_token or " + "response_type=code id_token are supported by this authorization server"); return; } // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified response_mode is unsupported."); return; } using (var database = new ApplicationContext()) { // Retrieve the application details corresponding to the requested client_id. var application = await(from entity in database.Applications where entity.ApplicationID == context.ClientId select entity).SingleOrDefaultAsync(context.OwinContext.Request.CallCancelled); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: " + "ensure that your client_id is correct"); return; } if (!string.IsNullOrEmpty(context.RedirectUri) && !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri"); return; } context.Validate(application.RedirectUri); } }
private async Task _validateAuthorizationCodeFlow(ValidateAuthorizationRequestContext context) { authservice = context.HttpContext.RequestServices.GetRequiredService <IValidateAuthorizationService>(); if (authservice == null) { context.Reject(OpenIdConnectConstants.Errors.ServerError, "Failed to validate this authorization request"); return; } if (string.IsNullOrEmpty(context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required redirect_uri parameter was missing."); return; } if (!(await authservice.CheckClientIdExists(context.ClientId))) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidClient, description: "Supplied Client Id was not a valid application Client Id."); return; } if (!(await authservice.CheckRedirectURIMatches(context.RedirectUri, context.ClientId))) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied Redirect URI was not valid for the supplied Client Id."); return; } if (!(await authservice.CheckScopesAreValid(context.Request.Scope))) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied scopes were was not valid Spotify Scopes."); return; } context.Validate(); }
public override Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts response_type=code authorization/authentication requests. // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding // checks rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only the authorization code flow is supported by this authorization server."); return(Task.FromResult(0)); } // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified 'response_mode' is unsupported."); return(Task.FromResult(0)); } IClientService clientService = (IClientService)context.HttpContext.RequestServices.GetService(typeof(IClientService)); ClientModel client = clientService.Get(context.Request.ClientId); // || !string.Equals(context.Request.ClientSecret, client.ClientSecret, StringComparison.Ordinal) // Ensure the client_id parameter corresponds to the Postman client. if (client == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return(Task.FromResult(0)); } // Ensure the redirect_uri parameter corresponds to the Postman client. if (!string.Equals(context.Request.RedirectUri, client.RedirectUrl, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified 'redirect_uri' is invalid."); return(Task.FromResult(0)); } context.Validate(); return(Task.FromResult(0)); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts response_type=code authorization/authentication requests. // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding // checks rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only the authorization code flow is supported by this authorization server."); return; } // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified 'response_mode' is unsupported."); return; } var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>(); // Retrieve the application details corresponding to the requested client_id. var application = await(from entity in database.Applications where entity.ApplicationID == context.ClientId select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return; } if (!string.IsNullOrEmpty(context.RedirectUri) && !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified 'redirect_uri' is invalid."); return; } context.Validate(application.RedirectUri); }
/// <summary> /// Represents an event called for each request to the authorization endpoint /// to determine if the request is valid and should continue. /// </summary> /// <param name="context">The context instance associated with this event.</param> public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts response_type=code authorization/authentication requests. // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding // checks rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only the authorization code flow is supported by this authorization server."); return; } // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!context.Request.ResponseMode.IsNullOrWhiteSpace() && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified 'response_mode' is unsupported."); return; } // Retrieve the application details corresponding to the requested client_id. var rockContext = new RockContext(); var authClientService = new AuthClientService(rockContext); var authClient = await authClientService.GetByClientIdAsync(context.ClientId); if (authClient == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return; } if (!context.RedirectUri.IsNullOrWhiteSpace() && !string.Equals(context.RedirectUri, authClient.RedirectUri, StringComparison.OrdinalIgnoreCase)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified 'redirect_uri' is invalid."); return; } context.Validate(authClient.RedirectUri); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts response_type=code authorization/authentication requests. // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding // checks rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow()) { context.Reject( OpenIdConnectConstants.Errors.UnsupportedResponseType, "Only the authorization and implicit code flows are supported by this authorization server"); return; } // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( OpenIdConnectConstants.Errors.InvalidRequest, "The specified response_mode is unsupported."); return; } // Retrieve the application details corresponding to the requested client_id. var application = await _applicationRepository.GetByIdAsync(context.ClientId); if (application == null) { context.Reject( OpenIdConnectConstants.Errors.InvalidClient, "Application not found in the database: ensure that your client_id is correct"); return; } var redirectUrl = application.Urls.FirstOrDefault(item => item.Equals(context.RedirectUri, StringComparison.Ordinal)); if (!string.IsNullOrEmpty(context.RedirectUri) && redirectUrl == null) { context.Reject( OpenIdConnectConstants.Errors.InvalidClient, "Invalid redirect_uri"); return; } context.Validate(redirectUrl); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { var request = context.Request; if (!request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: InvalidResponseMessage ); return; } if (string.IsNullOrWhiteSpace(context.ClientId)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: InvalidClientMessage ); return; } var application = await BookingContext.Applications .Where(a => a.Id == context.ClientId) .SingleOrDefaultAsync(context.HttpContext.RequestAborted); if (application == null || application.Type == ApplicationType.Introspection) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: InvalidClientMessage ); return; } if (!MatchRedirectUrl(application, context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: InvalidClientMessage ); return; } context.Validate(); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { _vService = context.HttpContext.RequestServices.GetRequiredService <ValidationService>(); if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow()) { context.Reject(OpenIdConnectConstants.Errors.UnsupportedResponseType, "Only authorization code, refresh token, and token grant types are accepted by this authorization server."); return; } var clientId = context.ClientId; var rdi = context.Request.RedirectUri; var state = context.Request.State; var scope = context.Request.Scope; if (string.IsNullOrWhiteSpace(clientId)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "client_id cannot be empty"); return; } if (string.IsNullOrWhiteSpace(rdi)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "redirect_uri cannot be empty"); return; } if (!await _vService.CheckClientIdIsValid(clientId)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied client id does not exist"); return; } if (!await _vService.CheckRedirectUriMatchesClientId(clientId, rdi)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied redirect uri is incorrect"); return; } if (!_vService.CheckScopesAreValid(scope)) { context.Reject(OpenIdConnectConstants.Errors.InvalidRequest, "One or all of the supplied scopes are invalid"); return; } context.Validate(); }
/// <summary> /// Validate wether the redirect uri is valid for the specific client . /// </summary> public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { var query = new ClientRedirectUriValidator(context.ClientId, context.RedirectUri); var result = await ExecuteMessage(context, query); if (!result.Succeeded) { context.Reject( error: "invalid_client", description: "Invalid redirect uri"); return; } context.Validate(); }
// Implement OnValidateAuthorizationRequest to support interactive flows (code/implicit/hybrid). public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { if (!context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only the authorization code flow is supported by this authorization server."); return; } if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified 'response_mode' is unsupported."); return; } var database = context.HttpContext.RequestServices.GetRequiredService <EgenutviklingContext>(); var application = await(from entity in database.Applications where entity.ApplicationID == context.ClientId select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return; } if (!string.IsNullOrEmpty(context.RedirectUri) && !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified 'redirect_uri' is invalid."); return; } context.Validate(application.RedirectUri); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Este servidor de autorización solo admite el código de autorización y el flujo implícito."); return; } if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "El especificado 'response_mode' no es soportado."); return; } var aplicacion = await _repository.GetAplicacionClienteAsync(context.ClientId, context.HttpContext.RequestAborted); if (aplicacion == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "El identificador de cliente especificado no es válido."); return; } if (string.IsNullOrEmpty(context.RedirectUri) || !string.Equals(context.RedirectUri, aplicacion.RedirigirUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "El especificado 'redirect_uri' es inválido."); return; } context.Validate(aplicacion.RedirigirUri); }
public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows // but this authorization provider only accepts response_type=code authorization/authentication requests. // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding // checks rejecting implicit/hybrid authorization requests when the client is a confidential application. if (!context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "Only the authorization code flow is supported by this authorization server"); return; } var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>(); // Retrieve the application details corresponding to the requested client_id. var application = await(from entity in database.Applications where entity.ApplicationID == context.ClientId select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: ensure that your client_id is correct"); return; } if (!string.IsNullOrEmpty(context.RedirectUri) && !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri"); return; } context.Validate(application.RedirectUri); }
public override Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context) { // ref: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/samples/Mvc/Mvc.Server/Providers/AuthorizationProvider.cs // Note: to support custom response modes, the OpenID Connect server middleware doesn't // reject unknown modes before the ApplyAuthorizationResponse event is invoked. // To ensure invalid modes are rejected early enough, a check is made here. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified 'response_mode' is unsupported."); return(Task.CompletedTask); } // Retrieve the application details corresponding to the requested client_id. if (!String.Equals(context.ClientId, _beatriceSecurityConfiguration.OAuth.ClientId, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return(Task.CompletedTask); } if (!String.IsNullOrEmpty(context.RedirectUri) && !_beatriceSecurityConfiguration.OAuth.RedirectUrls.Any(x => x.StartsWith(context.RedirectUri))) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified 'redirect_uri' is invalid."); return(Task.CompletedTask); } context.Validate(context.RedirectUri); return(Task.CompletedTask); }
public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context) { var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication> >(); // Note: redirect_uri is not required for pure OAuth2 requests // but this provider uses a stricter policy making it mandatory, // as required by the OpenID Connect core specification. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest. if (string.IsNullOrEmpty(context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required redirect_uri parameter was missing."); return; } // Retrieve the application details corresponding to the requested client_id. var application = await services.Applications.FindApplicationByIdAsync(context.ClientId); if (application == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: ensure that your client_id is correct."); return; } if (!await services.Applications.ValidateRedirectUriAsync(application, context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri."); return; } // To prevent downgrade attacks, ensure that authorization requests using the hybrid/implicit // flow are rejected if the client identifier corresponds to a confidential application. // Note: when using the authorization code grant, ValidateClientAuthentication is responsible of // rejecting the token request if the client_id corresponds to an unauthenticated confidential client. if (await services.Applications.IsConfidentialApplicationAsync(application) && !context.Request.IsAuthorizationCodeFlow()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Confidential clients can only use response_type=code."); return; } // If the user is connected, ensure that a corresponding profile exists and that // the appropriate set of scopes is requested to prevent personal data leakage. if (context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated)) { // Ensure the user profile still exists in the database. var user = await services.Users.GetUserAsync(context.HttpContext.User); if (user == null) { context.Reject( error: OpenIdConnectConstants.Errors.ServerError, description: "An internal error has occurred."); return; } // Return an error if the username corresponds to the registered // email address and if the "email" scope has not been requested. if (services.Users.SupportsUserEmail && context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) && !context.Request.HasScope(OpenIdConnectConstants.Scopes.Email)) { // Retrieve the username and the email address associated with the user. var username = await services.Users.GetUserNameAsync(user); var email = await services.Users.GetEmailAsync(user); if (!string.IsNullOrEmpty(email) && string.Equals(username, email, StringComparison.OrdinalIgnoreCase)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'email' scope is required."); return; } } } // Run additional checks for prompt=none requests. if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal)) { // If the user is not authenticated, return an error to the client application. // See http://openid.net/specs/openid-connect-core-1_0.html#Authenticates if (!context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated)) { context.Reject( error: OpenIdConnectConstants.Errors.LoginRequired, description: "The user must be authenticated."); return; } // Ensure that the authentication cookie contains the required NameIdentifier claim. var identifier = context.HttpContext.User.GetClaim(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(identifier)) { context.Reject( error: OpenIdConnectConstants.Errors.ServerError, description: "The authorization request cannot be processed."); return; } // Extract the principal contained in the id_token_hint parameter. // If no principal can be extracted, an error is returned to the client application. var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme); if (principal == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required id_token_hint parameter is missing."); return; } // Ensure the client application is listed as a valid audience in the identity token // and that the identity token corresponds to the authenticated user. if (!principal.HasClaim(OpenIdConnectConstants.Claims.Audience, context.Request.ClientId) || !principal.HasClaim(ClaimTypes.NameIdentifier, identifier)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The id_token_hint parameter is invalid."); return; } } context.Validate(); }
public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context) { var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TApplication, TAuthorization, TScope, TToken> >(); // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid, // none and custom flows but OpenIddict uses a stricter policy rejecting unknown flows. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow() && !context.Request.IsNoneFlow()) { services.Logger.LogError("The authorization request was rejected because the '{ResponseType}' " + "response type is not supported.", context.Request.ResponseType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not supported."); return; } // Reject code flow authorization requests if the authorization code flow is not enabled. if (context.Request.IsAuthorizationCodeFlow() && !services.Options.IsAuthorizationCodeFlowEnabled()) { services.Logger.LogError("The authorization request was rejected because " + "the authorization code flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject implicit flow authorization requests if the implicit flow is not enabled. if (context.Request.IsImplicitFlow() && !services.Options.IsImplicitFlowEnabled()) { services.Logger.LogError("The authorization request was rejected because the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled. if (context.Request.IsHybridFlow() && (!services.Options.IsAuthorizationCodeFlowEnabled() || !services.Options.IsImplicitFlowEnabled())) { services.Logger.LogError("The authorization request was rejected because the " + "authorization code flow or the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled. if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) && !services.Options.IsRefreshTokenFlowEnabled()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed."); return; } // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked. // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { services.Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " + "response mode is not supported.", context.Request.ResponseMode); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified response_mode parameter is not supported."); return; } // Note: redirect_uri is not required for pure OAuth2 requests // but this provider uses a stricter policy making it mandatory, // as required by the OpenID Connect core specification. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest. if (string.IsNullOrEmpty(context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required redirect_uri parameter was missing."); return; } // Note: the OpenID Connect server middleware always ensures a // code_challenge_method can't be specified without code_challenge. if (!string.IsNullOrEmpty(context.Request.CodeChallenge)) { // Since the default challenge method (plain) is explicitly disallowed, // reject the authorization request if the code_challenge_method is missing. if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod)) { services.Logger.LogError("The authorization request was rejected because the " + "required 'code_challenge_method' parameter was missing."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'code_challenge_method' parameter must be specified."); return; } // Disallow the use of the unsecure code_challenge_method=plain method. // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information. if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain)) { services.Logger.LogError("The authorization request was rejected because the " + "'code_challenge_method' parameter was set to 'plain'."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified code_challenge_method parameter is not allowed."); return; } // Reject authorization requests that contain response_type=token when a code_challenge is specified. if (context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { services.Logger.LogError("The authorization request was rejected because the " + "specified response type was not compatible with PKCE."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified response_type parameter is not allowed when using PKCE."); return; } } // Retrieve the application details corresponding to the requested client_id. var application = await services.Applications.FindByClientIdAsync(context.ClientId); if (application == null) { services.Logger.LogError("The authorization request was rejected because the client " + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: ensure that your client_id is correct."); return; } if (!await services.Applications.ValidateRedirectUriAsync(application, context.RedirectUri)) { services.Logger.LogError("The authorization request was rejected because the redirect_uri " + "was invalid: '{RedirectUri}'.", context.RedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri."); return; } // To prevent downgrade attacks, ensure that authorization requests returning an access token directly // from the authorization endpoint are rejected if the client_id corresponds to a confidential application. // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting // the token request if the client_id corresponds to an unauthenticated confidential client. if (await services.Applications.IsConfidentialAsync(application) && context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Confidential clients are not allowed to retrieve " + "an access token from the authorization endpoint."); return; } // Run additional checks for prompt=none requests. if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal)) { // If the user is not authenticated, return an error to the client application. // See http://openid.net/specs/openid-connect-core-1_0.html#Authenticates if (!context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated)) { services.Logger.LogError("The prompt=none authorization request was rejected because the user was not logged in."); context.Reject( error: OpenIdConnectConstants.Errors.LoginRequired, description: "The user must be authenticated."); return; } // Ensure that the authentication cookie contains the required NameIdentifier claim. var identifier = context.HttpContext.User.GetClaim(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(identifier)) { services.Logger.LogError("The prompt=none authorization request was rejected because the user session " + "was invalid and didn't contain the mandatory ClaimTypes.NameIdentifier claim."); context.Reject( error: OpenIdConnectConstants.Errors.ServerError, description: "The authorization request cannot be processed."); return; } // Extract the principal contained in the id_token_hint parameter. // If no principal can be extracted, an error is returned to the client application. var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme); if (principal == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required id_token_hint parameter is missing."); return; } // Ensure the client application is listed as a valid audience in the identity token // and that the identity token corresponds to the authenticated user. if (!principal.HasClaim(OpenIdConnectConstants.Claims.Audience, context.Request.ClientId) || !principal.HasClaim(ClaimTypes.NameIdentifier, identifier)) { services.Logger.LogError("The prompt=none authorization request was rejected because the id_token_hint was invalid."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The id_token_hint parameter is invalid."); return; } } context.Validate(); }
public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context) { var options = (OpenIddictServerOptions)context.Options; // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid, // none and custom flows but OpenIddict uses a stricter policy rejecting none and custum flows. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow()) { _logger.LogError("The authorization request was rejected because the '{ResponseType}' " + "response type is not supported.", context.Request.ResponseType); context.Reject( error: OpenIddictConstants.Errors.UnsupportedResponseType, description: "The specified 'response_type' parameter is not supported."); return; } // Reject code flow authorization requests if the authorization code flow is not enabled. if (context.Request.IsAuthorizationCodeFlow() && !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.AuthorizationCode)) { _logger.LogError("The authorization request was rejected because " + "the authorization code flow was not enabled."); context.Reject( error: OpenIddictConstants.Errors.UnsupportedResponseType, description: "The specified 'response_type' parameter is not allowed."); return; } // Reject implicit flow authorization requests if the implicit flow is not enabled. if (context.Request.IsImplicitFlow() && !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.Implicit)) { _logger.LogError("The authorization request was rejected because the implicit flow was not enabled."); context.Reject( error: OpenIddictConstants.Errors.UnsupportedResponseType, description: "The specified 'response_type' parameter is not allowed."); return; } // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled. if (context.Request.IsHybridFlow() && (!options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.AuthorizationCode) || !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.Implicit))) { _logger.LogError("The authorization request was rejected because the " + "authorization code flow or the implicit flow was not enabled."); context.Reject( error: OpenIddictConstants.Errors.UnsupportedResponseType, description: "The specified 'response_type' parameter is not allowed."); return; } // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled. if (context.Request.HasScope(OpenIddictConstants.Scopes.OfflineAccess) && !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.RefreshToken)) { context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed."); return; } // Validates scopes, unless scope validation was explicitly disabled. if (!options.DisableScopeValidation) { var scopes = new HashSet <string>(context.Request.GetScopes(), StringComparer.Ordinal); scopes.ExceptWith(options.Scopes); // If all the specified scopes are registered in the options, avoid making a database lookup. if (scopes.Count != 0) { foreach (var scope in await _scopeManager.FindByNamesAsync(scopes.ToImmutableArray())) { scopes.Remove(await _scopeManager.GetNameAsync(scope)); } } // If at least one scope was not recognized, return an error. if (scopes.Count != 0) { _logger.LogError("The authentication request was rejected because invalid scopes were specified: {Scopes}.", scopes); context.Reject( error: OpenIddictConstants.Errors.InvalidScope, description: "The specified 'scope' parameter is not valid."); return; } } // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked. // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { _logger.LogError("The authorization request was rejected because the '{ResponseMode}' " + "response mode is not supported.", context.Request.ResponseMode); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The specified 'response_mode' parameter is not supported."); return; } // Note: redirect_uri is not required for pure OAuth2 requests // but this provider uses a stricter policy making it mandatory, // as required by the OpenID Connect core specification. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest. if (string.IsNullOrEmpty(context.RedirectUri)) { context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The mandatory 'redirect_uri' parameter is missing."); return; } // Note: the OpenID Connect server middleware always ensures a // code_challenge_method can't be specified without code_challenge. if (!string.IsNullOrEmpty(context.Request.CodeChallenge)) { // Since the default challenge method (plain) is explicitly disallowed, // reject the authorization request if the code_challenge_method is missing. if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod)) { _logger.LogError("The authorization request was rejected because the " + "required 'code_challenge_method' parameter was missing."); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The 'code_challenge_method' parameter must be specified."); return; } // Disallow the use of the unsecure code_challenge_method=plain method. // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information. if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain)) { _logger.LogError("The authorization request was rejected because the " + "'code_challenge_method' parameter was set to 'plain'."); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The specified 'code_challenge_method' parameter is not allowed."); return; } // Reject authorization requests that contain response_type=token when a code_challenge is specified. if (context.Request.HasResponseType(OpenIddictConstants.ResponseTypes.Token)) { _logger.LogError("The authorization request was rejected because the " + "specified response type was not compatible with PKCE."); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The specified 'response_type' parameter is not allowed when using PKCE."); return; } } // Retrieve the application details corresponding to the requested client_id. var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { _logger.LogError("The authorization request was rejected because the client " + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The specified 'client_id' parameter is invalid."); return; } // Store the application entity as a request property to make it accessible // from the other provider methods without having to call the store twice. context.Request.SetProperty($"{OpenIddictConstants.Properties.Application}:{context.ClientId}", application); // To prevent downgrade attacks, ensure that authorization requests returning an access token directly // from the authorization endpoint are rejected if the client_id corresponds to a confidential application. // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting // the token request if the client_id corresponds to an unauthenticated confidential client. if (await _applicationManager.IsConfidentialAsync(application) && context.Request.HasResponseType(OpenIddictConstants.ResponseTypes.Token)) { context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "The specified 'response_type' parameter is not valid for this client application."); return; } // Reject the request if the application is not allowed to use the authorization endpoint. if (!options.IgnoreEndpointPermissions && !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Authorization)) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to use the authorization endpoint.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "This client application is not allowed to use the authorization endpoint."); return; } if (!options.IgnoreGrantTypePermissions) { // Reject the request if the application is not allowed to use the authorization code flow. if (context.Request.IsAuthorizationCodeFlow() && !await _applicationManager.HasPermissionAsync( application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode)) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to use the authorization code flow.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "The client application is not allowed to use the authorization code flow."); return; } // Reject the request if the application is not allowed to use the implicit flow. if (context.Request.IsImplicitFlow() && !await _applicationManager.HasPermissionAsync( application, OpenIddictConstants.Permissions.GrantTypes.Implicit)) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to use the implicit flow.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "The client application is not allowed to use the implicit flow."); return; } // Reject the request if the application is not allowed to use the authorization code/implicit flows. if (context.Request.IsHybridFlow() && (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode) || !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.Implicit))) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to use the hybrid flow.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "The client application is not allowed to use the hybrid flow."); return; } // Reject the request if the offline_access scope was request and if // the application is not allowed to use the refresh token grant type. if (context.Request.HasScope(OpenIddictConstants.Scopes.OfflineAccess) && !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken)) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to request the 'offline_access' scope.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The client application is not allowed to use the 'offline_access' scope."); return; } } // Ensure that the specified redirect_uri is valid and is associated with the client application. if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri)) { _logger.LogError("The authorization request was rejected because the redirect_uri " + "was invalid: '{RedirectUri}'.", context.RedirectUri); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The specified 'redirect_uri' parameter is not valid for this client application."); return; } // Unless permission enforcement was explicitly disabled, ensure // the client application is allowed to use the specified scopes. if (!options.IgnoreScopePermissions) { foreach (var scope in context.Request.GetScopes()) { // Avoid validating the "openid" and "offline_access" scopes as they represent protocol scopes. if (string.Equals(scope, OpenIddictConstants.Scopes.OfflineAccess, StringComparison.Ordinal) || string.Equals(scope, OpenIddictConstants.Scopes.OpenId, StringComparison.Ordinal)) { continue; } // Reject the request if the application is not allowed to use the iterated scope. if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.Scope + scope)) { _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + "was not allowed to use the scope {Scope}.", context.ClientId, scope); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "This client application is not allowed to use the specified scope."); return; } } } context.Validate(); await _eventService.PublishAsync(new OpenIddictServerEvents.ValidateAuthorizationRequest(context)); }
public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context) { var options = (OpenIddictOptions)context.Options; // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid, // none and custom flows but OpenIddict uses a stricter policy rejecting unknown flows. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow() && !context.Request.IsNoneFlow()) { Logger.LogError("The authorization request was rejected because the '{ResponseType}' " + "response type is not supported.", context.Request.ResponseType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not supported."); return; } // Reject code flow authorization requests if the authorization code flow is not enabled. if (context.Request.IsAuthorizationCodeFlow() && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode)) { Logger.LogError("The authorization request was rejected because " + "the authorization code flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject implicit flow authorization requests if the implicit flow is not enabled. if (context.Request.IsImplicitFlow() && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit)) { Logger.LogError("The authorization request was rejected because the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled. if (context.Request.IsHybridFlow() && (!options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode) || !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit))) { Logger.LogError("The authorization request was rejected because the " + "authorization code flow or the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, description: "The specified response_type parameter is not allowed."); return; } // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled. if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.RefreshToken)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed."); return; } // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked. // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict. if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " + "response mode is not supported.", context.Request.ResponseMode); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified response_mode parameter is not supported."); return; } // Note: redirect_uri is not required for pure OAuth2 requests // but this provider uses a stricter policy making it mandatory, // as required by the OpenID Connect core specification. // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest. if (string.IsNullOrEmpty(context.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The required redirect_uri parameter was missing."); return; } // Note: the OpenID Connect server middleware always ensures a // code_challenge_method can't be specified without code_challenge. if (!string.IsNullOrEmpty(context.Request.CodeChallenge)) { // Since the default challenge method (plain) is explicitly disallowed, // reject the authorization request if the code_challenge_method is missing. if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod)) { Logger.LogError("The authorization request was rejected because the " + "required 'code_challenge_method' parameter was missing."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'code_challenge_method' parameter must be specified."); return; } // Disallow the use of the unsecure code_challenge_method=plain method. // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information. if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain)) { Logger.LogError("The authorization request was rejected because the " + "'code_challenge_method' parameter was set to 'plain'."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified code_challenge_method parameter is not allowed."); return; } // Reject authorization requests that contain response_type=token when a code_challenge is specified. if (context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { Logger.LogError("The authorization request was rejected because the " + "specified response type was not compatible with PKCE."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The specified response_type parameter is not allowed when using PKCE."); return; } } // Retrieve the application details corresponding to the requested client_id. var application = await Applications.FindByClientIdAsync(context.ClientId, context.HttpContext.RequestAborted); if (application == null) { Logger.LogError("The authorization request was rejected because the client " + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Application not found in the database: ensure that your client_id is correct."); return; } // Ensure a redirect_uri was associated with the application. if (!await Applications.HasRedirectUriAsync(application, context.HttpContext.RequestAborted)) { Logger.LogError("The authorization request was rejected because no redirect_uri " + "was registered with the application '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, description: "The client application is not allowed to use interactive flows."); return; } // Ensure the redirect_uri is valid. if (!await Applications.ValidateRedirectUriAsync(application, context.RedirectUri, context.HttpContext.RequestAborted)) { Logger.LogError("The authorization request was rejected because the redirect_uri " + "was invalid: '{RedirectUri}'.", context.RedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid redirect_uri."); return; } // To prevent downgrade attacks, ensure that authorization requests returning an access token directly // from the authorization endpoint are rejected if the client_id corresponds to a confidential application. // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting // the token request if the client_id corresponds to an unauthenticated confidential client. if (await Applications.IsConfidentialAsync(application, context.HttpContext.RequestAborted) && context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Confidential clients are not allowed to retrieve " + "an access token from the authorization endpoint."); return; } context.Validate(); }