Skip to content
Merged
169 changes: 115 additions & 54 deletions oidc/src/main/java/oidc/endpoints/AuthorizationEndpoint.java

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions oidc/src/main/java/oidc/exceptions/UriTooLongException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package oidc.exceptions;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.URI_TOO_LONG)
public class UriTooLongException extends BaseException {

public UriTooLongException(String message) {
super(message);
}

@Override
public String getErrorCode() {
return "uri_too_long";
}

@Override
protected boolean suppressStackTrace() {
return true;
}
}
3 changes: 3 additions & 0 deletions oidc/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ server:
max-swallow-size: 10000000
max-http-request-header-size: 10000000

# Maximum length of query parameters in bytes for authorization endpoint
max-query-param-size: 8184

mongodb_db: oidc_test
oidc_saml_mapping_path: classpath:/oidc/saml_mapping.json
openid_configuration_path: classpath:/openid-configuration.json
Expand Down
180 changes: 113 additions & 67 deletions oidc/src/test/java/oidc/endpoints/AuthorizationEndpointTest.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;

Expand Down Expand Up @@ -227,4 +229,62 @@ private AuthorizationRequest authorizationRequest(Map<String, String> parameters
request.setQueryString(queryString);
return AuthorizationRequest.parse(JakartaServletUtils.createHTTPRequest(request));
}

@Test
public void validateQueryParamSizeWithinLimit() {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("scope", "openid");
parameters.add("response_type", "code");
parameters.add("client_id", "test");

// Should not throw exception
AuthorizationEndpoint endpoint = createAuthorizationEndpoint(1024);
endpoint.validateQueryParamSize(parameters);
}

@Test(expected = oidc.exceptions.UriTooLongException.class)
public void validateQueryParamSizeExceedsLimit() {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
// Create a scope parameter that exceeds 100 bytes
StringBuilder longScope = new StringBuilder("openid");
for (int i = 0; i < 50; i++) {
longScope.append(" openid");
}
parameters.add("scope", longScope.toString());
parameters.add("response_type", "code");
parameters.add("client_id", "test");

AuthorizationEndpoint endpoint = createAuthorizationEndpoint(100);
endpoint.validateQueryParamSize(parameters);
}

@Test
public void validateQueryParamSizeNullParameters() {
// Should not throw exception
AuthorizationEndpoint endpoint = createAuthorizationEndpoint(1024);
endpoint.validateQueryParamSize(null);
}

@Test
public void validateQueryParamSizeEmptyParameters() {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();

// Should not throw exception
AuthorizationEndpoint endpoint = createAuthorizationEndpoint(1024);
endpoint.validateQueryParamSize(parameters);
}

private AuthorizationEndpoint createAuthorizationEndpoint(int maxQueryParamSize) {
return new AuthorizationEndpoint(
null, // authorizationCodeRepository
null, // accessTokenRepository
null, // userRepository
null, // openIDClientRepository
null, // tokenGenerator
"salt",
"test",
false,
maxQueryParamSize
);
}
}
21 changes: 9 additions & 12 deletions oidc/src/test/java/oidc/saml/AbstractSamlUnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import org.springframework.security.saml2.provider.service.authentication.OpenSaml5AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.web.PortResolver;
import org.springframework.security.web.PortResolverImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

Expand All @@ -35,7 +33,6 @@
public abstract class AbstractSamlUnitTest {

protected static Saml2X509Credential saml2X509Credential;
protected static PortResolver portResolver = new PortResolverImpl();
protected static RelyingPartyRegistration relyingParty;

@BeforeAll
Expand All @@ -45,15 +42,15 @@ public static void beforeClass() {
OpenSamlInitializationService.initialize();

relyingParty = RelyingPartyRegistration
.withRegistrationId("oidcng")
.withRegistrationId("oidcng")
.entityId("entityID")
.signingX509Credentials(c -> c.add(saml2X509Credential))
.assertionConsumerServiceLocation("https://acs")
.assertingPartyMetadata(builder -> builder
.entityId("entityID")
.signingX509Credentials(c -> c.add(saml2X509Credential))
.assertionConsumerServiceLocation("https://acs")
.assertingPartyMetadata(builder -> builder
.entityId("entityID")
.wantAuthnRequestsSigned(false)
.singleSignOnServiceLocation("https://sso").build())
.build();
.wantAuthnRequestsSigned(false)
.singleSignOnServiceLocation("https://sso").build())
.build();
}

@SneakyThrows
Expand Down Expand Up @@ -81,7 +78,7 @@ public OpenSaml5AuthenticationProvider.ResponseToken getResponseToken(Response r
public Response unmarshall(String saml2Response) throws UnmarshallingException, XMLParserException {
XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
ResponseUnmarshaller responseUnmarshaller = (ResponseUnmarshaller) registry.getUnmarshallerFactory()
.getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
.getUnmarshaller(Response.DEFAULT_ELEMENT_NAME);
ParserPool parserPool = registry.getParserPool();
Document doc = parserPool.parse(new ByteArrayInputStream(saml2Response.getBytes()));
Element samlElement = doc.getDocumentElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void testSaml() throws Exception {
request.addParameter("request", signedJWT.serialize());

when(requestCache.getRequest(any(HttpServletRequest.class), any()))
.thenReturn(new DefaultSavedRequest(request, portResolver));
.thenReturn(new DefaultSavedRequest(request));

AuthnRequest authnRequest = getAuthnRequest();

Expand Down Expand Up @@ -107,7 +107,7 @@ public void testJWTRequestURIMismatch() {
HttpServletRequest servletRequest = new MockHttpServletRequest();

when(requestCache.getRequest(any(HttpServletRequest.class), any()))
.thenReturn(new DefaultSavedRequest(request, portResolver));
.thenReturn(new DefaultSavedRequest(request));
AuthnRequest authnRequest = getAuthnRequest();

OpenSaml5AuthenticationRequestResolver.AuthnRequestContext ctx =
Expand All @@ -128,7 +128,7 @@ public void testSamlForceAuthn() throws Exception {
request.addParameter("client_id", "mock_sp");

when(requestCache.getRequest(any(HttpServletRequest.class), any()))
.thenReturn(new DefaultSavedRequest(request, portResolver));
.thenReturn(new DefaultSavedRequest(request));

AuthnRequest authnRequest = getAuthnRequest();

Expand All @@ -151,4 +151,4 @@ public void noCookies() {
subject.accept(ctx);
}

}
}