/// <summary>
        /// Validates the request.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="clientValidationResult">The client validation result.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">
        /// parameters
        /// or
        /// client
        /// </exception>
        public async Task <TokenRequestValidationResult> ValidateRequestAsync(NameValueCollection parameters, ClientSecretValidationResult clientValidationResult)
        {
            _logger.LogDebug("Start token request validation");

            _validatedRequest = new ValidatedTokenRequest
            {
                IssuerName                          = await _issuerNameService.GetCurrentAsync(),
                Raw                                 = parameters ?? throw new ArgumentNullException(nameof(parameters)),
                                            Options = _options
            };

            if (clientValidationResult == null)
            {
                throw new ArgumentNullException(nameof(clientValidationResult));
            }

            _validatedRequest.SetClient(clientValidationResult.Client, clientValidationResult.Secret, clientValidationResult.Confirmation);

            /////////////////////////////////////////////
            // check client protocol type
            /////////////////////////////////////////////
            if (_validatedRequest.Client.ProtocolType != IdentityServerConstants.ProtocolTypes.OpenIdConnect)
            {
                LogError("Invalid protocol type for client",
                         new
                {
                    clientId             = _validatedRequest.Client.ClientId,
                    expectedProtocolType = IdentityServerConstants.ProtocolTypes.OpenIdConnect,
                    actualProtocolType   = _validatedRequest.Client.ProtocolType
                });

                return(Invalid(OidcConstants.TokenErrors.InvalidClient));
            }

            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = parameters.Get(OidcConstants.TokenRequest.GrantType);

            if (grantType.IsMissing())
            {
                LogError("Grant type is missing");
                return(Invalid(OidcConstants.TokenErrors.UnsupportedGrantType));
            }

            if (grantType.Length > _options.InputLengthRestrictions.GrantType)
            {
                LogError("Grant type is too long");
                return(Invalid(OidcConstants.TokenErrors.UnsupportedGrantType));
            }

            _validatedRequest.GrantType = grantType;

            //////////////////////////////////////////////////////////
            // check for resource indicator and basic formatting
            //////////////////////////////////////////////////////////
            var resourceIndicators = parameters.GetValues(OidcConstants.TokenRequest.Resource) ?? Enumerable.Empty <string>();

            if (resourceIndicators?.Any(x => x.Length > _options.InputLengthRestrictions.ResourceIndicatorMaxLength) == true)
            {
                return(Invalid(OidcConstants.AuthorizeErrors.InvalidTarget, "Resource indicator maximum length exceeded"));
            }

            if (!resourceIndicators.AreValidResourceIndicatorFormat(_logger))
            {
                return(Invalid(OidcConstants.AuthorizeErrors.InvalidTarget, "Invalid resource indicator format"));
            }

            if (resourceIndicators.Count() > 1)
            {
                return(Invalid(OidcConstants.AuthorizeErrors.InvalidTarget, "Multiple resource indicators not supported on token endpoint."));
            }

            _validatedRequest.RequestedResourceIndicator = resourceIndicators.SingleOrDefault();


            //////////////////////////////////////////////////////////
            // run specific logic for grants
            //////////////////////////////////////////////////////////

            switch (grantType)
            {
            case OidcConstants.GrantTypes.AuthorizationCode:
                return(await RunValidationAsync(ValidateAuthorizationCodeRequestAsync, parameters));

            case OidcConstants.GrantTypes.ClientCredentials:
                return(await RunValidationAsync(ValidateClientCredentialsRequestAsync, parameters));

            case OidcConstants.GrantTypes.Password:
                return(await RunValidationAsync(ValidateResourceOwnerCredentialRequestAsync, parameters));

            case OidcConstants.GrantTypes.RefreshToken:
                return(await RunValidationAsync(ValidateRefreshTokenRequestAsync, parameters));

            case OidcConstants.GrantTypes.DeviceCode:
                return(await RunValidationAsync(ValidateDeviceCodeRequestAsync, parameters));

            default:
                return(await RunValidationAsync(ValidateExtensionGrantRequestAsync, parameters));
            }
        }
        /// <summary>
        /// Validates the current request.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            _logger.LogDebug("Start client validation");

            var fail = new ClientSecretValidationResult
            {
                IsError = true
            };

            var parsedSecret = await _parser.ParseAsync(context);

            if (parsedSecret == null)
            {
                await RaiseFailureEventAsync("unknown", "No client id found");

                _logger.LogError("No client identifier found");
                return(fail);
            }

            // load client
            var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id);

            if (client == null)
            {
                await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client");

                _logger.LogError("No client with id '{clientId}' found. aborting", parsedSecret.Id);
                return(fail);
            }

            SecretValidationResult secretValidationResult = null;

            if (!client.RequireClientSecret || client.IsImplicitOnly())
            {
                _logger.LogDebug("Public Client - skipping secret validation success");
            }
            else
            {
                secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret);

                if (secretValidationResult.Success == false)
                {
                    await RaiseFailureEventAsync(client.ClientId, "Invalid client secret");

                    _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId);

                    return(fail);
                }
            }

            _logger.LogDebug("Client validation success");

            var success = new ClientSecretValidationResult
            {
                IsError      = false,
                Client       = client,
                Secret       = parsedSecret,
                Confirmation = secretValidationResult?.Confirmation
            };

            await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type);

            return(success);
        }
        private DeviceAuthorizationRequestValidationResult ValidateClient(ValidatedDeviceAuthorizationRequest request, ClientSecretValidationResult clientValidationResult)
        {
            //////////////////////////////////////////////////////////
            // set client & secret
            //////////////////////////////////////////////////////////
            if (clientValidationResult == null)
            {
                throw new ArgumentNullException(nameof(clientValidationResult));
            }
            request.SetClient(clientValidationResult.Client, clientValidationResult.Secret);

            //////////////////////////////////////////////////////////
            // check if client protocol type is oidc
            //////////////////////////////////////////////////////////
            if (request.Client.ProtocolType != IdentityServerConstants.ProtocolTypes.OpenIdConnect)
            {
                LogError("Invalid protocol type for OIDC authorize endpoint", request.Client.ProtocolType, request);
                return(Invalid(request, OidcConstants.AuthorizeErrors.UnauthorizedClient, "Invalid protocol"));
            }

            //////////////////////////////////////////////////////////
            // check if client allows device flow
            //////////////////////////////////////////////////////////
            if (!request.Client.AllowedGrantTypes.Contains(GrantType.DeviceFlow))
            {
                LogError("Client not configured for device flow", GrantType.DeviceFlow, request);
                return(Invalid(request, OidcConstants.AuthorizeErrors.UnauthorizedClient));
            }

            return(Valid(request));
        }
