コード例 #1
0
        private async Task _validateAuthorizationCodeFlow(ValidateAuthorizationRequestContext context)
        {
            authservice = context.HttpContext.RequestServices.GetRequiredService <IValidateAuthorizationService>();
            if (authservice == null)
            {
                context.Reject(OpenIdConnectConstants.Errors.ServerError, "Failed to validate this authorization request");
                return;
            }
            if (string.IsNullOrEmpty(context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The required redirect_uri parameter was missing.");
                return;
            }


            if (!(await authservice.CheckClientIdExists(context.ClientId)))
            {
                context.Reject(error: OpenIdConnectConstants.Errors.InvalidClient, description: "Supplied Client Id was not a valid application Client Id.");
                return;
            }
            if (!(await authservice.CheckRedirectURIMatches(context.RedirectUri, context.ClientId)))
            {
                context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied Redirect URI was not valid for the supplied Client Id.");
                return;
            }
            if (!(await authservice.CheckScopesAreValid(context.Request.Scope)))
            {
                context.Reject(error: OpenIdConnectConstants.Errors.InvalidRequest, description: "Supplied scopes were was not valid Spotify Scopes.");
                return;
            }

            context.Validate();
        }
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>();

            // Retrieve the application details corresponding to the requested client_id.
            var application = await(from entity in database.Applications
                                    where entity.ApplicationID == context.ClientId
                                    select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);

            if (application == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Application not found in the database: ensure that your client_id is correct");

                return;
            }

            if (!string.IsNullOrEmpty(context.RedirectUri) &&
                !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Invalid redirect_uri");

                return;
            }

            context.Validate(application.RedirectUri);
        }
コード例 #3
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts authorization code or hybrid flow authorization requests
            // that don't result in an access token being returned directly from the authorization endpoint.
            // You may consider relaxing it to support the implicit flow. In this case, consider adding checks
            // rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() ||
                context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only response_type=code and response_type=id_token or " +
                    "response_type=code id_token are supported by this authorization server");

                return;
            }

            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified response_mode is unsupported.");

                return;
            }

            using (var database = new ApplicationContext()) {
                // Retrieve the application details corresponding to the requested client_id.
                var application = await(from entity in database.Applications
                                        where entity.ApplicationID == context.ClientId
                                        select entity).SingleOrDefaultAsync(context.OwinContext.Request.CallCancelled);

                if (application == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidClient,
                        description: "Application not found in the database: " +
                        "ensure that your client_id is correct");
                    return;
                }

                if (!string.IsNullOrEmpty(context.RedirectUri) &&
                    !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidClient,
                        description: "Invalid redirect_uri");

                    return;
                }

                context.Validate(application.RedirectUri);
            }
        }
コード例 #4
0
        public override Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts response_type=code authorization/authentication requests.
            // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
            // checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow is supported by this authorization server.");

                return(Task.FromResult(0));
            }

            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' is unsupported.");

                return(Task.FromResult(0));
            }

            IClientService clientService = (IClientService)context.HttpContext.RequestServices.GetService(typeof(IClientService));

            ClientModel client = clientService.Get(context.Request.ClientId);

            // || !string.Equals(context.Request.ClientSecret, client.ClientSecret, StringComparison.Ordinal)
            // Ensure the client_id parameter corresponds to the Postman client.
            if (client == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified client identifier is invalid.");

                return(Task.FromResult(0));
            }

            // Ensure the redirect_uri parameter corresponds to the Postman client.
            if (!string.Equals(context.Request.RedirectUri, client.RedirectUrl, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified 'redirect_uri' is invalid.");

                return(Task.FromResult(0));
            }

            context.Validate();

            return(Task.FromResult(0));
        }
コード例 #5
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts response_type=code authorization/authentication requests.
            // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
            // checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow is supported by this authorization server.");

                return;
            }

            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' is unsupported.");

                return;
            }

            var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>();

            // Retrieve the application details corresponding to the requested client_id.
            var application = await(from entity in database.Applications
                                    where entity.ApplicationID == context.ClientId
                                    select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);

            if (application == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified client identifier is invalid.");

                return;
            }

            if (!string.IsNullOrEmpty(context.RedirectUri) &&
                !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified 'redirect_uri' is invalid.");

                return;
            }

            context.Validate(application.RedirectUri);
        }
コード例 #6
0
        /// <summary>
        /// Represents an event called for each request to the authorization endpoint
        /// to determine if the request is valid and should continue.
        /// </summary>
        /// <param name="context">The context instance associated with this event.</param>
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts response_type=code authorization/authentication requests.
            // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
            // checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow is supported by this authorization server.");

                return;
            }

            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!context.Request.ResponseMode.IsNullOrWhiteSpace() && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' is unsupported.");

                return;
            }

            // Retrieve the application details corresponding to the requested client_id.
            var rockContext       = new RockContext();
            var authClientService = new AuthClientService(rockContext);
            var authClient        = await authClientService.GetByClientIdAsync(context.ClientId);

            if (authClient == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified client identifier is invalid.");

                return;
            }

            if (!context.RedirectUri.IsNullOrWhiteSpace() &&
                !string.Equals(context.RedirectUri, authClient.RedirectUri, StringComparison.OrdinalIgnoreCase))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified 'redirect_uri' is invalid.");

                return;
            }

            context.Validate(authClient.RedirectUri);
        }
