From ee735a61cef7bb742641ce0bd589bfa48d87eafc Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 9 Apr 2019 14:20:52 +0200 Subject: [PATCH] Polish See gh-15814 --- .../oauth2/resource/KeyValueCondition.java | 2 +- .../OAuth2ResourceServerProperties.java | 28 ++++++++++++++++--- ...eOAuth2ResourceServerJwkConfiguration.java | 8 ++---- .../OAuth2ResourceServerJwtConfiguration.java | 8 ++---- ...2ResourceServerAutoConfigurationTests.java | 9 ++++++ ...2ResourceServerAutoConfigurationTests.java | 9 ++++++ 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/KeyValueCondition.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/KeyValueCondition.java index caacae0fa02..e96fb98cf59 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/KeyValueCondition.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/KeyValueCondition.java @@ -42,7 +42,7 @@ public class KeyValueCondition extends SpringBootCondition { "spring.security.oauth2.resourceserver.jwt.public-key-location"); if (!StringUtils.hasText(publicKeyLocation)) { return ConditionOutcome - .noMatch(message.didNotFind("issuer-uri property").atAll()); + .noMatch(message.didNotFind("public-key-location property").atAll()); } String issuerUri = environment .getProperty("spring.security.oauth2.resourceserver.jwt.issuer-uri"); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/OAuth2ResourceServerProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/OAuth2ResourceServerProperties.java index 4dcaa7aed33..e3f2ebc20b0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/OAuth2ResourceServerProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/OAuth2ResourceServerProperties.java @@ -1,5 +1,5 @@ /* - * 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"); * you may not use this file except in compliance with the License. @@ -15,7 +15,15 @@ */ 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.source.InvalidConfigurationPropertyValueException; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; /** * OAuth 2.0 resource server properties. @@ -53,7 +61,7 @@ public class OAuth2ResourceServerProperties { /** * Location of the file containing the public key used to verify a JWT. */ - private String publicKeyLocation; + private Resource publicKeyLocation; public String getJwkSetUri() { return this.jwkSetUri; @@ -79,14 +87,26 @@ public class OAuth2ResourceServerProperties { this.issuerUri = issuerUri; } - public String getPublicKeyLocation() { + public Resource getPublicKeyLocation() { return this.publicKeyLocation; } - public void setPublicKeyLocation(String publicKeyLocation) { + public void setPublicKeyLocation(Resource 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); + } + } + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java index 93efdf47edc..73106847406 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerJwkConfiguration.java @@ -15,7 +15,6 @@ */ package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive; -import java.io.InputStreamReader; import java.security.KeyFactory; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; @@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder; import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; 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 @@ -63,10 +60,9 @@ class ReactiveOAuth2ResourceServerJwkConfiguration { @Conditional(KeyValueCondition.class) @ConditionalOnMissingBean public NimbusReactiveJwtDecoder jwtDecoderByPublicKeyValue() throws Exception { - String keyValue = FileCopyUtils.copyToString(new InputStreamReader(ResourceUtils - .getURL(this.properties.getPublicKeyLocation()).openStream())); RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") - .generatePublic(new X509EncodedKeySpec(getKeySpec(keyValue))); + .generatePublic(new X509EncodedKeySpec( + getKeySpec(this.properties.readPublicKey()))); return NimbusReactiveJwtDecoder.withPublicKey(publicKey).build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerJwtConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerJwtConfiguration.java index 16d106ceca0..08dc972cfde 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerJwtConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerJwtConfiguration.java @@ -15,7 +15,6 @@ */ package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet; -import java.io.InputStreamReader; import java.security.KeyFactory; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; @@ -32,8 +31,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtDecoders; 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 @@ -63,10 +60,9 @@ class OAuth2ResourceServerJwtConfiguration { @Conditional(KeyValueCondition.class) @ConditionalOnMissingBean public JwtDecoder jwtDecoderByPublicKeyValue() throws Exception { - String keyValue = FileCopyUtils.copyToString(new InputStreamReader(ResourceUtils - .getURL(this.properties.getPublicKeyLocation()).openStream())); RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA") - .generatePublic(new X509EncodedKeySpec(getKeySpec(keyValue))); + .generatePublic(new X509EncodedKeySpec( + getKeySpec(this.properties.readPublicKey()))); return NimbusJwtDecoder.withPublicKey(publicKey).build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java index 5b81bedeff8..6ea97182bc3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java @@ -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 public void autoConfigurationWhenSetUriKeyLocationIssuerUriPresentShouldUseSetUri() { this.contextRunner.withPropertyValues( diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java index 6ec6fc80598..3bf9a6c295e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java @@ -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 public void autoConfigurationWhenSetUriKeyLocationAndIssuerUriPresentShouldUseSetUri() { this.contextRunner.withPropertyValues(