Example #4
0
        /// <summary>
        /// Validates the request.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="clientValidationResult">The client validation result.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">
        /// parameters
        /// or
        /// client
        /// </exception>
        public async Task <TokenRequestValidationResult> ValidateRequestAsync(NameValueCollection parameters, ClientSecretValidationResult clientValidationResult)
        {
            _logger.LogDebug("Start token request validation");

            _validatedRequest = new ValidatedTokenRequest
            {
                Raw = parameters ?? throw new ArgumentNullException(nameof(parameters)),
                            Options = _options
            };

            if (clientValidationResult == null)
            {
                throw new ArgumentNullException(nameof(clientValidationResult));
            }

            _validatedRequest.SetClient(clientValidationResult.Client, clientValidationResult.Secret, clientValidationResult.Confirmation);

            /////////////////////////////////////////////
            // check client protocol type
            /////////////////////////////////////////////
            if (_validatedRequest.Client.ProtocolType != IdentityServerConstants.ProtocolTypes.OpenIdConnect)
            {
                LogError("Invalid protocol type for client",
                         new
                {
                    clientId             = _validatedRequest.Client.ClientId,
                    expectedProtocolType = IdentityServerConstants.ProtocolTypes.OpenIdConnect,
                    actualProtocolType   = _validatedRequest.Client.ProtocolType
                });

                return(Invalid(OidcConstants.TokenErrors.InvalidClient));
            }

            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = parameters.Get(OidcConstants.TokenRequest.GrantType);

            if (grantType.IsMissing())
            {
                LogError("Grant type is missing");
                return(Invalid(OidcConstants.TokenErrors.UnsupportedGrantType));
            }

            if (grantType.Length > _options.InputLengthRestrictions.GrantType)
            {
                LogError("Grant type is too long");
                return(Invalid(OidcConstants.TokenErrors.UnsupportedGrantType));
            }

            _validatedRequest.GrantType = grantType;

            switch (grantType)
            {
            case OidcConstants.GrantTypes.AuthorizationCode:
                return(await RunValidationAsync(ValidateAuthorizationCodeRequestAsync, parameters));

            case OidcConstants.GrantTypes.ClientCredentials:
                return(await RunValidationAsync(ValidateClientCredentialsRequestAsync, parameters));

            case OidcConstants.GrantTypes.Password:
                return(await RunValidationAsync(ValidateResourceOwnerCredentialRequestAsync, parameters));

            case OidcConstants.GrantTypes.RefreshToken:
                return(await RunValidationAsync(ValidateRefreshTokenRequestAsync, parameters));

            case OidcConstants.GrantTypes.DeviceCode:
                return(await RunValidationAsync(ValidateDeviceCodeRequestAsync, parameters));

            default:
                return(await RunValidationAsync(ValidateExtensionGrantRequestAsync, parameters));
            }
        }
        public async Task <DeviceAuthorizationRequestValidationResult> ValidateAsync(NameValueCollection parameters, ClientSecretValidationResult clientValidationResult)
        {
            _logger.LogDebug("Start device authorization request validation");

            var request = new ValidatedDeviceAuthorizationRequest
            {
                Raw = parameters ?? throw new ArgumentNullException(nameof(parameters)),
                            Options = _options
            };

            var clientResult = ValidateClient(request, clientValidationResult);

            if (clientResult.IsError)
            {
                return(clientResult);
            }

            var scopeResult = await ValidateScopeAsync(request);

            if (scopeResult.IsError)
            {
                return(scopeResult);
            }

            _logger.LogDebug("{clientId} device authorization request validation success", request.Client.ClientId);
            return(Valid(request));
        }