コード例 #7
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts response_type=code authorization/authentication requests.
            // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
            // checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow())
            {
                context.Reject(
                    OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    "Only the authorization and implicit code flows are supported by this authorization server");

                return;
            }

            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    OpenIdConnectConstants.Errors.InvalidRequest,
                    "The specified response_mode is unsupported.");

                return;
            }

            // Retrieve the application details corresponding to the requested client_id.
            var application = await _applicationRepository.GetByIdAsync(context.ClientId);

            if (application == null)
            {
                context.Reject(
                    OpenIdConnectConstants.Errors.InvalidClient,
                    "Application not found in the database: ensure that your client_id is correct");

                return;
            }

            var redirectUrl = application.Urls.FirstOrDefault(item => item.Equals(context.RedirectUri, StringComparison.Ordinal));

            if (!string.IsNullOrEmpty(context.RedirectUri) && redirectUrl == null)
            {
                context.Reject(
                    OpenIdConnectConstants.Errors.InvalidClient,
                    "Invalid redirect_uri");

                return;
            }

            context.Validate(redirectUrl);
        }
コード例 #8
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            var request = context.Request;
            if (!request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: InvalidResponseMessage
                );

                return;
            }

            if (string.IsNullOrWhiteSpace(context.ClientId))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: InvalidClientMessage
                );

                return;
            }

            var application = await BookingContext.Applications
                .Where(a => a.Id == context.ClientId)
                .SingleOrDefaultAsync(context.HttpContext.RequestAborted);

            if (application == null || application.Type == ApplicationType.Introspection)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: InvalidClientMessage
                );

                return;
            }

            if (!MatchRedirectUrl(application, context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: InvalidClientMessage
                );

                return;
            }

            context.Validate();
        }
コード例 #9
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            _vService = context.HttpContext.RequestServices.GetRequiredService <ValidationService>();
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow())
            {
                context.Reject(OpenIdConnectConstants.Errors.UnsupportedResponseType,
                               "Only authorization code, refresh token, and token grant types are accepted by this authorization server.");

                return;
            }

            var clientId = context.ClientId;
            var rdi      = context.Request.RedirectUri;
            var state    = context.Request.State;
            var scope    = context.Request.Scope;

            if (string.IsNullOrWhiteSpace(clientId))
            {
                context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "client_id cannot be empty");
                return;
            }

            if (string.IsNullOrWhiteSpace(rdi))
            {
                context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "redirect_uri cannot be empty");
                return;
            }

            if (!await _vService.CheckClientIdIsValid(clientId))
            {
                context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied client id does not exist");
                return;
            }

            if (!await _vService.CheckRedirectUriMatchesClientId(clientId, rdi))
            {
                context.Reject(OpenIdConnectConstants.Errors.InvalidClient, "The supplied redirect uri is incorrect");
                return;
            }

            if (!_vService.CheckScopesAreValid(scope))
            {
                context.Reject(OpenIdConnectConstants.Errors.InvalidRequest, "One or all of the supplied scopes are invalid");
                return;
            }

            context.Validate();
        }
コード例 #10
0
        /// <summary>
        /// Validate wether the redirect uri is valid for the specific client .
        /// </summary>
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            var query  = new ClientRedirectUriValidator(context.ClientId, context.RedirectUri);
            var result = await ExecuteMessage(context, query);

            if (!result.Succeeded)
            {
                context.Reject(
                    error: "invalid_client",
                    description: "Invalid redirect uri");

                return;
            }

            context.Validate();
        }
コード例 #11
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            if (!context.Request.IsAuthorizationCodeFlow() &&
                !context.Request.IsClientCredentialsGrantType() &&
                !context.Request.IsImplicitFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow, client credentials code flow, and implicit grant code flows are supported by this server.");
                return;
            }

            await _validateAuthorizationCodeFlow(context);

            return;
        }
コード例 #12
0
        // Implement OnValidateAuthorizationRequest to support interactive flows (code/implicit/hybrid).
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            if (!context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow is supported by this authorization server.");
                return;
            }

            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() && !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' is unsupported.");
                return;
            }
            var database = context.HttpContext.RequestServices.GetRequiredService <EgenutviklingContext>();

            var application = await(from entity in database.Applications
                                    where entity.ApplicationID == context.ClientId
                                    select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);

            if (application == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified client identifier is invalid.");

                return;
            }

            if (!string.IsNullOrEmpty(context.RedirectUri) &&
                !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified 'redirect_uri' is invalid.");

                return;
            }

            context.Validate(application.RedirectUri);
        }
