diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java index fcdff4b4bb5..daddbbfdd6c 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceImpl.java @@ -185,6 +185,8 @@ public Response requestAccessToken(String grantType, String code, return response(error(Response.Status.FORBIDDEN.getStatusCode(), TokenErrorResponseType.DISABLED_CLIENT, "Client is disabled."), oAuth2AuditLog); } + tokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), oAuth2AuditLog); + final Function idTokenTokingBindingPreprocessing = TokenBindingMessage.createIdTokenTokingBindingPreprocessing( tokenBindingHeader, client.getIdTokenTokenBindingCnf()); // for all except authorization code grant final SessionId sessionIdObj = sessionIdService.getSessionId(request); @@ -199,11 +201,6 @@ public Response requestAccessToken(String grantType, String code, executionContext.setAttributeService(attributeService); if (gt == GrantType.AUTHORIZATION_CODE) { - // todo refactor - if (!TokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, null), oAuth2AuditLog); - } - log.debug("Attempting to find authorizationCodeGrant by clientId: '{}', code: '{}'", client.getClientId(), code); final AuthorizationCodeGrant authorizationCodeGrant = authorizationGrantList.getAuthorizationCodeGrant(code); log.trace("AuthorizationCodeGrant : '{}'", authorizationCodeGrant); @@ -266,11 +263,6 @@ public Response requestAccessToken(String grantType, String code, } if (gt == GrantType.REFRESH_TOKEN) { - // todo refactor - if (!TokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, "grant_type does not belong to client."), oAuth2AuditLog); - } - AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByRefreshToken(client.getClientId(), refreshToken); if (authorizationGrant == null) { @@ -331,11 +323,6 @@ public Response requestAccessToken(String grantType, String code, idToken)); oAuth2AuditLog.updateOAuth2AuditLog(authorizationGrant, true); } else if (gt == GrantType.CLIENT_CREDENTIALS) { - // todo refactor - if (!TokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, "grant_type is not present in client."), oAuth2AuditLog); - } - ClientCredentialsGrant clientCredentialsGrant = authorizationGrantList.createClientCredentialsGrant(new User(), client); scope = clientCredentialsGrant.checkScopesPolicy(scope); @@ -366,11 +353,6 @@ public Response requestAccessToken(String grantType, String code, scope, idToken)); } else if (gt == GrantType.RESOURCE_OWNER_PASSWORD_CREDENTIALS) { - // todo refactor - if (!TokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, "grant_type is not present in client."), oAuth2AuditLog); - } - boolean authenticated = false; User user = null; if (authenticationFilterService.isEnabled()) { @@ -439,11 +421,6 @@ public Response requestAccessToken(String grantType, String code, } else if (gt == GrantType.CIBA) { errorResponseFactory.validateComponentEnabled(ComponentType.CIBA); - // todo refactor - if (!TokenRestWebServiceValidator.validateGrantType(gt, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, "Grant types are invalid."), oAuth2AuditLog); - } - log.debug("Attempting to find authorizationGrant by authReqId: '{}'", authReqId); final CIBAGrant cibaGrant = authorizationGrantList.getCIBAGrant(authReqId); executionContext.setGrant(cibaGrant); @@ -619,10 +596,6 @@ private RefreshToken createRefreshToken(@NotNull HttpServletRequest request, @No private Response processDeviceCodeGrantType(final GrantType grantType, final Client client, final String deviceCode, String scope, final HttpServletRequest request, final HttpServletResponse response, final OAuth2AuditLog oAuth2AuditLog) { - if (!TokenRestWebServiceValidator.validateGrantType(grantType, client.getGrantTypes(), appConfiguration.getGrantTypesSupported())) { - return response(error(400, TokenErrorResponseType.INVALID_GRANT, "Grant types are invalid."), oAuth2AuditLog); - } - log.debug("Attempting to find authorizationGrant by deviceCode: '{}'", deviceCode); final DeviceCodeGrant deviceCodeGrant = authorizationGrantList.getDeviceCodeGrant(deviceCode); diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidator.java b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidator.java index db3de0049d4..1a7adab8d8c 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidator.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidator.java @@ -1,6 +1,7 @@ package io.jans.as.server.token.ws.rs; import io.jans.as.model.common.GrantType; +import io.jans.as.model.configuration.AppConfiguration; import io.jans.as.model.error.ErrorResponseFactory; import io.jans.as.model.token.TokenErrorResponseType; import io.jans.as.server.audit.ApplicationAuditLogger; @@ -17,7 +18,6 @@ import java.util.Arrays; import java.util.List; -import java.util.Set; /** * @author Yuriy Zabrovarnyy @@ -35,6 +35,8 @@ public class TokenRestWebServiceValidator { @Inject private ApplicationAuditLogger applicationAuditLogger; + @Inject + private AppConfiguration appConfiguration; public void validateParams(String grantType, String code, String redirectUri, String refreshToken, OAuth2AuditLog auditLog) { @@ -73,10 +75,19 @@ public static boolean validateParams(String clientId, String clientSecret) { && clientSecret != null && !clientSecret.isEmpty(); } - public static boolean validateGrantType(GrantType requestedGrantType, GrantType[] clientGrantTypesArray, Set grantTypesSupported) { + public void validateGrantType(GrantType requestedGrantType, GrantType[] clientGrantTypesArray, OAuth2AuditLog auditLog) { List clientGrantTypes = Arrays.asList(clientGrantTypesArray); + if (!clientGrantTypes.contains(requestedGrantType)) { + final String msg = "GrantType is not allowed by client's grantTypes."; + log.trace(msg); + throw new WebApplicationException(response(error(400, TokenErrorResponseType.INVALID_GRANT, msg), auditLog)); + } - return clientGrantTypes.contains(requestedGrantType) && grantTypesSupported.contains(requestedGrantType); + if (!appConfiguration.getGrantTypesSupported().contains(requestedGrantType)) { + final String msg = "GrantType is not allowed by AS configuration"; + log.trace(msg); + throw new WebApplicationException(response(error(400, TokenErrorResponseType.INVALID_GRANT, msg), auditLog)); + } } private Response response(Response.ResponseBuilder builder, OAuth2AuditLog oAuth2AuditLog) { diff --git a/jans-auth-server/server/src/test/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidatorTest.java b/jans-auth-server/server/src/test/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidatorTest.java new file mode 100644 index 00000000000..0a25a113644 --- /dev/null +++ b/jans-auth-server/server/src/test/java/io/jans/as/server/token/ws/rs/TokenRestWebServiceValidatorTest.java @@ -0,0 +1,115 @@ +package io.jans.as.server.token.ws.rs; + +import io.jans.as.model.common.GrantType; +import io.jans.as.model.configuration.AppConfiguration; +import io.jans.as.model.error.ErrorResponseFactory; +import io.jans.as.server.audit.ApplicationAuditLogger; +import io.jans.as.server.model.audit.OAuth2AuditLog; +import jakarta.ws.rs.WebApplicationException; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.slf4j.Logger; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import static io.jans.as.server.util.TestUtil.assertBadRequest; +import static org.junit.Assert.fail; + +/** + * @author Yuriy Zabrovarnyy + */ +@Listeners(MockitoTestNGListener.class) +public class TokenRestWebServiceValidatorTest { + + public static final OAuth2AuditLog AUDIT_LOG = new OAuth2AuditLog("", null); + + @Mock + private Logger log; + + @Mock + private AppConfiguration appConfiguration; + + @Mock + private ApplicationAuditLogger applicationAuditLogger; + + @Mock + private ErrorResponseFactory errorResponseFactory; + + @InjectMocks + private TokenRestWebServiceValidator tokenRestWebServiceValidator; + + @Test + public void validateParams_whenGrantTypeIsBlank_shouldRaiseError() { + try { + tokenRestWebServiceValidator.validateParams("", "some_code", "https://my.redirect", "refresh_token", AUDIT_LOG); + } catch (WebApplicationException e) { + assertBadRequest(e.getResponse()); + return; + } + fail("No error for blank grant type."); + } + + @Test + public void validateParams_whenGrantTypeIsAuthorizationCodeAndCodeIsBlank_shouldRaiseError() { + try { + tokenRestWebServiceValidator.validateParams(GrantType.AUTHORIZATION_CODE.getValue(), "", "https://my.redirect", "refresh_token", AUDIT_LOG); + } catch (WebApplicationException e) { + assertBadRequest(e.getResponse()); + return; + } + fail("No error for blank code for AUTHORIZATION_CODE grant type."); + } + + + @Test + public void validateParams_whenGrantTypeIsAuthorizationCodeAndRedirectUriIsBlank_shouldRaiseError() { + try { + tokenRestWebServiceValidator.validateParams(GrantType.AUTHORIZATION_CODE.getValue(), "some_code", "", "refresh_token", AUDIT_LOG); + } catch (WebApplicationException e) { + assertBadRequest(e.getResponse()); + return; + } + fail("No error for blank redirect_uri for AUTHORIZATION_CODE grant type."); + } + + @Test + public void validateParams_whenGrantTypeIsRefreshTokenAndRefreshTokenIsBlank_shouldRaiseError() { + try { + tokenRestWebServiceValidator.validateParams(GrantType.REFRESH_TOKEN.getValue(), "some_code", "https://my.redirect", "", AUDIT_LOG); + } catch (WebApplicationException e) { + assertBadRequest(e.getResponse()); + return; + } + fail("No error for blank refresh_token for REFRESH_TOKEN grant type."); + } + + @Test + public void validateParams_whenGrantTypeIsAuthorizationCodeAndCodeIsNotBlank_shouldNotRaiseError() { + try { + tokenRestWebServiceValidator.validateParams(GrantType.AUTHORIZATION_CODE.getValue(), "some_code", "https://my.redirect", "", AUDIT_LOG); + } catch (WebApplicationException e) { + fail("Error occurs. We should not get it."); + } + } + + @Test + public void validateParams_whenGrantTypeIsRefreshTokenAndRefreshTokenIsNotBlank_shouldNotRaiseError() { + try { + tokenRestWebServiceValidator.validateParams(GrantType.REFRESH_TOKEN.getValue(), "", "https://my.redirect", "refresh_token", AUDIT_LOG); + } catch (WebApplicationException e) { + fail("Error occurs. We should not get it."); + } + } + + @Test + public void validateGrantType_whenClientDotNotHaveGrantType_shouldRaiseError() { + try { + tokenRestWebServiceValidator.validateGrantType(GrantType.AUTHORIZATION_CODE, new GrantType[0], AUDIT_LOG); + } catch (WebApplicationException e) { + assertBadRequest(e.getResponse()); + return; + } + fail("No error for grant_type which is not allowed by client's grant_types."); + } +} diff --git a/jans-auth-server/server/src/test/java/io/jans/as/server/util/TestUtil.java b/jans-auth-server/server/src/test/java/io/jans/as/server/util/TestUtil.java index 32ddf14c6f1..58a2f8f1c45 100644 --- a/jans-auth-server/server/src/test/java/io/jans/as/server/util/TestUtil.java +++ b/jans-auth-server/server/src/test/java/io/jans/as/server/util/TestUtil.java @@ -1,8 +1,11 @@ package io.jans.as.server.util; import io.jans.as.client.RegisterResponse; +import io.jans.as.model.error.ErrorResponse; +import jakarta.ws.rs.core.Response; import static io.jans.as.model.uma.TestUtil.assertNotBlank; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; /** @@ -22,4 +25,12 @@ public static void assert_(RegisterResponse response) { assertNotNull(response.getClientIdIssuedAt()); assertNotNull(response.getClientSecretExpiresAt()); } + + public static void assertBadRequest(Response response) { + assertEquals(response.getStatus(), 400); + } + + public static void assertErrorCode(Response response, String expectedErrorCode) { + assertEquals(response.readEntity(ErrorResponse.class).getErrorCode(), expectedErrorCode); + } } diff --git a/jans-auth-server/server/src/test/resources/testng.xml b/jans-auth-server/server/src/test/resources/testng.xml index b0de9529bc0..77ca8ee1bc2 100644 --- a/jans-auth-server/server/src/test/resources/testng.xml +++ b/jans-auth-server/server/src/test/resources/testng.xml @@ -15,6 +15,7 @@ +