From 332df4168894220b5ea5acdf84d8977d8f8f161d Mon Sep 17 00:00:00 2001 From: YuriyZ Date: Mon, 28 Feb 2022 13:57:42 +0200 Subject: [PATCH] feat(jans-auth-server): reject par without pkce for fapi https://github.com/JanssenProject/jans/issues/875 --- .../server/par/ws/rs/ParRestWebService.java | 2 + .../as/server/par/ws/rs/ParValidator.java | 13 +++++ .../as/server/par/ws/rs/ParValidatorTest.java | 52 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 jans-auth-server/server/src/test/java/io/jans/as/server/par/ws/rs/ParValidatorTest.java diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java index 5e539948dc1..b8c994848c6 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java @@ -123,6 +123,8 @@ public Response requestPushedAuthorizationRequest( + "customRespHeaders = {}, claims = {}, tokenBindingHeader = {}", acrValuesStr, amrValuesStr, originHeaders, codeChallenge, codeChallengeMethod, customResponseHeaders, claims, tokenBindingHeader); + parValidator.validatePkce(codeChallenge, state); + List responseTypes = ResponseType.fromString(responseType, " "); ResponseMode responseModeObj = ResponseMode.getByValue(responseMode); diff --git a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java index 7629b781084..6fa9a35232c 100644 --- a/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java +++ b/jans-auth-server/server/src/main/java/io/jans/as/server/par/ws/rs/ParValidator.java @@ -26,6 +26,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; import java.util.Date; import java.util.Set; @@ -167,4 +168,16 @@ private void setStateIntoPar(@NotNull RedirectUriResponse redirectUriResponse, @ redirectUriResponse.setState(""); } } + + public void validatePkce(String codeChallenge, String state) { + if (!appConfiguration.isFapi()) { + return; + } + if (StringUtils.isBlank(codeChallenge)) { + throw new WebApplicationException(Response + .status(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST, state, "")) + .build()); + } + } } diff --git a/jans-auth-server/server/src/test/java/io/jans/as/server/par/ws/rs/ParValidatorTest.java b/jans-auth-server/server/src/test/java/io/jans/as/server/par/ws/rs/ParValidatorTest.java new file mode 100644 index 00000000000..94b2f90676e --- /dev/null +++ b/jans-auth-server/server/src/test/java/io/jans/as/server/par/ws/rs/ParValidatorTest.java @@ -0,0 +1,52 @@ +package io.jans.as.server.par.ws.rs; + +import io.jans.as.model.configuration.AppConfiguration; +import io.jans.as.model.error.ErrorResponseFactory; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import javax.ws.rs.WebApplicationException; + +import static org.mockito.Mockito.when; + +/** + * @author Yuriy Zabrovarnyy + */ +@Listeners(MockitoTestNGListener.class) +public class ParValidatorTest { + + @InjectMocks + private ParValidator parValidator; + + @Mock + private AppConfiguration appConfiguration; + + @Mock + private ErrorResponseFactory errorResponseFactory; // mock is required + + @SuppressWarnings("java:S5976") // we do want separate methods with clear names. Clarity of use case. + @Test + public void validatePkce_whenFapiIsFalse_shouldNotThrowError() { + when(appConfiguration.isFapi()).thenReturn(false); + + parValidator.validatePkce(null, null); + } + + @Test(expectedExceptions = WebApplicationException.class) + public void validatePkce_whenFapiIsTrueAndNoCodeChallenage_shouldThrowError() { + when(appConfiguration.isFapi()).thenReturn(true); + + parValidator.validatePkce(null, null); + } + + @Test + public void validatePkce_whenFapiIsTrueAndCodeChallenageIsSet_shouldNotThrowError() { + when(appConfiguration.isFapi()).thenReturn(true); + + parValidator.validatePkce("codechallangehere", null); + } + +}