private async Task <TokenRequestValidationResult> ValidateResourceOwnerCredentialRequestAsync(NameValueCollection parameters) { _logger.LogDebug("Start resource owner password token request validation"); ///////////////////////////////////////////// // check if client is authorized for grant type ///////////////////////////////////////////// if (!_validatedRequest.Client.AllowedGrantTypes.Contains(GrantType.ResourceOwnerPassword)) { LogError("{clientId} not authorized for resource owner flow", _validatedRequest.Client.ClientId); return(Invalid(OidcConstants.TokenErrors.UnauthorizedClient)); } ///////////////////////////////////////////// // check if client is allowed to request scopes ///////////////////////////////////////////// if (!(await ValidateRequestedScopesAsync(parameters))) { return(Invalid(OidcConstants.TokenErrors.InvalidScope)); } ///////////////////////////////////////////// // check resource owner credentials ///////////////////////////////////////////// var userName = parameters.Get(OidcConstants.TokenRequest.UserName); var password = parameters.Get(OidcConstants.TokenRequest.Password); if (userName.IsMissing() || password.IsMissing()) { LogError("Username or password missing"); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } if (userName.Length > _options.InputLengthRestrictions.UserName || password.Length > _options.InputLengthRestrictions.Password) { LogError("Username or password too long"); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } _validatedRequest.UserName = userName; ///////////////////////////////////////////// // authenticate user ///////////////////////////////////////////// var resourceOwnerContext = new ResourceOwnerPasswordValidationContext { UserName = userName, Password = password, Request = _validatedRequest }; await _resourceOwnerValidator.ValidateAsync(resourceOwnerContext); if (resourceOwnerContext.Result.IsError) { if (resourceOwnerContext.Result.Error == OidcConstants.TokenErrors.UnsupportedGrantType) { LogError("Resource owner password credential grant type not supported"); await RaiseFailedResourceOwnerAuthenticationEventAsync(userName, "password grant type not supported"); return(Invalid(OidcConstants.TokenErrors.UnsupportedGrantType, customResponse: resourceOwnerContext.Result.CustomResponse)); } var errorDescription = "invalid_username_or_password"; if (resourceOwnerContext.Result.ErrorDescription.IsPresent()) { errorDescription = resourceOwnerContext.Result.ErrorDescription; } LogError("User authentication failed: {error}", errorDescription ?? resourceOwnerContext.Result.Error); await RaiseFailedResourceOwnerAuthenticationEventAsync(userName, errorDescription); return(Invalid(OidcConstants.TokenErrors.InvalidGrant, errorDescription, resourceOwnerContext.Result.CustomResponse)); } if (resourceOwnerContext.Result.Subject == null) { var error = "User authentication failed: no principal returned"; LogError(error); await RaiseFailedResourceOwnerAuthenticationEventAsync(userName, error); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } ///////////////////////////////////////////// // make sure user is enabled ///////////////////////////////////////////// var isActiveCtx = new IsActiveContext(resourceOwnerContext.Result.Subject, _validatedRequest.Client, IdentityServerConstants.ProfileIsActiveCallers.ResourceOwnerValidation); await _profile.IsActiveAsync(isActiveCtx); if (isActiveCtx.IsActive == false) { LogError("User has been disabled: {subjectId}", resourceOwnerContext.Result.Subject.GetSubjectId()); await RaiseFailedResourceOwnerAuthenticationEventAsync(userName, "user is inactive"); return(Invalid(OidcConstants.TokenErrors.InvalidGrant)); } _validatedRequest.UserName = userName; _validatedRequest.Subject = resourceOwnerContext.Result.Subject; await RaiseSuccessfulResourceOwnerAuthenticationEventAsync(userName, resourceOwnerContext.Result.Subject.GetSubjectId()); _logger.LogDebug("Resource owner password token request validation success."); return(Valid(resourceOwnerContext.Result.CustomResponse)); }