コード例 #13
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsImplicitFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Este servidor de autorización solo admite el código de autorización y el flujo implícito.");

                return;
            }

            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "El especificado 'response_mode' no es soportado.");

                return;
            }

            var aplicacion = await _repository.GetAplicacionClienteAsync(context.ClientId, context.HttpContext.RequestAborted);

            if (aplicacion == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "El identificador de cliente especificado no es válido.");

                return;
            }

            if (string.IsNullOrEmpty(context.RedirectUri) ||
                !string.Equals(context.RedirectUri, aplicacion.RedirigirUri, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "El especificado 'redirect_uri' es inválido.");
                return;
            }

            context.Validate(aplicacion.RedirigirUri);
        }
コード例 #14
0
        public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // Note: the OpenID Connect server middleware supports the authorization code, implicit and hybrid flows
            // but this authorization provider only accepts response_type=code authorization/authentication requests.
            // You may consider relaxing it to support the implicit or hybrid flows. In this case, consider adding
            // checks rejecting implicit/hybrid authorization requests when the client is a confidential application.
            if (!context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "Only the authorization code flow is supported by this authorization server");

                return;
            }

            var database = context.HttpContext.RequestServices.GetRequiredService <ApplicationContext>();

            // Retrieve the application details corresponding to the requested client_id.
            var application = await(from entity in database.Applications
                                    where entity.ApplicationID == context.ClientId
                                    select entity).SingleOrDefaultAsync(context.HttpContext.RequestAborted);

            if (application == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Application not found in the database: ensure that your client_id is correct");

                return;
            }

            if (!string.IsNullOrEmpty(context.RedirectUri) &&
                !string.Equals(context.RedirectUri, application.RedirectUri, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Invalid redirect_uri");

                return;
            }

            context.Validate(application.RedirectUri);
        }
コード例 #15
0
        public override Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
        {
            // ref: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/samples/Mvc/Mvc.Server/Providers/AuthorizationProvider.cs
            // Note: to support custom response modes, the OpenID Connect server middleware doesn't
            // reject unknown modes before the ApplyAuthorizationResponse event is invoked.
            // To ensure invalid modes are rejected early enough, a check is made here.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' is unsupported.");

                return(Task.CompletedTask);
            }

            // Retrieve the application details corresponding to the requested client_id.
            if (!String.Equals(context.ClientId, _beatriceSecurityConfiguration.OAuth.ClientId, StringComparison.Ordinal))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified client identifier is invalid.");

                return(Task.CompletedTask);
            }

            if (!String.IsNullOrEmpty(context.RedirectUri) &&
                !_beatriceSecurityConfiguration.OAuth.RedirectUrls.Any(x => x.StartsWith(context.RedirectUri)))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "The specified 'redirect_uri' is invalid.");

                return(Task.CompletedTask);
            }

            context.Validate(context.RedirectUri);
            return(Task.CompletedTask);
        }
