private async Task _validateAuthorizationTokenRequest(ValidateTokenRequestContext context) { // TODO increment user rate limit (nb this increment only happens in Validate) // TODO check user is within their rate limit for the requested client_id if (String.IsNullOrWhiteSpace(context.ClientId)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_id."); return; } else if (String.IsNullOrWhiteSpace(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_secret."); return; } if (String.IsNullOrWhiteSpace(context.Request.Code)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Missing credentials: ensure that you specified a value for code."); return; } context.Validate(); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Note: the OpenID Connect server middleware supports authorization code, refresh token, client credentials // and resource owner password credentials grant types but this authorization provider uses a safer policy // rejecting the last two ones. You may consider relaxing it to support the ROPC or client credentials grant types. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( OpenIdConnectConstants.Errors.UnsupportedGrantType, "Only authorization code and refresh token grant types " + "are accepted by this authorization server"); return; } // Note: client authentication is not mandatory for non-confidential client applications like mobile apps // (except when using the client credentials grant type) but this authorization server uses a safer policy // that makes client authentication mandatory and returns an error if client_id or client_secret is missing. // You may consider relaxing it to support the resource owner password credentials grant type // with JavaScript or desktop applications, where client credentials cannot be safely stored. // In this case, call context.Skip() to inform the server middleware the client is not trusted. if (string.IsNullOrEmpty(context.ClientId) || string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( OpenIdConnectConstants.Errors.InvalidRequest, "Missing credentials: ensure that your credentials were correctly " + "flowed in the request body or in the authorization header"); 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; } // Note: to mitigate brute force attacks, you SHOULD strongly consider applying // a key derivation function like PBKDF2 to slow down the secret validation process. // You SHOULD also consider using a time-constant comparer to prevent timing attacks. // For that, you can use the CryptoHelper library developed by @henkmollema: // https://github.com/henkmollema/CryptoHelper. If you don't need .NET Core support, // SecurityDriven.NET/inferno is a rock-solid alternative: http://securitydriven.net/inferno/ if (!string.Equals(context.ClientSecret, application.Secret, StringComparison.Ordinal)) { context.Reject( OpenIdConnectConstants.Errors.InvalidClient, "Invalid credentials: ensure that you specified a correct client_secret"); return; } context.Validate(); }
private async Task _validateClientCredentialsTokenRequest(ValidateTokenRequestContext context) { // TODO increment user rate limit (nb this increment only happens in Validate) authservice = context.HttpContext.RequestServices.GetRequiredService <IValidateAuthorizationService>(); if (authservice == null) { context.Reject(OpenIdConnectConstants.Errors.ServerError, "Failed to validate this authorization request"); return; } if (String.IsNullOrWhiteSpace(context.ClientId)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_id."); return; } else if (String.IsNullOrWhiteSpace(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_secret."); return; } else if (!(await authservice.CheckClientIdExists(context.ClientId))) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidClient, description: "Supplied Client Id was not a valid application Client Id."); return; } else if (!(await authservice.CheckSecretMatchesId(context.ClientId, context.ClientSecret))) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied Secret was not correct for the Client Id."); return; } context.Validate(); }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { string clientId = string.Empty; string clientSecret = string.Empty; Client client = null; _authService = (IAuthService)context.HttpContext.RequestServices.GetService(typeof(IAuthService)); if (context.ClientId == null) { //Remove the comments from the below line context.SetError, and invalidate context //if you want to force sending clientId/secrects once obtain access tokens. //context.Validate(); context.Reject("Nao foram fornecidas todas as credenciais necessarias"); return(Task.FromResult <object>(null)); } client = _authService.FindClient(context.ClientId); if (client == null) { context.Reject("O clientId fornecido nao eh valido"); return(Task.FromResult <object>(null)); } if (!client.Active) { context.Reject("O Client nao esta mais ativo"); return(Task.FromResult <object>(null)); } context.Validate(); return(Task.FromResult <object>(null)); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Note: the OpenID Connect server middleware supports authorization code, refresh token, client credentials // and resource owner password credentials grant types but this authorization provider uses a safer policy // rejecting the last two ones. You may consider relaxing it to support the ROPC or client credentials grant types. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code and refresh token grant types " + "are accepted by this authorization server"); return; } // Note: client authentication is not mandatory for non-confidential client applications like mobile apps // (except when using the client credentials grant type) but this authorization server uses a safer policy // that makes client authentication mandatory and returns an error if client_id or client_secret is missing. // You may consider relaxing it to support the resource owner password credentials grant type // with JavaScript or desktop applications, where client credentials cannot be safely stored. // In this case, call context.Skip() to inform the server middleware the client is not trusted. if (string.IsNullOrEmpty(context.ClientId) || string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Missing credentials: ensure that your credentials were correctly " + "flowed in the request body or in the authorization header"); 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.Equals(context.ClientSecret, application.Secret, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid credentials: ensure that you " + "specified a correct client_secret"); return; } context.Validate(); } }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // ref: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/README.md if (String.Equals(context.ClientId, _beatriceSecurityConfiguration.OAuth.ClientId, StringComparison.Ordinal) && String.Equals(context.ClientSecret, _beatriceSecurityConfiguration.OAuth.ClientSecret, StringComparison.Ordinal)) { context.Validate(); } return(Task.CompletedTask); }
/// <summary> /// Validates whether the client is a valid known application in our system. /// </summary> public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { if (!context.Request.IsRefreshTokenGrantType() && !context.Request.IsPasswordGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only password and refresh token grant types " + "are accepted by this authorization server"); return; } var query = new ValidateClientQuery(context.ClientId, context.ClientSecret); var result = await ExecuteQuery(context, query); if (!result.Succeeded) { context.Reject( error: "invalid_client", description: "Client not found in the database: ensure that your client_id is correct"); return; } context.HttpContext.Items.Add("as:clientAllowedOrigin", result.AllowedOrigin); if (context.Request.IsPasswordGrantType()) { // Resolve ASP.NET Core Identity's user manager from the DI container. var userManager = context.HttpContext.RequestServices.GetRequiredService <UserManager <IdentityUser> >(); var user = await userManager.FindByNameAsync(context.Request.Username); if (user == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid user details."); return; } // Reject the token request if email confirmation is required. //if (!(await userManager.IsEmailConfirmedAsync(user))) //{ // context.Reject( // error: OpenIdConnectConstants.Errors.InvalidGrant, // description: "Email confirmation is required for this account."); // return; //} } context.Validate(); }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Only allow resource owner credential flow if (!context.Request.IsPasswordGrantType()) { context.Reject( error: "unsupported_grant_type", description: "Only resource owner credentials " + "are accepted by this authorization server"); } context.Validate(); return(Task.FromResult <object>(null)); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Reject token requests that don't use grant_type=password or grant_type=refresh_token. if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject(error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only grant_type=password and refresh_token requests are accepted by this server."); return; } var client = _clientRepository.GetClient(context.ClientId, context.ClientSecret); if (client != null) { context.Validate(); } }
/// <summary> /// Represents an event called for each request to the token 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 ValidateTokenRequest(ValidateTokenRequestContext context) { // Note: the OpenID Connect server middleware supports authorization code, refresh token, client credentials // and resource owner password credentials grant types but this authorization provider uses a safer policy // rejecting the last two ones. You may consider relaxing it to support the ROPC or client credentials grant types. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsTokenRequest()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code and refresh token grant types " + "are accepted by this authorization server."); return; } // Note: client authentication is not mandatory for non-confidential client applications like mobile apps // (except when using the client credentials grant type) but this authorization server uses a safer policy // that makes client authentication mandatory and returns an error if client_id or client_secret is missing. // You may consider relaxing it to support the resource owner password credentials grant type // with JavaScript or desktop applications, where client credentials cannot be safely stored. // In this case, call context.Skip() to inform the server middleware the client is not trusted. if (context.ClientId.IsNullOrWhiteSpace() || context.ClientSecret.IsNullOrWhiteSpace()) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The mandatory 'client_id'/'client_secret' parameters are missing."); return; } // Retrieve the application details corresponding to the requested client_id. var rockContext = new RockContext(); var authClientService = new AuthClientService(rockContext); var authClient = await authClientService.GetByClientIdAndSecretAsync(context.ClientId, context.ClientSecret); if (authClient == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client credentials are invalid."); return; } context.Validate(); }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Reject the token request if it doesn't specify grant_type=authorization_code, // grant_type=password or grant_type=refresh_token. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only grant_type=authorization_code, grant_type=password or " + "grant_type=refresh_token are accepted by this server."); return(Task.FromResult(0)); } // Since there's only one application and since it's a public client // (i.e a client that cannot keep its credentials private), call Skip() // to inform the server the request should be accepted without // enforcing client authentication. //context.Skip(); IClientService clientService = (IClientService)context.HttpContext.RequestServices.GetService(typeof(IClientService)); ClientModel client = clientService.Get(context.ClientId); if (client == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return(Task.FromResult(0)); } if (!string.Equals(context.ClientSecret, client.ClientSecret, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client credentials are invalid."); return(Task.FromResult(0)); } context.Validate(); return(Task.FromResult(0)); }
// Implement OnValidateTokenRequest to support flows using the token endpoint // (code/refresh token/password/client credentials/custom grant). public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code and refresh token grant type are accepted by this authorization server."); return; } if (string.IsNullOrEmpty(context.ClientId) || string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The mandatory 'client_id'/'client_secret' parameters are missing"); 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.Equals(context.ClientSecret, application.Secret, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid"); return; } context.Validate(); } /*
/// <summary> /// Validates whether the client is a valid known application in our system. /// </summary> public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { var query = new ClientValidator(context.ClientId, context.ClientSecret); var result = await ExecuteMessage(context, query); if (!result.Succeeded) { context.Reject( error: "invalid_client", description: "Client not found in the database: ensure that your client_id is correct"); return; } context.HttpContext.Items.Add("as:clientAllowedOrigin", result.AllowedOrigin); context.Validate(); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsPasswordGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: @"Este servidor de autorización solo acepta el código de autorización, los tipos de concesión de token de actualización y grant_type=password."); return; } if (string.IsNullOrEmpty(context.ClientId) || string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Faltan los parametros obligatorios 'client_id'/'client_secret'."); 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.Equals(context.ClientSecret, aplicacion.Secreto, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Las credenciales especificadas del cliente son inválidas."); return; } context.Validate(); }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Reject token requests that don't use grant_type=password or grant_type=refresh_token. if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only grant_type=password and refresh_token " + "requests are accepted by this server."); return(Task.CompletedTask); } if (string.Equals(context.ClientId, "client_id", StringComparison.Ordinal) && string.Equals(context.ClientSecret, "client_secret", StringComparison.Ordinal)) { context.Validate(); } return(Task.CompletedTask); }
public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { var options = (OpenIddictServerOptions)context.Options; // Reject token requests that don't specify a supported grant type. if (!options.GrantTypes.Contains(context.Request.GrantType)) { _logger.LogError("The token request was rejected because the '{GrantType}' " + "grant type is not supported.", context.Request.GrantType); context.Reject( error: OpenIddictConstants.Errors.UnsupportedGrantType, description: "The specified 'grant_type' parameter is not supported."); return; } // Reject token 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; } // Optimization: the OpenID Connect server middleware automatically rejects grant_type=authorization_code // requests missing the redirect_uri parameter if one was specified in the initial authorization request. // Since OpenIddict doesn't allow redirect_uri-less authorization requests, an earlier check can be made here, // which saves the OpenID Connect server middleware from having to deserialize the authorization code ticket. // See http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation for more information. if (context.Request.IsAuthorizationCodeGrantType() && string.IsNullOrEmpty(context.Request.RedirectUri)) { context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The mandatory 'redirect_uri' parameter is missing."); return; } // Note: the OpenID Connect server middleware allows returning a refresh token with grant_type=client_credentials, // though it's usually not recommended by the OAuth2 specification. To encourage developers to make a new // grant_type=client_credentials request instead of using refresh tokens, OpenIddict uses a stricter policy // that rejects grant_type=client_credentials requests containing the 'offline_access' scope. // See https://tools.ietf.org/html/rfc6749#section-4.4.3 for more information. if (context.Request.IsClientCredentialsGrantType() && context.Request.HasScope(OpenIddictConstants.Scopes.OfflineAccess)) { context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not valid for the specified 'grant_type' parameter."); 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 token 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; } } // Optimization: the OpenID Connect server middleware automatically rejects grant_type=client_credentials // requests when validation is skipped but an earlier check is made here to avoid making unnecessary // database roundtrips to retrieve the client application corresponding to the client_id. if (context.Request.IsClientCredentialsGrantType() && (string.IsNullOrEmpty(context.Request.ClientId) || string.IsNullOrEmpty(context.Request.ClientSecret))) { context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The 'client_id' and 'client_secret' parameters are " + "required when using the client credentials grant."); return; } // At this stage, skip client authentication if the client identifier is missing // or reject the token request if client identification is set as required. // Note: the OpenID Connect server middleware will automatically ensure that // the calling application cannot use an authorization code or a refresh token // if it's not the intended audience, even if client authentication was skipped. if (string.IsNullOrEmpty(context.ClientId)) { // Reject the request if client identification is mandatory. if (!options.AcceptAnonymousClients) { _logger.LogError("The token request was rejected becaused the " + "mandatory client_id parameter was missing or empty."); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The mandatory 'client_id' parameter is missing."); return; } _logger.LogDebug("The token request validation process was partially skipped " + "because the 'client_id' parameter was missing or empty."); context.Skip(); return; } // Retrieve the application details corresponding to the requested client_id. var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { _logger.LogError("The token request was rejected because the client " + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidClient, description: "The specified 'client_id' parameter is invalid."); return; } // Reject the request if the application is not allowed to use the token endpoint. if (!options.IgnoreEndpointPermissions && !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Token)) { _logger.LogError("The token request was rejected because the application '{ClientId}' " + "was not allowed to use the token endpoint.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "This client application is not allowed to use the token endpoint."); return; } if (!options.IgnoreGrantTypePermissions) { // Reject the request if the application is not allowed to use the specified grant type. if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.GrantType + context.Request.GrantType)) { _logger.LogError("The token request was rejected because the application '{ClientId}' was not allowed to " + "use the specified grant type: {GrantType}.", context.ClientId, context.Request.GrantType); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "This client application is not allowed to use the specified grant type."); 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 token 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; } } // 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 token 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; } } } if (await _applicationManager.IsPublicAsync(application)) { // Note: public applications are not allowed to use the client credentials grant. if (context.Request.IsClientCredentialsGrantType()) { _logger.LogError("The token request was rejected because the public client application '{ClientId}' " + "was not allowed to use the client credentials grant.", context.Request.ClientId); context.Reject( error: OpenIddictConstants.Errors.UnauthorizedClient, description: "The specified 'grant_type' parameter is not valid for this client application."); return; } // Reject token requests containing a client_secret when the client is a public application. if (!string.IsNullOrEmpty(context.ClientSecret)) { _logger.LogError("The token request was rejected because the public application '{ClientId}' " + "was not allowed to send a client secret.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidRequest, description: "The 'client_secret' parameter is not valid for this client application."); return; } _logger.LogDebug("The token request validation process was not fully validated because " + "the client '{ClientId}' was a public application.", context.ClientId); // If client authentication cannot be enforced, call context.Skip() to inform // the OpenID Connect server middleware that the caller cannot be fully trusted. context.Skip(); return; } // Confidential and hybrid applications MUST authenticate // to protect them from impersonation attacks. if (string.IsNullOrEmpty(context.ClientSecret)) { _logger.LogError("The token request was rejected because the confidential or hybrid application " + "'{ClientId}' didn't specify a client secret.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidClient, description: "The 'client_secret' parameter required for this client application is missing."); return; } if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret)) { _logger.LogError("The token request was rejected because the confidential or hybrid application " + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIddictConstants.Errors.InvalidClient, description: "The specified client credentials are invalid."); return; } context.Validate(); await _eventDispatcher.DispatchAsync(new OpenIddictServerEvents.ValidateTokenRequest(context)); }
public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { var applications = context.HttpContext.RequestServices.GetRequiredService <OpenIddictApplicationManager <TApplication> >(); var logger = context.HttpContext.RequestServices.GetRequiredService <ILogger <OpenIddictProvider <TApplication, TAuthorization, TScope, TToken> > >(); var options = context.HttpContext.RequestServices.GetRequiredService <IOptions <OpenIddictOptions> >(); // Reject token requests that don't specify a supported grant type. if (!options.Value.GrantTypes.Contains(context.Request.GrantType)) { logger.LogError("The token request was rejected because the '{Grant}' " + "grant is not supported.", context.Request.GrantType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "The specified grant_type is not supported by this authorization server."); return; } // Reject token requests that specify scope=offline_access if the refresh token flow is not enabled. if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) && !options.Value.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.RefreshToken)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed."); return; } // Optimization: the OpenID Connect server middleware automatically rejects grant_type=authorization_code // requests missing the redirect_uri parameter if one was specified in the initial authorization request. // Since OpenIddict doesn't allow redirect_uri-less authorization requests, an earlier check can be made here, // which saves the OpenID Connect server middleware from having to deserialize the authorization code ticket. // See http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation for more information. if (context.Request.IsAuthorizationCodeGrantType() && string.IsNullOrEmpty(context.Request.RedirectUri)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The mandatory 'redirect_uri' parameter was missing."); return; } // Note: the OpenID Connect server middleware allows returning a refresh token with grant_type=client_credentials, // though it's usually not recommended by the OAuth2 specification. To encourage developers to make a new // grant_type=client_credentials request instead of using refresh tokens, OpenIddict uses a stricter policy // that rejects grant_type=client_credentials requests containing the 'offline_access' scope. // See https://tools.ietf.org/html/rfc6749#section-4.4.3 for more information. if (context.Request.IsClientCredentialsGrantType() && context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed when using grant_type=client_credentials."); return; } // Optimization: the OpenID Connect server middleware automatically rejects grant_type=client_credentials // requests when validation is skipped but an earlier check is made here to avoid making unnecessary // database roundtrips to retrieve the client application corresponding to the client_id. if (context.Request.IsClientCredentialsGrantType() && (string.IsNullOrEmpty(context.Request.ClientId) || string.IsNullOrEmpty(context.Request.ClientSecret))) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Client applications must be authenticated to use the client credentials grant."); return; } // At this stage, skip client authentication if the client identifier is missing // or reject the token request if client identification is set as required. // Note: the OpenID Connect server middleware will automatically ensure that // the calling application cannot use an authorization code or a refresh token // if it's not the intended audience, even if client authentication was skipped. if (string.IsNullOrEmpty(context.ClientId)) { // Reject the request if client identification is mandatory. if (options.Value.RequireClientIdentification) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The mandatory 'client_id' parameter was missing."); return; } logger.LogDebug("The token request validation process was partially skipped " + "because the 'client_id' parameter was missing or empty."); context.Skip(); 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 token 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 applications.IsPublicAsync(application, context.HttpContext.RequestAborted)) { // Note: public applications are not allowed to use the client credentials grant. if (context.Request.IsClientCredentialsGrantType()) { logger.LogError("The token request was rejected because the public client application '{ClientId}' " + "was not allowed to use the client credentials grant.", context.Request.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, description: "Public clients are not allowed to use the client credentials grant."); return; } // Reject tokens requests containing a client_secret when the client is a public application. if (!string.IsNullOrEmpty(context.ClientSecret)) { logger.LogError("The token request was rejected because the public application '{ClientId}' " + "was not allowed to send a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Public clients are not allowed to send a client_secret."); return; } logger.LogInformation("The token request validation process was not fully validated because " + "the client '{ClientId}' was a public application.", context.ClientId); // If client authentication cannot be enforced, call context.Skip() to inform // the OpenID Connect server middleware that the caller cannot be fully trusted. context.Skip(); return; } // Confidential applications MUST authenticate // to protect them from impersonation attacks. if (string.IsNullOrEmpty(context.ClientSecret)) { logger.LogError("The token request was rejected because the confidential application " + "'{ClientId}' didn't specify a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_secret."); return; } if (!await applications.ValidateClientSecretAsync(application, context.ClientSecret, context.HttpContext.RequestAborted)) { logger.LogError("The token request was rejected because the confidential application " + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid credentials: ensure that you specified a correct client_secret."); return; } context.Validate(); }
public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication, TAuthorization, TScope, TToken> >(); // Reject token requests that don't specify a supported grant type. if (!services.Options.GrantTypes.Contains(context.Request.GrantType)) { services.Logger.LogError("The token request was rejected because the '{Grant}' " + "grant is not supported.", context.Request.GrantType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "The specified grant_type is not supported by this authorization server."); return; } // Reject token 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 allows returning a refresh token with grant_type=client_credentials, // though it's usually not recommended by the OAuth2 specification. To encourage developers to make a new // grant_type=client_credentials request instead of using refresh tokens, OpenIddict uses a stricter policy // that rejects grant_type=client_credentials requests containing the 'offline_access' scope. // See https://tools.ietf.org/html/rfc6749#section-4.4.3 for more information. if (context.Request.IsClientCredentialsGrantType() && context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The 'offline_access' scope is not allowed when using grant_type=client_credentials."); return; } // Note: the OpenID Connect server middleware rejects grant_type=client_credentials requests // when validation is skipped but an early check is made here to avoid making unnecessary // database roundtrips to retrieve the client application corresponding to the client_id. if (context.Request.IsClientCredentialsGrantType() && (string.IsNullOrEmpty(context.Request.ClientId) || string.IsNullOrEmpty(context.Request.ClientSecret))) { services.Logger.LogError("The token request was rejected because the client credentials were missing."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Client applications must be authenticated to use the client credentials grant."); return; } // Note: though required by the OpenID Connect specification for the refresh token grant, // client authentication is not mandatory for non-confidential client applications in OAuth2. // To avoid breaking OAuth2 scenarios, OpenIddict uses a relaxed policy that allows // public applications to use the refresh token grant without having to authenticate. // See http://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken // and https://tools.ietf.org/html/rfc6749#section-6 for more information. // At this stage, skip client authentication if the client identifier is missing. // Note: the OpenID Connect server middleware will automatically ensure that // the calling application cannot use an authorization code or a refresh token // if it's not the intended audience, even if client authentication was skipped. if (string.IsNullOrEmpty(context.ClientId)) { services.Logger.LogInformation("The token request validation process was skipped " + "because the client_id parameter was missing or empty."); context.Skip(); 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 token 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.IsPublicAsync(application)) { // Note: public applications are not allowed to use the client credentials grant. if (context.Request.IsClientCredentialsGrantType()) { services.Logger.LogError("The token request was rejected because the public client application '{ClientId}' " + "was not allowed to use the client credentials grant.", context.Request.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, description: "Public clients are not allowed to use the client credentials grant."); return; } // Reject tokens requests containing a client_secret when the client is a public application. if (!string.IsNullOrEmpty(context.ClientSecret)) { services.Logger.LogError("The token request was rejected because the public application '{ClientId}' " + "was not allowed to send a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Public clients are not allowed to send a client_secret."); return; } services.Logger.LogInformation("The token request validation process was not fully validated because " + "the client '{ClientId}' was a public application.", context.ClientId); // If client authentication cannot be enforced, call context.Skip() to inform // the OpenID Connect server middleware that the caller cannot be fully trusted. context.Skip(); return; } // Confidential applications MUST authenticate // to protect them from impersonation attacks. if (string.IsNullOrEmpty(context.ClientSecret)) { services.Logger.LogError("The token request was rejected because the confidential application " + "'{ClientId}' didn't specify a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_secret."); return; } if (!await services.Applications.ValidateSecretAsync(application, context.ClientSecret)) { services.Logger.LogError("The token request was rejected because the confidential application " + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid credentials: ensure that you specified a correct client_secret."); return; } context.Validate(); }
public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { context.Validate(); return(Task.CompletedTask); }
private async Task _validateRefreshTokenRequest(ValidateTokenRequestContext context) { authservice = context.HttpContext.RequestServices.GetRequiredService <IValidateAuthorizationService>(); if (authservice == null) { context.Reject(OpenIdConnectConstants.Errors.ServerError, "Failed to validate this authorization request"); return; } IRateLimitService rls = context.HttpContext.RequestServices.GetRequiredService <IRateLimitService>(); if (rls == null) { context.Reject(OpenIdConnectConstants.Errors.ServerError, "Failed to validate this authorization request"); return; } // TODO increment user rate limit (nb this increment only happens in Validate) if (String.IsNullOrWhiteSpace(context.Request.RefreshToken)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Missing parameter: ensure that you specified a refresh_token."); } AuthenticateResult ar = await context.HttpContext.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme); AuthenticationTicket at = ar.Ticket; if (ar == null) { context.Reject(); return; } else if (ar.Principal == null) { context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied refresh token was not valid"); return; } else if (ar.Principal.Identity == null) { context.Reject(); return; } else if (!ar.Principal.Identity.IsAuthenticated) { context.Reject(); return; } /** here we do the legwork of validating that: * the client application still exists, * the supplied secret still matches, * the user's refresh and access tokens haven't been revoked, * the user isn't rate limited */ List <Claim> claims = ar.Principal.Claims.ToList(); var gtype = claims.Find(x => x.Type == "grant_type"); var userid = claims.Find(x => x.Type == "sub"); var clientSecret = context.ClientSecret; if (gtype == null || string.IsNullOrWhiteSpace(gtype.Value)) { context.Reject(); } if (userid == null || string.IsNullOrWhiteSpace(userid.Value)) { context.Reject(); } if (!await authservice.CheckClientIdExists(context.ClientId)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied client id no longer exists."); return; } else if (!await authservice.CheckSecretMatchesId(context.ClientId, context.ClientSecret)) { context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied client secret is no longer valid."); return; } else if (!await authservice.CheckTokenNotRevoked(gtype.Value, context.Request.RefreshToken)) { context.Reject(OpenIdConnectConstants.Errors.AccessDenied, "The supplied token has been revoked. Please re-authenticate."); } //TODO come back to this - rls is no longer our preferred service. _mc.RateLimits should be our goto else if (!(await rls.UserWithinRateLimit(userid.Value)) && !(await rls.UserWithinAppRateLimit(context.ClientId, userid.Value, gtype.Value))) { context.Reject(RateLimits.RateLimitExceededError, RateLimits.RateLimitExceededErrorDescription); return; } await rls.IncrementUserAPICallCount(userid.Value, context.ClientId); context.Validate(); }
// // Summary: // Represents an event called for each request to the token endpoint to determine // if the request is valid and should continue to be processed. // // Parameters: // context: // The context instance associated with this event. // // Returns: // A System.Threading.Tasks.Task that can be used to monitor the asynchronous operation. public override Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Reject the token request if it doesn't specify grant_type=authorization_code, // grant_type=password or grant_type=refresh_token. if (!context.Request.IsPasswordGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsClientCredentialsGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code, refresh token, client credentials grant types " + "are accepted by this authorization server."); return(Task.CompletedTask); } // Note: client authentication is not mandatory for non-confidential client applications like mobile apps // (except when using the client credentials grant type) but this authorization server uses a safer policy // that makes client authentication mandatory and returns an error if client_id or client_secret is missing. // You may consider relaxing it to support the resource owner password credentials grant type // with JavaScript or desktop applications, where client credentials cannot be safely stored. // In this case, call context.Skip() to inform the server middleware the client is not trusted. if (context.Request.IsClientCredentialsGrantType()) { if (string.IsNullOrEmpty(context.ClientId) || string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "The mandatory 'client_id'/'client_secret' parameters are missing."); return(Task.CompletedTask); } var client = _authService.FindUser(u => u.Id.ToString() == context.ClientId); if (client == null) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client identifier is invalid."); return(Task.CompletedTask); } // Note: to mitigate brute force attacks, you SHOULD strongly consider applying // a key derivation function like PBKDF2 to slow down the secret validation process. // You SHOULD also consider using a time-constant comparer to prevent timing attacks. // For that, you can use the CryptoHelper library developed by @henkmollema: // https://github.com/henkmollema/CryptoHelper. if (!_authService.ValidateRequestedClientCredentials(client, context.ClientId, context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The specified client credentials are invalid."); return(Task.CompletedTask); } context.Validate(); } else { context.Skip(); } return(Task.CompletedTask); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { VService = context.HttpContext.RequestServices.GetRequiredService <ValidationService>(); // We only accept "authorization_code", "refresh", "token" for this endpoint. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsClientCredentialsGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code, refresh token, and token grant types are accepted by this authorization server." ); } string clientid = null; string clientsecret = null; string redirecturi = null; string code = null; string refreshtoken = null; // Validating the Authorization Code Token Request if (context.Request.IsAuthorizationCodeGrantType()) { clientid = context.ClientId; clientsecret = context.ClientSecret; code = context.Request.Code; redirecturi = context.Request.RedirectUri; if (String.IsNullOrWhiteSpace(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_id cannot be empty" ); return; } else if (String.IsNullOrWhiteSpace(clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_secret cannot be empty" ); return; } else if (String.IsNullOrWhiteSpace(redirecturi)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "redirect_uri cannot be empty" ); return; } else if (!await VService.CheckClientIdIsValid(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client id was does not exist" ); return; } else if (!await VService.CheckClientIdAndSecretIsValid(clientid, clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client secret is invalid" ); return; } else if (!await VService.CheckRedirectURIMatchesClientId(clientid, redirecturi)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied redirect uri is incorrect" ); return; } context.Validate(); return; } // Validating the Refresh Code Token Request else if (context.Request.IsRefreshTokenGrantType()) { clientid = context.Request.ClientId; clientsecret = context.Request.ClientSecret; refreshtoken = context.Request.RefreshToken; if (String.IsNullOrWhiteSpace(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_id cannot be empty" ); return; } else if (String.IsNullOrWhiteSpace(clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_secret cannot be empty" ); return; } else if (!await VService.CheckClientIdIsValid(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client id does not exist" ); return; } else if (!await VService.CheckClientIdAndSecretIsValid(clientid, clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client secret is invalid" ); return; } else if (!await VService.CheckRefreshTokenIsValid(refreshtoken)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied refresh token is invalid" ); return; } context.Validate(); return; } // Validating Client Credentials Request, aka, 'token' else if (context.Request.IsClientCredentialsGrantType()) { clientid = context.ClientId; clientsecret = context.ClientSecret; if (String.IsNullOrWhiteSpace(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_id cannot be empty" ); return; } else if (String.IsNullOrWhiteSpace(clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "client_secret cannot be empty" ); return; } else if (!await VService.CheckClientIdIsValid(clientid)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client id does not exist" ); return; } else if (!await VService.CheckClientIdAndSecretIsValid(clientid, clientsecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "The supplied client secret is invalid" ); return; } context.Validate(); return; } else { context.Reject( error: OpenIdConnectConstants.Errors.ServerError, description: "Could not validate the token request" ); return; } }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { // Note: OpenIdConnectServerHandler supports authorization code, refresh token, // client credentials, resource owner password credentials and custom grants // but this authorization server uses a stricter policy rejecting custom grant types. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsPasswordGrantType() && !context.Request.IsClientCredentialsGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code, refresh token, client credentials " + "and password grants are accepted by this authorization server."); return; } // Note: though required by the OpenID Connect specification for the refresh token grant, // client authentication is not mandatory for non-confidential client applications in OAuth2. // To avoid breaking OAuth2 scenarios, OpenIddict uses a relaxed policy that allows // public applications to use the refresh token grant without having to authenticate. // See http://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken // and https://tools.ietf.org/html/rfc6749#section-6 for more information. // Skip client authentication if the client identifier is missing. // Note: ASOS will automatically ensure that the calling application // cannot use an authorization code or a refresh token if it's not // the intended audience, even if client authentication was skipped. if (string.IsNullOrEmpty(context.ClientId)) { context.Skip(); return; } //var database = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>(); var clientMgr = context.HttpContext.RequestServices.GetRequiredService <OidcClientManager>(); // Retrieve the application details corresponding to the requested client_id. var application = clientMgr.FindByClientId(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; } // Openiddict的做法不同,而是区分Public 和 Confidential,public的禁止传送client_secret if (!string.Equals(context.ClientSecret, application.Secret, StringComparison.Ordinal)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid credentials: ensure that you specified a correct client_secret"); return; } context.Validate(); }
public override async Task ValidateTokenRequest(ValidateTokenRequestContext context) { var request = context.Request; if (!request.IsAuthorizationCodeGrantType() && !request.IsRefreshTokenGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: InvalidGrantMessage ); 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 (application.Type == ApplicationType.Public) { if (!string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: InvalidClientMessage ); return; } context.Skip(); return; } if (!PasswordHasher.VerifyHashedPassword(application.Secret, context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: InvalidClientMessage ); return; } context.Validate(); }
public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication> >(); // Note: OpenIdConnectServerHandler supports authorization code, refresh token, // client credentials, resource owner password credentials and custom grants // but this authorization server uses a stricter policy rejecting custom grant types. if (!context.Request.IsAuthorizationCodeGrantType() && !context.Request.IsRefreshTokenGrantType() && !context.Request.IsPasswordGrantType() && !context.Request.IsClientCredentialsGrantType()) { context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, description: "Only authorization code, refresh token, client credentials " + "and password grants are accepted by this authorization server."); return; } // Note: though required by the OpenID Connect specification for the refresh token grant, // client authentication is not mandatory for non-confidential client applications in OAuth2. // To avoid breaking OAuth2 scenarios, OpenIddict uses a relaxed policy that allows // public applications to use the refresh token grant without having to authenticate. // See http://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken // and https://tools.ietf.org/html/rfc6749#section-6 for more information. // Skip client authentication if the client identifier is missing. // Note: ASOS will automatically ensure that the calling application // cannot use an authorization code or a refresh token if it's not // the intended audience, even if client authentication was skipped. if (string.IsNullOrEmpty(context.ClientId)) { context.Skip(); 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; } // Reject tokens requests containing a client_secret if the client application is not confidential. if (await services.Applications.IsPublicApplicationAsync(application) && !string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Public clients are not allowed to send a client_secret."); return; } // Confidential applications MUST authenticate // to protect them from impersonation attacks. else if (await services.Applications.IsConfidentialApplicationAsync(application)) { if (string.IsNullOrEmpty(context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Missing credentials: ensure that you specified a client_secret."); return; } if (!await services.Applications.ValidateSecretAsync(application, context.ClientSecret)) { context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, description: "Invalid credentials: ensure that you specified a correct client_secret."); return; } } context.Validate(); }