Beispiel #1
0
 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();
 }
Beispiel #2
0
        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();
        }
Beispiel #3
0
 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();
 }
Beispiel #4
0
        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();
            }
        }
Beispiel #6
0
        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();
        }
Beispiel #8
0
        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));
        }
Beispiel #9
0
        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();
            }
        }
Beispiel #10
0
        /// <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();
        }
Beispiel #14
0
        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();
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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));
        }
Beispiel #17
0
        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);
 }
Beispiel #20
0
        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);
        }
Beispiel #22
0
        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;
            }
        }
Beispiel #23
0
        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();
        }
Beispiel #25
0
        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();
        }