コード例 #16
0
 public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
 {
     if (context.Request.IsPasswordGrantType())
     {
     }
 }
        public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context)
        {
            var options = (OpenIddictServerOptions)context.Options;

            // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid,
            // none and custom flows but OpenIddict uses a stricter policy rejecting none and custum flows.
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow())
            {
                _logger.LogError("The authorization request was rejected because the '{ResponseType}' " +
                                 "response type is not supported.", context.Request.ResponseType);

                context.Reject(
                    error: OpenIddictConstants.Errors.UnsupportedResponseType,
                    description: "The specified 'response_type' parameter is not supported.");

                return;
            }

            // Reject code flow authorization requests if the authorization code flow is not enabled.
            if (context.Request.IsAuthorizationCodeFlow() &&
                !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.AuthorizationCode))
            {
                _logger.LogError("The authorization request was rejected because " +
                                 "the authorization code flow was not enabled.");

                context.Reject(
                    error: OpenIddictConstants.Errors.UnsupportedResponseType,
                    description: "The specified 'response_type' parameter is not allowed.");

                return;
            }

            // Reject implicit flow authorization requests if the implicit flow is not enabled.
            if (context.Request.IsImplicitFlow() && !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.Implicit))
            {
                _logger.LogError("The authorization request was rejected because the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIddictConstants.Errors.UnsupportedResponseType,
                    description: "The specified 'response_type' parameter is not allowed.");

                return;
            }

            // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled.
            if (context.Request.IsHybridFlow() && (!options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.AuthorizationCode) ||
                                                   !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.Implicit)))
            {
                _logger.LogError("The authorization request was rejected because the " +
                                 "authorization code flow or the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIddictConstants.Errors.UnsupportedResponseType,
                    description: "The specified 'response_type' parameter is not allowed.");

                return;
            }

            // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled.
            if (context.Request.HasScope(OpenIddictConstants.Scopes.OfflineAccess) &&
                !options.GrantTypes.Contains(OpenIddictConstants.GrantTypes.RefreshToken))
            {
                context.Reject(
                    error: OpenIddictConstants.Errors.InvalidRequest,
                    description: "The 'offline_access' scope is not allowed.");

                return;
            }

            // Validates scopes, unless scope validation was explicitly disabled.
            if (!options.DisableScopeValidation)
            {
                var scopes = new HashSet <string>(context.Request.GetScopes(), StringComparer.Ordinal);
                scopes.ExceptWith(options.Scopes);

                // If all the specified scopes are registered in the options, avoid making a database lookup.
                if (scopes.Count != 0)
                {
                    foreach (var scope in await _scopeManager.FindByNamesAsync(scopes.ToImmutableArray()))
                    {
                        scopes.Remove(await _scopeManager.GetNameAsync(scope));
                    }
                }

                // If at least one scope was not recognized, return an error.
                if (scopes.Count != 0)
                {
                    _logger.LogError("The authentication request was rejected because invalid scopes were specified: {Scopes}.", scopes);

                    context.Reject(
                        error: OpenIddictConstants.Errors.InvalidScope,
                        description: "The specified 'scope' parameter is not valid.");

                    return;
                }
            }

            // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes
            // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked.
            // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                _logger.LogError("The authorization request was rejected because the '{ResponseMode}' " +
                                 "response mode is not supported.", context.Request.ResponseMode);

                context.Reject(
                    error: OpenIddictConstants.Errors.InvalidRequest,
                    description: "The specified 'response_mode' parameter is not supported.");

                return;
            }

            // Note: redirect_uri is not required for pure OAuth2 requests
            // but this provider uses a stricter policy making it mandatory,
            // as required by the OpenID Connect core specification.
            // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest.
            if (string.IsNullOrEmpty(context.RedirectUri))
            {
                context.Reject(
                    error: OpenIddictConstants.Errors.InvalidRequest,
                    description: "The mandatory 'redirect_uri' parameter is missing.");

                return;
            }

            // Note: the OpenID Connect server middleware always ensures a
            // code_challenge_method can't be specified without code_challenge.
            if (!string.IsNullOrEmpty(context.Request.CodeChallenge))
            {
                // Since the default challenge method (plain) is explicitly disallowed,
                // reject the authorization request if the code_challenge_method is missing.
                if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod))
                {
                    _logger.LogError("The authorization request was rejected because the " +
                                     "required 'code_challenge_method' parameter was missing.");

                    context.Reject(
                        error: OpenIddictConstants.Errors.InvalidRequest,
                        description: "The 'code_challenge_method' parameter must be specified.");

                    return;
                }

                // Disallow the use of the unsecure code_challenge_method=plain method.
                // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information.
                if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain))
                {
                    _logger.LogError("The authorization request was rejected because the " +
                                     "'code_challenge_method' parameter was set to 'plain'.");

                    context.Reject(
                        error: OpenIddictConstants.Errors.InvalidRequest,
                        description: "The specified 'code_challenge_method' parameter is not allowed.");

                    return;
                }

                // Reject authorization requests that contain response_type=token when a code_challenge is specified.
                if (context.Request.HasResponseType(OpenIddictConstants.ResponseTypes.Token))
                {
                    _logger.LogError("The authorization request was rejected because the " +
                                     "specified response type was not compatible with PKCE.");

                    context.Reject(
                        error: OpenIddictConstants.Errors.InvalidRequest,
                        description: "The specified 'response_type' parameter is not allowed when using PKCE.");

                    return;
                }
            }

            // Retrieve the application details corresponding to the requested client_id.
            var application = await _applicationManager.FindByClientIdAsync(context.ClientId);

            if (application == null)
            {
                _logger.LogError("The authorization request was rejected because the client " +
                                 "application was not found: '{ClientId}'.", context.ClientId);

                context.Reject(
                    error: OpenIddictConstants.Errors.InvalidRequest,
                    description: "The specified 'client_id' parameter is invalid.");

                return;
            }

            // Store the application entity as a request property to make it accessible
            // from the other provider methods without having to call the store twice.
            context.Request.SetProperty($"{OpenIddictConstants.Properties.Application}:{context.ClientId}", application);

            // To prevent downgrade attacks, ensure that authorization requests returning an access token directly
            // from the authorization endpoint are rejected if the client_id corresponds to a confidential application.
            // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting
            // the token request if the client_id corresponds to an unauthenticated confidential client.
            if (await _applicationManager.IsConfidentialAsync(application) &&
                context.Request.HasResponseType(OpenIddictConstants.ResponseTypes.Token))
            {
                context.Reject(
                    error: OpenIddictConstants.Errors.UnauthorizedClient,
                    description: "The specified 'response_type' parameter is not valid for this client application.");

                return;
            }

            // Reject the request if the application is not allowed to use the authorization endpoint.
            if (!options.IgnoreEndpointPermissions &&
                !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Authorization))
            {
                _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                 "was not allowed to use the authorization endpoint.", context.ClientId);

                context.Reject(
                    error: OpenIddictConstants.Errors.UnauthorizedClient,
                    description: "This client application is not allowed to use the authorization endpoint.");

                return;
            }

            if (!options.IgnoreGrantTypePermissions)
            {
                // Reject the request if the application is not allowed to use the authorization code flow.
                if (context.Request.IsAuthorizationCodeFlow() && !await _applicationManager.HasPermissionAsync(
                        application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode))
                {
                    _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                     "was not allowed to use the authorization code flow.", context.ClientId);

                    context.Reject(
                        error: OpenIddictConstants.Errors.UnauthorizedClient,
                        description: "The client application is not allowed to use the authorization code flow.");

                    return;
                }

                // Reject the request if the application is not allowed to use the implicit flow.
                if (context.Request.IsImplicitFlow() && !await _applicationManager.HasPermissionAsync(
                        application, OpenIddictConstants.Permissions.GrantTypes.Implicit))
                {
                    _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                     "was not allowed to use the implicit flow.", context.ClientId);

                    context.Reject(
                        error: OpenIddictConstants.Errors.UnauthorizedClient,
                        description: "The client application is not allowed to use the implicit flow.");

                    return;
                }

                // Reject the request if the application is not allowed to use the authorization code/implicit flows.
                if (context.Request.IsHybridFlow() &&
                    (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode) ||
                     !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.Implicit)))
                {
                    _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                     "was not allowed to use the hybrid flow.", context.ClientId);

                    context.Reject(
                        error: OpenIddictConstants.Errors.UnauthorizedClient,
                        description: "The client application is not allowed to use the hybrid flow.");

                    return;
                }

                // Reject the request if the offline_access scope was request and if
                // the application is not allowed to use the refresh token grant type.
                if (context.Request.HasScope(OpenIddictConstants.Scopes.OfflineAccess) &&
                    !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken))
                {
                    _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                     "was not allowed to request the 'offline_access' scope.", context.ClientId);

                    context.Reject(
                        error: OpenIddictConstants.Errors.InvalidRequest,
                        description: "The client application is not allowed to use the 'offline_access' scope.");

                    return;
                }
            }

            // Ensure that the specified redirect_uri is valid and is associated with the client application.
            if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri))
            {
                _logger.LogError("The authorization request was rejected because the redirect_uri " +
                                 "was invalid: '{RedirectUri}'.", context.RedirectUri);

                context.Reject(
                    error: OpenIddictConstants.Errors.InvalidRequest,
                    description: "The specified 'redirect_uri' parameter is not valid for this client application.");

                return;
            }

            // Unless permission enforcement was explicitly disabled, ensure
            // the client application is allowed to use the specified scopes.
            if (!options.IgnoreScopePermissions)
            {
                foreach (var scope in context.Request.GetScopes())
                {
                    // Avoid validating the "openid" and "offline_access" scopes as they represent protocol scopes.
                    if (string.Equals(scope, OpenIddictConstants.Scopes.OfflineAccess, StringComparison.Ordinal) ||
                        string.Equals(scope, OpenIddictConstants.Scopes.OpenId, StringComparison.Ordinal))
                    {
                        continue;
                    }

                    // Reject the request if the application is not allowed to use the iterated scope.
                    if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.Scope + scope))
                    {
                        _logger.LogError("The authorization request was rejected because the application '{ClientId}' " +
                                         "was not allowed to use the scope {Scope}.", context.ClientId, scope);

                        context.Reject(
                            error: OpenIddictConstants.Errors.InvalidRequest,
                            description: "This client application is not allowed to use the specified scope.");

                        return;
                    }
                }
            }

            context.Validate();

            await _eventService.PublishAsync(new OpenIddictServerEvents.ValidateAuthorizationRequest(context));
        }
