Commit 605b0aef authored by Madhura Bhave's avatar Madhura Bhave Committed by Andy Wilkinson

Simplify validation logic in ResourceServerProperties

Closes gh-8306
Closes gh-8317
parent 3e0e4e81
...@@ -204,40 +204,34 @@ public class ResourceServerProperties implements Validator, BeanFactoryAware { ...@@ -204,40 +204,34 @@ public class ResourceServerProperties implements Validator, BeanFactoryAware {
} }
ResourceServerProperties resource = (ResourceServerProperties) target; ResourceServerProperties resource = (ResourceServerProperties) target;
validate(resource, errors); validate(resource, errors);
} }
private void validate(ResourceServerProperties target, Errors errors) { private void validate(ResourceServerProperties target, Errors errors) {
if ((StringUtils.hasText(this.jwt.getKeyUri()) boolean jwtConfigPresent = StringUtils.hasText(this.jwt.getKeyUri())
|| StringUtils.hasText(this.jwt.getKeyValue())) || StringUtils.hasText(this.jwt.getKeyValue());
&& StringUtils.hasText(this.jwk.getKeySetUri())) { boolean jwkConfigPresent = StringUtils.hasText(this.jwk.getKeySetUri());
if (jwtConfigPresent && jwkConfigPresent) {
errors.reject("ambiguous.keyUri", errors.reject("ambiguous.keyUri",
"Only one of jwt.keyUri (or jwt.keyValue) and " "Only one of jwt.keyUri (or jwt.keyValue) and jwk.keySetUri should"
+ "jwk.keySetUri should be configured."); + " be configured.");
} }
else { else {
if (StringUtils.hasText(this.clientId)) { if (jwtConfigPresent || jwkConfigPresent) {
if (!StringUtils.hasText(this.clientSecret)) { // It's a JWT decoder
if (!StringUtils.hasText(target.getUserInfoUri())) { return;
errors.rejectValue("userInfoUri", "missing.userInfoUri", }
"Missing userInfoUri (no client secret available)"); if (!StringUtils.hasText(target.getUserInfoUri())
} && !StringUtils.hasText(target.getTokenInfoUri())) {
} errors.rejectValue("tokenInfoUri", "missing.tokenInfoUri",
else { "Missing tokenInfoUri and userInfoUri and there is no "
if (isPreferTokenInfo() + "JWT verifier key");
&& !StringUtils.hasText(target.getTokenInfoUri())) { }
if (StringUtils.hasText(getJwt().getKeyUri()) if (StringUtils.hasText(target.getTokenInfoUri()) && isPreferTokenInfo()) {
|| StringUtils.hasText(getJwt().getKeyValue()) if (StringUtils.hasText(this.clientId)
|| StringUtils.hasText(getJwk().getKeySetUri())) { && !StringUtils.hasText(this.clientSecret)) {
// It's a JWT decoder errors.rejectValue("clientSecret", "missing.clientSecret",
return; "Missing client secret");
}
if (!StringUtils.hasText(target.getUserInfoUri())) {
errors.rejectValue("tokenInfoUri", "missing.tokenInfoUri",
"Missing tokenInfoUri and userInfoUri and there is no "
+ "JWT verifier key");
}
}
} }
} }
} }
...@@ -276,21 +270,7 @@ public class ResourceServerProperties implements Validator, BeanFactoryAware { ...@@ -276,21 +270,7 @@ public class ResourceServerProperties implements Validator, BeanFactoryAware {
} }
public String getKeyUri() { public String getKeyUri() {
if (this.keyUri != null) { return this.keyUri;
return this.keyUri;
}
if (ResourceServerProperties.this.userInfoUri != null
&& ResourceServerProperties.this.userInfoUri.endsWith("/userinfo")) {
return ResourceServerProperties.this.userInfoUri.replace("/userinfo",
"/token_key");
}
if (ResourceServerProperties.this.tokenInfoUri != null
&& ResourceServerProperties.this.tokenInfoUri
.endsWith("/check_token")) {
return ResourceServerProperties.this.tokenInfoUri.replace("/check_token",
"/token_key");
}
return null;
} }
} }
......
...@@ -42,6 +42,8 @@ public class ResourceServerPropertiesTests { ...@@ -42,6 +42,8 @@ public class ResourceServerPropertiesTests {
private ResourceServerProperties properties = new ResourceServerProperties("client", private ResourceServerProperties properties = new ResourceServerProperties("client",
"secret"); "secret");
private Errors errors = mock(Errors.class);
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void json() throws Exception { public void json() throws Exception {
...@@ -54,39 +56,109 @@ public class ResourceServerPropertiesTests { ...@@ -54,39 +56,109 @@ public class ResourceServerPropertiesTests {
} }
@Test @Test
public void tokenKeyDerivedFromUserInfoUri() throws Exception { public void validateWhenBothJwtAndJwkKeyUrisPresentShouldFail() throws Exception {
this.properties.setUserInfoUri("http://example.com/userinfo"); this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys");
assertThat(this.properties.getJwt().getKeyUri()) this.properties.getJwt().setKeyUri("http://my-auth-server/token_key");
.isEqualTo("http://example.com/token_key"); setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verify(this.errors).reject("ambiguous.keyUri",
"Only one of jwt.keyUri (or jwt.keyValue) and jwk.keySetUri should be configured.");
} }
@Test @Test
public void tokenKeyDerivedFromTokenInfoUri() throws Exception { public void validateWhenBothJwtKeyValueAndJwkKeyUriPresentShouldFail()
this.properties.setTokenInfoUri("http://example.com/check_token"); throws Exception {
assertThat(this.properties.getJwt().getKeyUri()) this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys");
.isEqualTo("http://example.com/token_key"); this.properties.getJwt().setKeyValue("my-key");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verify(this.errors).reject("ambiguous.keyUri",
"Only one of jwt.keyUri (or jwt.keyValue) and jwk.keySetUri should be configured.");
} }
@Test @Test
public void validateWhenBothJwtAndJwtKeyConfigurationPresentShouldFail() public void validateWhenJwkKeySetUriProvidedShouldSucceed() throws Exception {
throws Exception {
this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys"); this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys");
this.properties.getJwt().setKeyUri("http://my-auth-server/token_key");
setListableBeanFactory(); setListableBeanFactory();
Errors errors = mock(Errors.class); this.properties.validate(this.properties, this.errors);
this.properties.validate(this.properties, errors); verifyZeroInteractions(this.errors);
verify(errors).reject("ambiguous.keyUri", }
"Only one of jwt.keyUri (or jwt.keyValue) and jwk.keySetUri should be configured.");
@Test
public void validateWhenKeyValuePresentShouldSucceed() throws Exception {
this.properties.getJwt().setKeyValue("my-key");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verifyZeroInteractions(this.errors);
} }
@Test @Test
public void validateWhenKeySetUriProvidedShouldSucceed() throws Exception { public void validateWhenKeysUriOrValuePresentAndUserInfoAbsentShouldNotFail()
throws Exception {
this.properties = new ResourceServerProperties("client", "");
this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys"); this.properties.getJwk().setKeySetUri("http://my-auth-server/token_keys");
setListableBeanFactory(); setListableBeanFactory();
Errors errors = mock(Errors.class); this.properties.validate(this.properties, this.errors);
this.properties.validate(this.properties, errors); verifyZeroInteractions(this.errors);
verifyZeroInteractions(errors); }
@Test
public void validateWhenKeyConfigAbsentAndInfoUrisNotConfiguredShouldFail()
throws Exception {
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verify(this.errors).rejectValue("tokenInfoUri", "missing.tokenInfoUri",
"Missing tokenInfoUri and userInfoUri and there is no JWT verifier key");
}
@Test
public void validateWhenTokenUriConfiguredShouldNotFail() throws Exception {
this.properties.setTokenInfoUri("http://my-auth-server/userinfo");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verifyZeroInteractions(this.errors);
}
@Test
public void validateWhenUserInfoUriConfiguredShouldNotFail() throws Exception {
this.properties.setUserInfoUri("http://my-auth-server/userinfo");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verifyZeroInteractions(this.errors);
}
@Test
public void validateWhenTokenUriPreferredAndClientSecretAbsentShouldFail()
throws Exception {
this.properties = new ResourceServerProperties("client", "");
this.properties.setTokenInfoUri("http://my-auth-server/check_token");
this.properties.setUserInfoUri("http://my-auth-server/userinfo");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verify(this.errors).rejectValue("clientSecret", "missing.clientSecret",
"Missing client secret");
}
@Test
public void validateWhenTokenUriAbsentAndClientSecretAbsentShouldNotFail()
throws Exception {
this.properties = new ResourceServerProperties("client", "");
this.properties.setUserInfoUri("http://my-auth-server/userinfo");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verifyZeroInteractions(this.errors);
}
@Test
public void validateWhenTokenUriNotPreferredAndClientSecretAbsentShouldNotFail()
throws Exception {
this.properties = new ResourceServerProperties("client", "");
this.properties.setPreferTokenInfo(false);
this.properties.setTokenInfoUri("http://my-auth-server/check_token");
this.properties.setUserInfoUri("http://my-auth-server/userinfo");
setListableBeanFactory();
this.properties.validate(this.properties, this.errors);
verifyZeroInteractions(this.errors);
} }
private void setListableBeanFactory() { private void setListableBeanFactory() {
......
...@@ -90,14 +90,6 @@ public class ResourceServerTokenServicesConfigurationTests { ...@@ -90,14 +90,6 @@ public class ResourceServerTokenServicesConfigurationTests {
} }
} }
@Test
public void defaultIsRemoteTokenServices() {
this.context = new SpringApplicationBuilder(ResourceConfiguration.class)
.web(false).run();
RemoteTokenServices services = this.context.getBean(RemoteTokenServices.class);
assertThat(services).isNotNull();
}
@Test @Test
public void useRemoteTokenServices() { public void useRemoteTokenServices() {
EnvironmentTestUtils.addEnvironment(this.environment, EnvironmentTestUtils.addEnvironment(this.environment,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment