Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jans-auth-server): added externalUriWhiteList configuration property before call external uri from AS #3130 #3425

Merged
merged 1 commit into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions jans-auth-server/agama/engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
</suiteXmlFiles>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
13 changes: 13 additions & 0 deletions jans-auth-server/agama/model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,17 @@
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,9 @@ public class AppConfiguration implements Configuration {
@DocProperty(description = "JMS Password")
private String jmsPassword;

@DocProperty(description = "This list specifies which external URIs can be called by AS (if empty any URI can be called)")
private List<String> externalUriWhiteList;

@DocProperty(description = "This list specifies which client redirection URIs are white-listed")
private List<String> clientWhiteList;

Expand Down Expand Up @@ -2473,6 +2476,15 @@ public void setJmsPassword(String jmsPassword) {
this.jmsPassword = jmsPassword;
}

public List<String> getExternalUriWhiteList() {
if (externalUriWhiteList == null) externalUriWhiteList = new ArrayList<>();
return externalUriWhiteList;
}

public void setExternalUriWhiteList(List<String> externalUriWhiteList) {
this.externalUriWhiteList = externalUriWhiteList;
}

public List<String> getClientWhiteList() {
return clientWhiteList;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import io.jans.as.model.jwt.Jwt;
import io.jans.as.model.register.RegisterErrorResponseType;
import io.jans.as.model.ssa.SsaValidationType;
import io.jans.as.model.util.JwtUtil;
import io.jans.as.model.util.Pair;
import io.jans.as.server.ciba.CIBARegisterParamsValidatorService;
import io.jans.as.server.model.common.AbstractToken;
import io.jans.as.server.model.common.AuthorizationGrant;
import io.jans.as.server.model.common.AuthorizationGrantList;
import io.jans.as.server.model.registration.RegisterParamsValidator;
import io.jans.as.server.service.external.ExternalDynamicClientRegistrationService;
import io.jans.as.server.service.net.UriService;
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
import jakarta.inject.Named;
Expand Down Expand Up @@ -78,6 +78,9 @@ public class RegisterValidator {
@Inject
private SsaValidationConfigService ssaValidationConfigService;

@Inject
private UriService uriService;

public void validateNotBlank(String input, String errorReason) {
if (StringUtils.isBlank(input)) {
log.trace("Failed to perform client action, reason: {}", errorReason);
Expand Down Expand Up @@ -191,7 +194,7 @@ private String getJwksString(JSONObject softwareStatement) {
@Nullable
private JSONObject getJwks(HttpServletRequest httpRequest, Jwt jwt, String jwksUri, String jwksStr) {
if (StringUtils.isNotBlank(jwksUri)) {
return JwtUtil.getJSONWebKeys(jwksUri);
return uriService.loadJson(jwksUri);
}

if (StringUtils.isNotBlank(jwksStr)) {
Expand Down Expand Up @@ -259,8 +262,11 @@ public JSONObject validateSoftwareStatement(HttpServletRequest httpServletReques
}

JSONObject jwks = Strings.isNullOrEmpty(jwksUriClaim) ?
new JSONObject(jwksClaim) :
JwtUtil.getJSONWebKeys(jwksUriClaim);
null :
uriService.loadJson(jwksUriClaim);
if (jwks == null && StringUtils.isNotBlank(jwksClaim)) {
jwks = new JSONObject(jwksClaim);
}

boolean validSignature = cryptoProvider.verifySignature(softwareStatement.getSigningInput(),
softwareStatement.getEncodedSignature(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import io.jans.as.model.register.RegisterRequestParam;
import io.jans.as.model.ssa.SsaValidationConfig;
import io.jans.as.model.ssa.SsaValidationType;
import io.jans.as.model.util.JwtUtil;
import io.jans.as.server.service.net.UriService;
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
import jakarta.inject.Named;
Expand Down Expand Up @@ -42,6 +42,9 @@ public class SsaValidationConfigService {
@Inject
private AbstractCryptoProvider cryptoProvider;

@Inject
private UriService uriService;

public List<SsaValidationConfig> getByIssuer(String issuer, SsaValidationType type) {
if (StringUtils.isBlank(issuer)) {
return new ArrayList<>();
Expand Down Expand Up @@ -130,18 +133,18 @@ private boolean isSignatureValid(Jwt jwt, SsaValidationConfig config) {
private JSONObject loadJwks(SsaValidationConfig config) {
JSONObject jwks = null;
if (StringUtils.isNotBlank(config.getJwksUri())) {
jwks = JwtUtil.getJSONWebKeys(config.getJwksUri());
jwks = uriService.loadJson(config.getJwksUri());
}

if (jwks == null && StringUtils.isNotBlank(config.getJwks())) {
jwks = new JSONObject(config.getJwks());
}

if (jwks == null && StringUtils.isNotBlank(config.getConfigurationEndpoint()) && StringUtils.isNotBlank(config.getConfigurationEndpointClaim())) {
final JSONObject responseJson = JwtUtil.getJSONWebKeys(config.getConfigurationEndpoint());
final JSONObject responseJson = uriService.loadJson(config.getConfigurationEndpoint());
final String jwksEndpoint = responseJson.optString(config.getConfigurationEndpointClaim());
if (StringUtils.isNotBlank(jwksEndpoint)) {
jwks = JwtUtil.getJSONWebKeys(jwksEndpoint);
jwks = uriService.loadJson(jwksEndpoint);
}
}
return jwks;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package io.jans.as.server.service.net;

import io.jans.as.model.configuration.AppConfiguration;
import io.jans.as.model.util.JwtUtil;
import io.jans.as.model.util.URLPatternList;
import jakarta.ejb.Stateless;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.apache.tika.utils.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;

import java.util.List;

/**
* @author Yuriy Z
*/
@Stateless
@Named
public class UriService {

@Inject
private Logger log;

@Inject
private AppConfiguration appConfiguration;

public boolean canCall(String uri) {
if (StringUtils.isBlank(uri)) {
return false;
}

final List<String> externalUriWhiteList = appConfiguration.getExternalUriWhiteList();
if (externalUriWhiteList == null || externalUriWhiteList.isEmpty()) {
return true;
}

return new URLPatternList(externalUriWhiteList).isUrlListed(uri);
}

public JSONObject loadJson(String uri) {
if (!canCall(uri)) {
log.debug("Unable to call external uri: {}, externalUriWhiteList: {}", uri, appConfiguration.getExternalUriWhiteList());
return null;
}
return JwtUtil.getJSONWebKeys(uri);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.jans.as.server.service.net;

import io.jans.as.model.configuration.AppConfiguration;
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 java.util.ArrayList;
import java.util.Collections;

import static org.mockito.Mockito.when;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;

/**
* @author Yuriy Z
*/
@Listeners(MockitoTestNGListener.class)
public class UriServiceTest {

@InjectMocks
private UriService uriService;

@Mock
private Logger log;

@Mock
private AppConfiguration appConfiguration;

@Test
public void canCall_whenExternalUriWhiteListIsBlank_shouldReturnTrue() {
when(appConfiguration.getExternalUriWhiteList()).thenReturn(new ArrayList<>());

assertTrue(uriService.canCall("http://example.com"));
}

@Test
public void canCall_whenUriAllowedByExternalUriWhiteList_shouldReturnTrue() {
when(appConfiguration.getExternalUriWhiteList()).thenReturn(Collections.singletonList("example.com"));

assertTrue(uriService.canCall("http://example.com"));
}

@Test
public void canCall_whenUriNotAllowedByExternalUriWhiteList_shouldReturnFalse() {
when(appConfiguration.getExternalUriWhiteList()).thenReturn(Collections.singletonList("my.com"));

assertFalse(uriService.canCall("http://example.com"));
}
}
1 change: 1 addition & 0 deletions jans-auth-server/server/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<class name="io.jans.as.server.service.RedirectionUriServiceTest" />
<class name="io.jans.as.server.service.external.ExternalAuthenticationServiceTest" />
<class name="io.jans.as.server.servlet.OpenIdConfigurationTest" />
<class name="io.jans.as.server.service.net.UriServiceTest" />

<class name="io.jans.as.server.token.ws.rs.TokenExchangeServiceTest" />
<class name="io.jans.as.server.token.ws.rs.TokenRestWebServiceValidatorTest" />
Expand Down