コード例 #18
0
        public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context)
        {
            var options = (OpenIddictOptions)context.Options;

            // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid,
            // none and custom flows but OpenIddict uses a stricter policy rejecting unknown flows.
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() &&
                !context.Request.IsImplicitFlow() && !context.Request.IsNoneFlow())
            {
                Logger.LogError("The authorization request was rejected because the '{ResponseType}' " +
                                "response type is not supported.", context.Request.ResponseType);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not supported.");

                return;
            }

            // Reject code flow authorization requests if the authorization code flow is not enabled.
            if (context.Request.IsAuthorizationCodeFlow() &&
                !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode))
            {
                Logger.LogError("The authorization request was rejected because " +
                                "the authorization code flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject implicit flow authorization requests if the implicit flow is not enabled.
            if (context.Request.IsImplicitFlow() && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit))
            {
                Logger.LogError("The authorization request was rejected because the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled.
            if (context.Request.IsHybridFlow() && (!options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode) ||
                                                   !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit)))
            {
                Logger.LogError("The authorization request was rejected because the " +
                                "authorization code flow or the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled.
            if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) &&
                !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.RefreshToken))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The 'offline_access' scope is not allowed.");

                return;
            }

            // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes
            // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked.
            // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " +
                                "response mode is not supported.", context.Request.ResponseMode);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified response_mode parameter is not supported.");

                return;
            }

            // Note: redirect_uri is not required for pure OAuth2 requests
            // but this provider uses a stricter policy making it mandatory,
            // as required by the OpenID Connect core specification.
            // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest.
            if (string.IsNullOrEmpty(context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The required redirect_uri parameter was missing.");

                return;
            }

            // Note: the OpenID Connect server middleware always ensures a
            // code_challenge_method can't be specified without code_challenge.
            if (!string.IsNullOrEmpty(context.Request.CodeChallenge))
            {
                // Since the default challenge method (plain) is explicitly disallowed,
                // reject the authorization request if the code_challenge_method is missing.
                if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod))
                {
                    Logger.LogError("The authorization request was rejected because the " +
                                    "required 'code_challenge_method' parameter was missing.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The 'code_challenge_method' parameter must be specified.");

                    return;
                }

                // Disallow the use of the unsecure code_challenge_method=plain method.
                // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information.
                if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain))
                {
                    Logger.LogError("The authorization request was rejected because the " +
                                    "'code_challenge_method' parameter was set to 'plain'.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The specified code_challenge_method parameter is not allowed.");

                    return;
                }

                // Reject authorization requests that contain response_type=token when a code_challenge is specified.
                if (context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token))
                {
                    Logger.LogError("The authorization request was rejected because the " +
                                    "specified response type was not compatible with PKCE.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The specified response_type parameter is not allowed when using PKCE.");

                    return;
                }
            }

            // Retrieve the application details corresponding to the requested client_id.
            var application = await Applications.FindByClientIdAsync(context.ClientId, context.HttpContext.RequestAborted);

            if (application == null)
            {
                Logger.LogError("The authorization request was rejected because the client " +
                                "application was not found: '{ClientId}'.", context.ClientId);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Application not found in the database: ensure that your client_id is correct.");

                return;
            }

            // Ensure a redirect_uri was associated with the application.
            if (!await Applications.HasRedirectUriAsync(application, context.HttpContext.RequestAborted))
            {
                Logger.LogError("The authorization request was rejected because no redirect_uri " +
                                "was registered with the application '{ClientId}'.", context.ClientId);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnauthorizedClient,
                    description: "The client application is not allowed to use interactive flows.");

                return;
            }

            // Ensure the redirect_uri is valid.
            if (!await Applications.ValidateRedirectUriAsync(application, context.RedirectUri, context.HttpContext.RequestAborted))
            {
                Logger.LogError("The authorization request was rejected because the redirect_uri " +
                                "was invalid: '{RedirectUri}'.", context.RedirectUri);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Invalid redirect_uri.");

                return;
            }

            // To prevent downgrade attacks, ensure that authorization requests returning an access token directly
            // from the authorization endpoint are rejected if the client_id corresponds to a confidential application.
            // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting
            // the token request if the client_id corresponds to an unauthenticated confidential client.
            if (await Applications.IsConfidentialAsync(application, context.HttpContext.RequestAborted) &&
                context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "Confidential clients are not allowed to retrieve " +
                    "an access token from the authorization endpoint.");

                return;
            }

            context.Validate();
        }
