Add support for public key file for OAuth2 resource server
Closes gh-15814
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.security.oauth2.resource;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Condition for creating a jwt decoder using a public key value.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class KeyValueCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage
|
||||
.forCondition("Public Key Value Condition");
|
||||
Environment environment = context.getEnvironment();
|
||||
String publicKeyLocation = environment.getProperty(
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location");
|
||||
if (!StringUtils.hasText(publicKeyLocation)) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.didNotFind("issuer-uri property").atAll());
|
||||
}
|
||||
String issuerUri = environment
|
||||
.getProperty("spring.security.oauth2.resourceserver.jwt.issuer-uri");
|
||||
String jwkSetUri = environment
|
||||
.getProperty("spring.security.oauth2.resourceserver.jwt.jwk-set-uri");
|
||||
if (StringUtils.hasText(jwkSetUri)) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.found("jwk-set-uri property").items(jwkSetUri));
|
||||
}
|
||||
if (StringUtils.hasText(issuerUri)) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.found("issuer-uri property").items(issuerUri));
|
||||
}
|
||||
return ConditionOutcome
|
||||
.match(message.foundExactly("public key location property"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,6 +50,11 @@ public class OAuth2ResourceServerProperties {
|
||||
*/
|
||||
private String issuerUri;
|
||||
|
||||
/**
|
||||
* Location of the file containing the public key used to verify a JWT.
|
||||
*/
|
||||
private String publicKeyLocation;
|
||||
|
||||
public String getJwkSetUri() {
|
||||
return this.jwkSetUri;
|
||||
}
|
||||
@@ -74,6 +79,14 @@ public class OAuth2ResourceServerProperties {
|
||||
this.issuerUri = issuerUri;
|
||||
}
|
||||
|
||||
public String getPublicKeyLocation() {
|
||||
return this.publicKeyLocation;
|
||||
}
|
||||
|
||||
public void setPublicKeyLocation(String publicKeyLocation) {
|
||||
this.publicKeyLocation = publicKeyLocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,9 +15,16 @@
|
||||
*/
|
||||
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;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.IssuerUriCondition;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.KeyValueCondition;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
@@ -25,9 +32,12 @@ 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 is available.
|
||||
* Configures a {@link ReactiveJwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI
|
||||
* or Public Key configuration is available.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Artsiom Yudovin
|
||||
@@ -35,26 +45,42 @@ import org.springframework.security.oauth2.jwt.ReactiveJwtDecoders;
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class ReactiveOAuth2ResourceServerJwkConfiguration {
|
||||
|
||||
private final OAuth2ResourceServerProperties properties;
|
||||
private final OAuth2ResourceServerProperties.Jwt properties;
|
||||
|
||||
ReactiveOAuth2ResourceServerJwkConfiguration(
|
||||
OAuth2ResourceServerProperties properties) {
|
||||
this.properties = properties;
|
||||
this.properties = properties.getJwt();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
|
||||
@ConditionalOnMissingBean
|
||||
public ReactiveJwtDecoder jwtDecoder() {
|
||||
return new NimbusReactiveJwtDecoder(this.properties.getJwt().getJwkSetUri());
|
||||
return new NimbusReactiveJwtDecoder(this.properties.getJwkSetUri());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@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)));
|
||||
return NimbusReactiveJwtDecoder.withPublicKey(publicKey).build();
|
||||
}
|
||||
|
||||
private byte[] getKeySpec(String keyValue) {
|
||||
keyValue = keyValue.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "").replace("\n", "");
|
||||
return Base64.getDecoder().decode(keyValue);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Conditional(IssuerUriCondition.class)
|
||||
@ConditionalOnMissingBean
|
||||
public ReactiveJwtDecoder jwtDecoderByIssuerUri() {
|
||||
return ReactiveJwtDecoders
|
||||
.fromOidcIssuerLocation(this.properties.getJwt().getIssuerUri());
|
||||
return ReactiveJwtDecoders.fromOidcIssuerLocation(this.properties.getIssuerUri());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,20 +15,29 @@
|
||||
*/
|
||||
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;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.IssuerUriCondition;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.KeyValueCondition;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
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.NimbusJwtDecoderJwkSupport;
|
||||
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 or OpenID Connect Issuer URI is
|
||||
* available.
|
||||
* Configures a {@link JwtDecoder} when a JWK Set URI, OpenID Connect Issuer URI or Public
|
||||
* Key configuration is available.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Artsiom Yudovin
|
||||
@@ -46,8 +55,25 @@ class OAuth2ResourceServerJwtConfiguration {
|
||||
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
|
||||
@ConditionalOnMissingBean
|
||||
public JwtDecoder jwtDecoderByJwkKeySetUri() {
|
||||
return new NimbusJwtDecoderJwkSupport(this.properties.getJwkSetUri(),
|
||||
this.properties.getJwsAlgorithm());
|
||||
return NimbusJwtDecoder.withJwkSetUri(this.properties.getJwkSetUri())
|
||||
.jwsAlgorithm(this.properties.getJwsAlgorithm()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@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)));
|
||||
return NimbusJwtDecoder.withPublicKey(publicKey).build();
|
||||
}
|
||||
|
||||
private byte[] getKeySpec(String keyValue) {
|
||||
keyValue = keyValue.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||
.replace("-----END PUBLIC KEY-----", "").replace("\n", "");
|
||||
return Base64.getDecoder().decode(keyValue);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -82,8 +82,7 @@ public class ReactiveOAuth2ResourceServerAutoConfigurationTests {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(ReactiveJwtDecoder.class))
|
||||
.isInstanceOf(NimbusReactiveJwtDecoder.class);
|
||||
assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class);
|
||||
assertFilterConfiguredWithJwtAuthenticationManager(context);
|
||||
});
|
||||
}
|
||||
@@ -101,26 +100,54 @@ public class ReactiveOAuth2ResourceServerAutoConfigurationTests {
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort())
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(ReactiveJwtDecoder.class))
|
||||
.isInstanceOf(NimbusReactiveJwtDecoder.class);
|
||||
assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class);
|
||||
assertFilterConfiguredWithJwtAuthenticationManager(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenBothSetUriAndIssuerUriPresentShouldUseSetUri() {
|
||||
public void autoConfigurationShouldConfigureResourceServerUsingPublicKeyValue() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class);
|
||||
assertFilterConfiguredWithJwtAuthenticationManager(context);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenSetUriKeyLocationIssuerUriPresentShouldUseSetUri() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com",
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location",
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=https://jwk-oidc-issuer-location.com")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(ReactiveJwtDecoder.class))
|
||||
.isInstanceOf(NimbusReactiveJwtDecoder.class);
|
||||
assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class);
|
||||
assertFilterConfiguredWithJwtAuthenticationManager(context);
|
||||
assertThat(context.containsBean("jwtDecoder")).isTrue();
|
||||
assertThat(context.containsBean("jwtDecoderByIssuerUri")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenKeyLocationAndIssuerUriPresentShouldUseIssuerUri()
|
||||
throws Exception {
|
||||
this.server = new MockWebServer();
|
||||
this.server.start();
|
||||
String issuer = this.server.url("").toString();
|
||||
String cleanIssuerPath = cleanIssuerPath(issuer);
|
||||
setupMockResponse(cleanIssuerPath);
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort(),
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(NimbusReactiveJwtDecoder.class);
|
||||
assertFilterConfiguredWithJwtAuthenticationManager(context);
|
||||
assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenJwkSetUriNullShouldNotFail() {
|
||||
this.contextRunner.run((context) -> assertThat(context)
|
||||
|
||||
@@ -42,11 +42,11 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -78,8 +78,7 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(JwtDecoder.class))
|
||||
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
|
||||
assertThat(context).hasSingleBean(JwtDecoder.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
});
|
||||
}
|
||||
@@ -90,7 +89,11 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com")
|
||||
.run((context) -> {
|
||||
JwtDecoder jwtDecoder = context.getBean(JwtDecoder.class);
|
||||
assertThat(jwtDecoder).hasFieldOrPropertyWithValue("jwsAlgorithm",
|
||||
Object processor = ReflectionTestUtils.getField(jwtDecoder,
|
||||
"jwtProcessor");
|
||||
Object keySelector = ReflectionTestUtils.getField(processor,
|
||||
"jwsKeySelector");
|
||||
assertThat(keySelector).hasFieldOrPropertyWithValue("jwsAlg",
|
||||
JWSAlgorithm.RS256);
|
||||
});
|
||||
}
|
||||
@@ -102,7 +105,11 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
"spring.security.oauth2.resourceserver.jwt.jws-algorithm=HS512")
|
||||
.run((context) -> {
|
||||
JwtDecoder jwtDecoder = context.getBean(JwtDecoder.class);
|
||||
assertThat(jwtDecoder).hasFieldOrPropertyWithValue("jwsAlgorithm",
|
||||
Object processor = ReflectionTestUtils.getField(jwtDecoder,
|
||||
"jwtProcessor");
|
||||
Object keySelector = ReflectionTestUtils.getField(processor,
|
||||
"jwsKeySelector");
|
||||
assertThat(keySelector).hasFieldOrPropertyWithValue("jwsAlg",
|
||||
JWSAlgorithm.HS512);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
});
|
||||
@@ -121,24 +128,57 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort())
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(JwtDecoder.class))
|
||||
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
|
||||
assertThat(context).hasSingleBean(JwtDecoder.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenBothSetUriAndIssuerUriPresentShouldUseSetUri() {
|
||||
public void autoConfigurationShouldConfigureResourceServerUsingPublicKeyValue()
|
||||
throws Exception {
|
||||
this.server = new MockWebServer();
|
||||
this.server.start();
|
||||
String issuer = this.server.url("").toString();
|
||||
String cleanIssuerPath = cleanIssuerPath(issuer);
|
||||
setupMockResponse(cleanIssuerPath);
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JwtDecoder.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenSetUriKeyLocationAndIssuerUriPresentShouldUseSetUri() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=https://issuer-uri.com",
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location",
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://jwk-set-uri.com")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(JwtDecoder.class))
|
||||
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
|
||||
assertThat(context).hasSingleBean(JwtDecoder.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
assertThat(context.containsBean("jwtDecoderByJwkKeySetUri")).isTrue();
|
||||
assertThat(context.containsBean("jwtDecoderByOidcIssuerUri"))
|
||||
.isFalse();
|
||||
assertThat(context.containsBean("jwtDecoderByIssuerUri")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationWhenKeyLocationAndIssuerUriPresentShouldUseIssuerUri()
|
||||
throws Exception {
|
||||
this.server = new MockWebServer();
|
||||
this.server.start();
|
||||
String issuer = this.server.url("").toString();
|
||||
String cleanIssuerPath = cleanIssuerPath(issuer);
|
||||
setupMockResponse(cleanIssuerPath);
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort(),
|
||||
"spring.security.oauth2.resourceserver.jwt.public-key-location=classpath:public-key-location")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(JwtDecoder.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd
|
||||
UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs
|
||||
HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D
|
||||
o2kQ+X5xK9cipRgEKwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -190,7 +190,7 @@
|
||||
<spring-plugin.version>2.0.0.M1</spring-plugin.version>
|
||||
<spring-restdocs.version>2.0.3.RELEASE</spring-restdocs.version>
|
||||
<spring-retry.version>1.2.4.RELEASE</spring-retry.version>
|
||||
<spring-security.version>5.1.5.RELEASE</spring-security.version>
|
||||
<spring-security.version>5.2.0.BUILD-SNAPSHOT</spring-security.version>
|
||||
<spring-session-bom.version>Bean-SR4</spring-session-bom.version>
|
||||
<spring-ws.version>3.0.7.RELEASE</spring-ws.version>
|
||||
<sqlite-jdbc.version>3.27.2</sqlite-jdbc.version>
|
||||
|
||||
@@ -3657,6 +3657,12 @@ as shown in the following examples:
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
|
||||
----
|
||||
|
||||
NOTE: If the authorization server does not support a JWK Set URI, you can configure the
|
||||
resource server with the Public Key used for verifying the signature of the JWT. This can
|
||||
be done using the `spring.security.oauth2.resourceserver.jwt.public-key-location` property,
|
||||
where the value needs to point to a file containing the public key in the PEM-encoded x509
|
||||
format.
|
||||
|
||||
The same properties are applicable for both servlet and reactive applications.
|
||||
|
||||
Alternatively, you can define your own `JwtDecoder` bean for servlet applications
|
||||
|
||||
Reference in New Issue
Block a user