Commit ee735a61 authored by Stephane Nicoll's avatar Stephane Nicoll

Polish

See gh-15814
parent f42b6199
...@@ -42,7 +42,7 @@ public class KeyValueCondition extends SpringBootCondition { ...@@ -42,7 +42,7 @@ public class KeyValueCondition extends SpringBootCondition {
"spring.security.oauth2.resourceserver.jwt.public-key-location"); "spring.security.oauth2.resourceserver.jwt.public-key-location");
if (!StringUtils.hasText(publicKeyLocation)) { if (!StringUtils.hasText(publicKeyLocation)) {
return ConditionOutcome return ConditionOutcome
.noMatch(message.didNotFind("issuer-uri property").atAll()); .noMatch(message.didNotFind("public-key-location property").atAll());
} }
String issuerUri = environment String issuerUri = environment
.getProperty("spring.security.oauth2.resourceserver.jwt.issuer-uri"); .getProperty("spring.security.oauth2.resourceserver.jwt.issuer-uri");
......
/* /*
* Copyright 2012-2018 the original author or authors. * Copyright 2012-2019 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -15,7 +15,15 @@ ...@@ -15,7 +15,15 @@
*/ */
package org.springframework.boot.autoconfigure.security.oauth2.resource; package org.springframework.boot.autoconfigure.security.oauth2.resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
/** /**
* OAuth 2.0 resource server properties. * OAuth 2.0 resource server properties.
...@@ -53,7 +61,7 @@ public class OAuth2ResourceServerProperties { ...@@ -53,7 +61,7 @@ public class OAuth2ResourceServerProperties {
/** /**
* Location of the file containing the public key used to verify a JWT. * Location of the file containing the public key used to verify a JWT.
*/ */
private String publicKeyLocation; private Resource publicKeyLocation;
public String getJwkSetUri() { public String getJwkSetUri() {
return this.jwkSetUri; return this.jwkSetUri;
...@@ -79,14 +87,26 @@ public class OAuth2ResourceServerProperties { ...@@ -79,14 +87,26 @@ public class OAuth2ResourceServerProperties {
this.issuerUri = issuerUri; this.issuerUri = issuerUri;
} }
public String getPublicKeyLocation() { public Resource getPublicKeyLocation() {
return this.publicKeyLocation; return this.publicKeyLocation;
} }
public void setPublicKeyLocation(String publicKeyLocation) { public void setPublicKeyLocation(Resource publicKeyLocation) {
this.publicKeyLocation = publicKeyLocation; this.publicKeyLocation = publicKeyLocation;
} }
public String readPublicKey() throws IOException {
String key = "spring.security.oauth2.resourceserver.public-key-location";
Assert.notNull(this.publicKeyLocation, "PublicKeyLocation must not be null");
if (!this.publicKeyLocation.exists()) {
throw new InvalidConfigurationPropertyValueException(key,
this.publicKeyLocation, "Public key location does not exist");
}
try (InputStream inputStream = this.publicKeyLocation.getInputStream()) {
return StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
}
}
} }
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive; package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive;
import java.io.InputStreamReader;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
...@@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration; ...@@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder; import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders; import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
/** /**
* Configures a {@link ReactiveJwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI * Configures a {@link ReactiveJwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI
...@@ -63,10 +60,9 @@ class ReactiveOAuth2ResourceServerJwkConfiguration { ...@@ -63,10 +60,9 @@ class ReactiveOAuth2ResourceServerJwkConfiguration {
@Conditional(KeyValueCondition.class) @Conditional(KeyValueCondition.class)
@ConditionalOnMissingBean @ConditionalOnMissingBean
public NimbusReactiveJwtDecoder jwtDecoderByPublicKeyValue() throws Exception { public NimbusReactiveJwtDecoder jwtDecoderByPublicKeyValue() throws Exception {
String keyValue = FileCopyUtils.copyToString(new InputStreamReader(ResourceUtils
.getURL(this.properties.getPublicKeyLocation()).openStream()));
RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(getKeySpec(keyValue))); .generatePublic(new X509EncodedKeySpec(
getKeySpec(this.properties.readPublicKey())));
return NimbusReactiveJwtDecoder.withPublicKey(publicKey).build(); return NimbusReactiveJwtDecoder.withPublicKey(publicKey).build();
} }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
*/ */
package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet; package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet;
import java.io.InputStreamReader;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
...@@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration; ...@@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders; import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
/** /**
* Configures a {@link JwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI or Public * Configures a {@link JwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI or Public
...@@ -63,10 +60,9 @@ class OAuth2ResourceServerJwtConfiguration { ...@@ -63,10 +60,9 @@ class OAuth2ResourceServerJwtConfiguration {
@Conditional(KeyValueCondition.class) @Conditional(KeyValueCondition.class)
@ConditionalOnMissingBean @ConditionalOnMissingBean
public JwtDecoder jwtDecoderByPublicKeyValue() throws Exception { public JwtDecoder jwtDecoderByPublicKeyValue() throws Exception {
String keyValue = FileCopyUtils.copyToString(new InputStreamReader(ResourceUtils
.getURL(this.properties.getPublicKeyLocation()).openStream()));
RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(getKeySpec(keyValue))); .generatePublic(new X509EncodedKeySpec(
getKeySpec(this.properties.readPublicKey())));
return NimbusJwtDecoder.withPublicKey(publicKey).build(); return NimbusJwtDecoder.withPublicKey(publicKey).build();
} }
......
...@@ -115,6 +115,15 @@ public class ReactiveOAuth2ResourceServerAutoConfigurationTests { ...@@ -115,6 +115,15 @@ public class ReactiveOAuth2ResourceServerAutoConfigurationTests {
}); });
} }
@Test
public void autoConfigurationShouldFailIfPublicKeyLocationDoesNotExist() {
this.contextRunner.withPropertyValues(
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:does-not-exist")
.run((context) -> assertThat(context).hasFailed().getFailure()
.hasMessageContaining("class path resource [does-not-exist]")
.hasMessageContaining("Public key location does not exist"));
}
@Test @Test
public void autoConfigurationWhenSetUriKeyLocationIssuerUriPresentShouldUseSetUri() { public void autoConfigurationWhenSetUriKeyLocationIssuerUriPresentShouldUseSetUri() {
this.contextRunner.withPropertyValues( this.contextRunner.withPropertyValues(
......
...@@ -149,6 +149,15 @@ public class OAuth2ResourceServerAutoConfigurationTests { ...@@ -149,6 +149,15 @@ public class OAuth2ResourceServerAutoConfigurationTests {
}); });
} }
@Test
public void autoConfigurationShouldFailIfPublicKeyLocationDoesNotExist() {
this.contextRunner.withPropertyValues(
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:does-not-exist")
.run((context) -> assertThat(context).hasFailed().getFailure()
.hasMessageContaining("class path resource [does-not-exist]")
.hasMessageContaining("Public key location does not exist"));
}
@Test @Test
public void autoConfigurationWhenSetUriKeyLocationAndIssuerUriPresentShouldUseSetUri() { public void autoConfigurationWhenSetUriKeyLocationAndIssuerUriPresentShouldUseSetUri() {
this.contextRunner.withPropertyValues( this.contextRunner.withPropertyValues(
......
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