コード例 #19
0
 // Implement OnValidateAuthorizationRequest to support interactive flows (code/implicit/hybrid).
 public override async Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
 {
 }
コード例 #20
0
        public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context)
        {
            var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TApplication, TAuthorization, TScope, TToken> >();

            // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid,
            // none and custom flows but OpenIddict uses a stricter policy rejecting unknown flows.
            if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() &&
                !context.Request.IsImplicitFlow() && !context.Request.IsNoneFlow())
            {
                services.Logger.LogError("The authorization request was rejected because the '{ResponseType}' " +
                                         "response type is not supported.", context.Request.ResponseType);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not supported.");

                return;
            }

            // Reject code flow authorization requests if the authorization code flow is not enabled.
            if (context.Request.IsAuthorizationCodeFlow() && !services.Options.IsAuthorizationCodeFlowEnabled())
            {
                services.Logger.LogError("The authorization request was rejected because " +
                                         "the authorization code flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject implicit flow authorization requests if the implicit flow is not enabled.
            if (context.Request.IsImplicitFlow() && !services.Options.IsImplicitFlowEnabled())
            {
                services.Logger.LogError("The authorization request was rejected because the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject hybrid flow authorization requests if the authorization code or the implicit flows are not enabled.
            if (context.Request.IsHybridFlow() && (!services.Options.IsAuthorizationCodeFlowEnabled() ||
                                                   !services.Options.IsImplicitFlowEnabled()))
            {
                services.Logger.LogError("The authorization request was rejected because the " +
                                         "authorization code flow or the implicit flow was not enabled.");

                context.Reject(
                    error: OpenIdConnectConstants.Errors.UnsupportedResponseType,
                    description: "The specified response_type parameter is not allowed.");

                return;
            }

            // Reject authorization requests that specify scope=offline_access if the refresh token flow is not enabled.
            if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) && !services.Options.IsRefreshTokenFlowEnabled())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The 'offline_access' scope is not allowed.");

                return;
            }

            // Note: the OpenID Connect server middleware supports the query, form_post and fragment response modes
            // and doesn't reject unknown/custom modes until the ApplyAuthorizationResponse event is invoked.
            // To ensure authorization requests are rejected early enough, an additional check is made by OpenIddict.
            if (!string.IsNullOrEmpty(context.Request.ResponseMode) && !context.Request.IsFormPostResponseMode() &&
                !context.Request.IsFragmentResponseMode() &&
                !context.Request.IsQueryResponseMode())
            {
                services.Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " +
                                         "response mode is not supported.", context.Request.ResponseMode);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The specified response_mode parameter is not supported.");

                return;
            }

            // Note: redirect_uri is not required for pure OAuth2 requests
            // but this provider uses a stricter policy making it mandatory,
            // as required by the OpenID Connect core specification.
            // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest.
            if (string.IsNullOrEmpty(context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The required redirect_uri parameter was missing.");

                return;
            }

            // Note: the OpenID Connect server middleware always ensures a
            // code_challenge_method can't be specified without code_challenge.
            if (!string.IsNullOrEmpty(context.Request.CodeChallenge))
            {
                // Since the default challenge method (plain) is explicitly disallowed,
                // reject the authorization request if the code_challenge_method is missing.
                if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod))
                {
                    services.Logger.LogError("The authorization request was rejected because the " +
                                             "required 'code_challenge_method' parameter was missing.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The 'code_challenge_method' parameter must be specified.");

                    return;
                }

                // Disallow the use of the unsecure code_challenge_method=plain method.
                // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information.
                if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain))
                {
                    services.Logger.LogError("The authorization request was rejected because the " +
                                             "'code_challenge_method' parameter was set to 'plain'.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The specified code_challenge_method parameter is not allowed.");

                    return;
                }

                // Reject authorization requests that contain response_type=token when a code_challenge is specified.
                if (context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token))
                {
                    services.Logger.LogError("The authorization request was rejected because the " +
                                             "specified response type was not compatible with PKCE.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The specified response_type parameter is not allowed when using PKCE.");

                    return;
                }
            }

            // Retrieve the application details corresponding to the requested client_id.
            var application = await services.Applications.FindByClientIdAsync(context.ClientId);

            if (application == null)
            {
                services.Logger.LogError("The authorization request was rejected because the client " +
                                         "application was not found: '{ClientId}'.", context.ClientId);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Application not found in the database: ensure that your client_id is correct.");

                return;
            }

            if (!await services.Applications.ValidateRedirectUriAsync(application, context.RedirectUri))
            {
                services.Logger.LogError("The authorization request was rejected because the redirect_uri " +
                                         "was invalid: '{RedirectUri}'.", context.RedirectUri);

                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Invalid redirect_uri.");

                return;
            }

            // To prevent downgrade attacks, ensure that authorization requests returning an access token directly
            // from the authorization endpoint are rejected if the client_id corresponds to a confidential application.
            // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting
            // the token request if the client_id corresponds to an unauthenticated confidential client.
            if (await services.Applications.IsConfidentialAsync(application) &&
                context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "Confidential clients are not allowed to retrieve " +
                    "an access token from the authorization endpoint.");

                return;
            }

            // Run additional checks for prompt=none requests.
            if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal))
            {
                // If the user is not authenticated, return an error to the client application.
                // See http://openid.net/specs/openid-connect-core-1_0.html#Authenticates
                if (!context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated))
                {
                    services.Logger.LogError("The prompt=none authorization request was rejected because the user was not logged in.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.LoginRequired,
                        description: "The user must be authenticated.");

                    return;
                }

                // Ensure that the authentication cookie contains the required NameIdentifier claim.
                var identifier = context.HttpContext.User.GetClaim(ClaimTypes.NameIdentifier);
                if (string.IsNullOrEmpty(identifier))
                {
                    services.Logger.LogError("The prompt=none authorization request was rejected because the user session " +
                                             "was invalid and didn't contain the mandatory ClaimTypes.NameIdentifier claim.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.ServerError,
                        description: "The authorization request cannot be processed.");

                    return;
                }

                // Extract the principal contained in the id_token_hint parameter.
                // If no principal can be extracted, an error is returned to the client application.
                var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme);

                if (principal == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The required id_token_hint parameter is missing.");

                    return;
                }

                // Ensure the client application is listed as a valid audience in the identity token
                // and that the identity token corresponds to the authenticated user.
                if (!principal.HasClaim(OpenIdConnectConstants.Claims.Audience, context.Request.ClientId) ||
                    !principal.HasClaim(ClaimTypes.NameIdentifier, identifier))
                {
                    services.Logger.LogError("The prompt=none authorization request was rejected because the id_token_hint was invalid.");

                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The id_token_hint parameter is invalid.");

                    return;
                }
            }

            context.Validate();
        }
