diff --git a/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java b/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java index 577cd0314d..5fb64e32e9 100644 --- a/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java +++ b/Model/src/main/java/org/gluu/oxauth/model/configuration/AppConfiguration.java @@ -101,6 +101,7 @@ public class AppConfiguration implements Configuration { private Boolean requestUriParameterSupported; private Boolean requestUriHashVerificationEnabled; private Boolean requireRequestUriRegistration; + private List requestUriBlackList; private String opPolicyUri; private String opTosUri; private int authorizationCodeLifetime; @@ -2089,6 +2090,15 @@ public void setCibaEnabled(Boolean cibaEnabled) { this.cibaEnabled = cibaEnabled; } + public List getRequestUriBlackList() { + if (requestUriBlackList == null) requestUriBlackList = Lists.newArrayList(); + return requestUriBlackList; + } + + public void setRequestUriBlackList(List requestUriBlackList) { + this.requestUriBlackList = requestUriBlackList; + } + public Boolean getRequestUriHashVerificationEnabled() { return requestUriHashVerificationEnabled != null ? requestUriHashVerificationEnabled : false; } diff --git a/Server/src/main/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequest.java b/Server/src/main/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequest.java index fe3804f836..a9cabcdbf7 100644 --- a/Server/src/main/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequest.java +++ b/Server/src/main/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequest.java @@ -6,19 +6,9 @@ package org.gluu.oxauth.model.authorize; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.security.PrivateKey; -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.core.Response; - +import com.google.common.collect.Lists; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.ArrayUtils; import org.gluu.oxauth.model.common.Display; import org.gluu.oxauth.model.common.Prompt; import org.gluu.oxauth.model.common.ResponseType; @@ -27,6 +17,7 @@ import org.gluu.oxauth.model.crypto.encryption.BlockEncryptionAlgorithm; import org.gluu.oxauth.model.crypto.encryption.KeyEncryptionAlgorithm; import org.gluu.oxauth.model.crypto.signature.SignatureAlgorithm; +import org.gluu.oxauth.model.error.ErrorResponseFactory; import org.gluu.oxauth.model.exception.InvalidJwtException; import org.gluu.oxauth.model.jwe.Jwe; import org.gluu.oxauth.model.jwe.JweDecrypterImpl; @@ -35,9 +26,11 @@ import org.gluu.oxauth.model.registration.Client; import org.gluu.oxauth.model.util.Base64Util; import org.gluu.oxauth.model.util.JwtUtil; +import org.gluu.oxauth.model.util.URLPatternList; import org.gluu.oxauth.model.util.Util; import org.gluu.oxauth.service.ClientService; import org.gluu.oxauth.service.RedirectUriResponse; +import org.gluu.oxauth.service.RedirectionUriService; import org.gluu.oxauth.util.ServerUtil; import org.gluu.service.cdi.util.CdiUtil; import org.jetbrains.annotations.Nullable; @@ -47,8 +40,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.List; /** * @author Javier Rojas Blum @@ -462,6 +463,7 @@ private static String queryRequest(@Nullable String requestUri, @Nullable Redire } public static JwtAuthorizationRequest createJwtRequest(String request, String requestUri, Client client, RedirectUriResponse redirectUriResponse, AbstractCryptoProvider cryptoProvider, AppConfiguration appConfiguration) { + validateRequestUri(requestUri, client, appConfiguration, redirectUriResponse.getState()); final String requestFromClient = queryRequest(requestUri, redirectUriResponse, appConfiguration); if (StringUtils.isNotBlank(requestFromClient)) { request = requestFromClient; @@ -481,4 +483,35 @@ public static JwtAuthorizationRequest createJwtRequest(String request, String re return null; } + public static void validateRequestUri(String requestUri, Client client, AppConfiguration appConfiguration, String state) { + validateRequestUri(requestUri, client, appConfiguration, state, CdiUtil.bean(ErrorResponseFactory.class)); + } + + public static void validateRequestUri(String requestUri, Client client, AppConfiguration appConfiguration, String state, ErrorResponseFactory errorResponseFactory) { + if (StringUtils.isBlank(requestUri)) { + return; // nothing to validate + } + + // client.requestUris() - validation + if (ArrayUtils.isNotEmpty(client.getRequestUris()) && !RedirectionUriService.isUriEqual(requestUri, client.getRequestUris())) { + log.debug("request_uri is forbidden by client request uris."); + throw new WebApplicationException(Response + .status(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST_URI, state, "")) + .build()); + } + + // check black list + final List blackList = appConfiguration.getRequestUriBlackList(); + if (!blackList.isEmpty()) { + URLPatternList urlPatternList = new URLPatternList(blackList); + if (urlPatternList.isUrlListed(requestUri)) { + log.debug("request_uri is forbidden by requestUriBlackList configuration."); + throw new WebApplicationException(Response + .status(Response.Status.BAD_REQUEST) + .entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST_URI, state, "")) + .build()); + } + } + } } \ No newline at end of file diff --git a/Server/src/main/java/org/gluu/oxauth/service/RedirectUriResponse.java b/Server/src/main/java/org/gluu/oxauth/service/RedirectUriResponse.java index aff52fd888..6dca548a8e 100644 --- a/Server/src/main/java/org/gluu/oxauth/service/RedirectUriResponse.java +++ b/Server/src/main/java/org/gluu/oxauth/service/RedirectUriResponse.java @@ -48,6 +48,10 @@ public void setState(String state) { this.state = state; } + public String getState() { + return state; + } + public Response.ResponseBuilder createErrorBuilder(IErrorType errorType) { redirectUri.parseQueryString(errorFactory.getErrorAsQueryString(errorType, state)); return RedirectUtil.getRedirectResponseBuilder(redirectUri, httpRequest); diff --git a/Server/src/main/java/org/gluu/oxauth/service/RedirectionUriService.java b/Server/src/main/java/org/gluu/oxauth/service/RedirectionUriService.java index dad452d57a..376d1bb4b5 100644 --- a/Server/src/main/java/org/gluu/oxauth/service/RedirectionUriService.java +++ b/Server/src/main/java/org/gluu/oxauth/service/RedirectionUriService.java @@ -31,6 +31,7 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import org.slf4j.LoggerFactory; /** * @author Javier Rojas Blum @@ -39,8 +40,7 @@ @ApplicationScoped public class RedirectionUriService { - @Inject - private Logger log; + private static final Logger log = LoggerFactory.getLogger(RedirectionUriService.class); @Inject private ClientService clientService; @@ -125,7 +125,7 @@ public String validateRedirectionUri(@NotNull Client client, String redirectionU return null; } - public boolean isUriEqual(String redirectionUri, String[] redirectUris) { + public static boolean isUriEqual(String redirectionUri, String[] redirectUris) { final String redirectUriWithoutParams = uriWithoutParams(redirectionUri); for (String uri : redirectUris) { diff --git a/Server/src/test/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequestTest.java b/Server/src/test/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequestTest.java new file mode 100644 index 0000000000..82bb49e0b4 --- /dev/null +++ b/Server/src/test/java/org/gluu/oxauth/model/authorize/JwtAuthorizationRequestTest.java @@ -0,0 +1,77 @@ +package org.gluu.oxauth.model.authorize; + +import org.gluu.oxauth.model.configuration.AppConfiguration; +import org.gluu.oxauth.model.error.ErrorResponseFactory; +import org.gluu.oxauth.model.registration.Client; +import org.testng.annotations.Test; + +import javax.ws.rs.WebApplicationException; +import java.util.Arrays; +import java.util.Collections; + +/** + * @author Yuriy Zabrovarnyy + */ +public class JwtAuthorizationRequestTest { + + @Test + public void validateRequestUri_whichIsAllowedByClient_shouldBeOk() { + String requestUri = "https://myrp.com/request_uri"; + + Client client = new Client(); + client.setRequestUris(new String[]{"https://myrp.com/request_uri"}); + JwtAuthorizationRequest.validateRequestUri(requestUri, client, new AppConfiguration(), "", new ErrorResponseFactory()); + } + + @Test + public void validateRequestUri_withNoRestrictions_shouldBeOk() { + String requestUri = "https://myrp.com/request_uri"; + + JwtAuthorizationRequest.validateRequestUri(requestUri, new Client(), new AppConfiguration(), "", new ErrorResponseFactory()); + } + + @Test(expectedExceptions = WebApplicationException.class) + public void validateRequestUri_whichIsNotAllowedByClient_shouldRaiseException() { + String requestUri = "https://myrp.com/request_uri"; + + Client client = new Client(); + client.setRequestUris(new String[]{"https://myrp.com"}); + JwtAuthorizationRequest.validateRequestUri(requestUri, client, new AppConfiguration(), "", new ErrorResponseFactory()); + } + + @Test(expectedExceptions = WebApplicationException.class) + public void validateRequestUri_whichIsBlackListed_shouldRaiseException() { + String requestUri = "https://myrp.com/request_uri"; + + final AppConfiguration appConfiguration = new AppConfiguration(); + appConfiguration.setRequestUriBlackList(Arrays.asList("myrp.com", "evil.com")); + JwtAuthorizationRequest.validateRequestUri(requestUri, new Client(), appConfiguration, "", new ErrorResponseFactory()); + } + + @Test(expectedExceptions = WebApplicationException.class) + public void validateRequestUri_forLocalhost_shouldRaiseException() { + String requestUri = "https://localhost/request_uri"; + + final AppConfiguration appConfiguration = new AppConfiguration(); + appConfiguration.setRequestUriBlackList(Collections.singletonList("localhost")); + JwtAuthorizationRequest.validateRequestUri(requestUri, new Client(), appConfiguration, "", new ErrorResponseFactory()); + } + + @Test(expectedExceptions = WebApplicationException.class) + public void validateRequestUri_forLocalhostIp_shouldRaiseException() { + String requestUri = "https://127.0.0.1/request_uri"; + + final AppConfiguration appConfiguration = new AppConfiguration(); + appConfiguration.setRequestUriBlackList(Collections.singletonList("127.0.0.1")); + JwtAuthorizationRequest.validateRequestUri(requestUri, new Client(), appConfiguration, "", new ErrorResponseFactory()); + } + + @Test + public void validateRequestUri_whichIsNotBlackListed_shouldBeOk() { + String requestUri = "https://myrp.com/request_uri"; + + final AppConfiguration appConfiguration = new AppConfiguration(); + appConfiguration.setRequestUriBlackList(Arrays.asList("evil.com", "second.com")); + JwtAuthorizationRequest.validateRequestUri(requestUri, new Client(), appConfiguration, "", new ErrorResponseFactory()); + } +}