package com.company.authorizationserver.configuration.grants.password; import jakarta.servlet.http.HttpServletRequest; import com.company.authorizationserver.configuration.grants.OAuth2EndpointUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.lang.Nullable; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.OAuth2ErrorCodes; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.util.MultiValueMap; import java.util.Set; /** * Converter for OAuth2 password grant type. This converter is used to convert a request to an authentication object. * Spring Authorization Server does not provide a converter for this grant type. So we have to implement it on our own. * * @author Attoumane AHAMADI */ public class OAuth2PasswordGrantAuthenticationConverter implements AuthenticationConverter { public static final AuthorizationGrantType PASSWORD_GRANT_TYPE = new AuthorizationGrantType("password"); @Nullable @Override public Authentication convert(HttpServletRequest request) { // grant_type (REQUIRED) String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); if (!PASSWORD_GRANT_TYPE.getValue().equals(grantType)) { return null; } Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication(); if (clientPrincipal == null) { OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_CLIENT, OAuth2ParameterNames.CLIENT_ID, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } MultiValueMap parameters = OAuth2EndpointUtils.getParameters(request); //if client id does not match the client id in the request, throw an error if (!StringUtils.equals(clientPrincipal.getName(), parameters.getFirst(OAuth2ParameterNames.CLIENT_ID))) { OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_CLIENT, OAuth2ParameterNames.CLIENT_ID, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } // scope (OPTIONAL) String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE); if (StringUtils.isNotBlank(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) { OAuth2EndpointUtils.throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE, OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI); } Set scopes = scope != null ? Set.of(scope.split(" ")) : null; return new OAuth2PasswordGrantAuthenticationToken(parameters.getFirst(OAuth2ParameterNames.USERNAME), parameters.getFirst(OAuth2ParameterNames.PASSWORD), clientPrincipal, scopes); } }