コード例 #21
0
        public override async Task ValidateAuthorizationRequest([NotNull] ValidateAuthorizationRequestContext context)
        {
            var services = context.HttpContext.RequestServices.GetRequiredService <OpenIddictServices <TUser, TApplication> >();

            // Note: redirect_uri is not required for pure OAuth2 requests
            // but this provider uses a stricter policy making it mandatory,
            // as required by the OpenID Connect core specification.
            // See http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest.
            if (string.IsNullOrEmpty(context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "The required redirect_uri parameter was missing.");

                return;
            }

            // Retrieve the application details corresponding to the requested client_id.
            var application = await services.Applications.FindApplicationByIdAsync(context.ClientId);

            if (application == null)
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Application not found in the database: ensure that your client_id is correct.");

                return;
            }

            if (!await services.Applications.ValidateRedirectUriAsync(application, context.RedirectUri))
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidClient,
                    description: "Invalid redirect_uri.");

                return;
            }

            // To prevent downgrade attacks, ensure that authorization requests using the hybrid/implicit
            // flow are rejected if the client identifier corresponds to a confidential application.
            // Note: when using the authorization code grant, ValidateClientAuthentication is responsible of
            // rejecting the token request if the client_id corresponds to an unauthenticated confidential client.
            if (await services.Applications.IsConfidentialApplicationAsync(application) && !context.Request.IsAuthorizationCodeFlow())
            {
                context.Reject(
                    error: OpenIdConnectConstants.Errors.InvalidRequest,
                    description: "Confidential clients can only use response_type=code.");

                return;
            }

            // If the user is connected, ensure that a corresponding profile exists and that
            // the appropriate set of scopes is requested to prevent personal data leakage.
            if (context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated))
            {
                // Ensure the user profile still exists in the database.
                var user = await services.Users.GetUserAsync(context.HttpContext.User);

                if (user == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.ServerError,
                        description: "An internal error has occurred.");

                    return;
                }

                // Return an error if the username corresponds to the registered
                // email address and if the "email" scope has not been requested.
                if (services.Users.SupportsUserEmail && context.Request.HasScope(OpenIdConnectConstants.Scopes.Profile) &&
                    !context.Request.HasScope(OpenIdConnectConstants.Scopes.Email))
                {
                    // Retrieve the username and the email address associated with the user.
                    var username = await services.Users.GetUserNameAsync(user);

                    var email = await services.Users.GetEmailAsync(user);

                    if (!string.IsNullOrEmpty(email) && string.Equals(username, email, StringComparison.OrdinalIgnoreCase))
                    {
                        context.Reject(
                            error: OpenIdConnectConstants.Errors.InvalidRequest,
                            description: "The 'email' scope is required.");

                        return;
                    }
                }
            }

            // Run additional checks for prompt=none requests.
            if (string.Equals(context.Request.Prompt, "none", StringComparison.Ordinal))
            {
                // If the user is not authenticated, return an error to the client application.
                // See http://openid.net/specs/openid-connect-core-1_0.html#Authenticates
                if (!context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.LoginRequired,
                        description: "The user must be authenticated.");

                    return;
                }

                // Ensure that the authentication cookie contains the required NameIdentifier claim.
                var identifier = context.HttpContext.User.GetClaim(ClaimTypes.NameIdentifier);
                if (string.IsNullOrEmpty(identifier))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.ServerError,
                        description: "The authorization request cannot be processed.");

                    return;
                }

                // Extract the principal contained in the id_token_hint parameter.
                // If no principal can be extracted, an error is returned to the client application.
                var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme);

                if (principal == null)
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The required id_token_hint parameter is missing.");

                    return;
                }

                // Ensure the client application is listed as a valid audience in the identity token
                // and that the identity token corresponds to the authenticated user.
                if (!principal.HasClaim(OpenIdConnectConstants.Claims.Audience, context.Request.ClientId) ||
                    !principal.HasClaim(ClaimTypes.NameIdentifier, identifier))
                {
                    context.Reject(
                        error: OpenIdConnectConstants.Errors.InvalidRequest,
                        description: "The id_token_hint parameter is invalid.");

                    return;
                }
            }

            context.Validate();
        }
コード例 #22
0
 public Task ValidateAuthorizationRequest(ValidateAuthorizationRequestContext context)
 {
     throw new NotImplementedException();
 }