Polish "OIDC issuer uri in OAuth resource server config"
Closes gh-14190
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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
|
||||
*
|
||||
* http://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.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Condition for creating {@link JwtDecoder} by oidc issuer location.
|
||||
*
|
||||
* @author Artsiom Yudovin
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class IssuerUriCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
ConditionMessage.Builder message = ConditionMessage
|
||||
.forCondition("OpenID Connect Issuer URI Condition");
|
||||
Environment environment = context.getEnvironment();
|
||||
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(issuerUri)) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.didNotFind("issuer-uri property").atAll());
|
||||
}
|
||||
if (StringUtils.hasText(jwkSetUri)) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.found("jwk-set-uri property").items(jwkSetUri));
|
||||
}
|
||||
return ConditionOutcome.match(message.foundExactly("issuer-uri property"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,9 +41,9 @@ public class OAuth2ResourceServerProperties {
|
||||
private String jwkSetUri;
|
||||
|
||||
/**
|
||||
* Oidc issuer location.
|
||||
* URI that an OpenID Connect Provider asserts as its Issuer Identifier.
|
||||
*/
|
||||
private String oidcIssuerLocation;
|
||||
private String issuerUri;
|
||||
|
||||
public String getJwkSetUri() {
|
||||
return this.jwkSetUri;
|
||||
@@ -53,12 +53,12 @@ public class OAuth2ResourceServerProperties {
|
||||
this.jwkSetUri = jwkSetUri;
|
||||
}
|
||||
|
||||
public String getOidcIssuerLocation() {
|
||||
return this.oidcIssuerLocation;
|
||||
public String getIssuerUri() {
|
||||
return this.issuerUri;
|
||||
}
|
||||
|
||||
public void setOidcIssuerLocation(String oidcIssuerLocation) {
|
||||
this.oidcIssuerLocation = oidcIssuerLocation;
|
||||
public void setIssuerUri(String issuerUri) {
|
||||
this.issuerUri = issuerUri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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
|
||||
*
|
||||
* http://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.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
|
||||
/**
|
||||
* Condition for creating {@link JwtDecoder} by oidc issuer location.
|
||||
*
|
||||
* @author Artsiom Yudovin
|
||||
*/
|
||||
public class OidcIssuerLocationCondition implements Condition {
|
||||
|
||||
private static final String OIDC_ISSUER_LOCATION = "spring.security.oauth2.resourceserver.jwt.oidc-issuer-location";
|
||||
|
||||
private static final String JWT_SET_URI = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri";
|
||||
|
||||
@Override
|
||||
public boolean matches(ConditionContext conditionContext,
|
||||
AnnotatedTypeMetadata annotatedTypeMetadata) {
|
||||
Environment environment = conditionContext.getEnvironment();
|
||||
return environment.containsProperty(OIDC_ISSUER_LOCATION)
|
||||
&& !environment.containsProperty(JWT_SET_URI);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,8 +17,8 @@ package org.springframework.boot.autoconfigure.security.oauth2.resource.servlet;
|
||||
|
||||
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.OAuth2ResourceServerProperties;
|
||||
import org.springframework.boot.autoconfigure.security.oauth2.resource.OidcIssuerLocationCondition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -27,8 +27,8 @@ import org.springframework.security.oauth2.jwt.JwtDecoders;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport;
|
||||
|
||||
/**
|
||||
* Configures a {@link JwtDecoder} when a JWK Set URI is available or Oidc Issuer
|
||||
* Location.
|
||||
* Configures a {@link JwtDecoder} when a JWK Set URI or OpenID Connect Issuer URI is
|
||||
* available.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Artsiom Yudovin
|
||||
@@ -45,16 +45,16 @@ class OAuth2ResourceServerJwkConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.jwt.jwk-set-uri")
|
||||
@ConditionalOnMissingBean
|
||||
public JwtDecoder jwtDecoder() {
|
||||
public JwtDecoder jwtDecoderByJwkKeySetUri() {
|
||||
return new NimbusJwtDecoderJwkSupport(this.properties.getJwt().getJwkSetUri());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Conditional(OidcIssuerLocationCondition.class)
|
||||
@Conditional(IssuerUriCondition.class)
|
||||
@ConditionalOnMissingBean
|
||||
public JwtDecoder jwtDecoderByOidcIssuerLocation() {
|
||||
public JwtDecoder jwtDecoderByIssuerUri() {
|
||||
return JwtDecoders
|
||||
.fromOidcIssuerLocation(this.properties.getJwt().getOidcIssuerLocation());
|
||||
.fromOidcIssuerLocation(this.properties.getJwt().getIssuerUri());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,16 +85,17 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationShouldConfigureResourceServerOidcIssuerLocation()
|
||||
public void autoConfigurationShouldConfigureResourceServerUsingOidcIssuerUri()
|
||||
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.oidc-issuer-location=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort())
|
||||
this.contextRunner
|
||||
.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort())
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(JwtDecoder.class))
|
||||
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
|
||||
@@ -103,23 +104,16 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationShouldConfigureSetUriWithTwoProperties()
|
||||
throws Exception {
|
||||
this.server = new MockWebServer();
|
||||
this.server.start();
|
||||
String issuer = this.server.url("").toString();
|
||||
String cleanIssuerPath = cleanIssuerPath(issuer);
|
||||
setupMockResponse(cleanIssuerPath);
|
||||
public void autoConfigurationWhenBothSetUriAndIssuerUriPresentShouldUseSetUri() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.oidc-issuer-location=http://"
|
||||
+ this.server.getHostName() + ":" + this.server.getPort(),
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://issuer-uri.com",
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://jwk-set-uri.com")
|
||||
.run((context) -> {
|
||||
assertThat(context.getBean(JwtDecoder.class))
|
||||
.isInstanceOf(NimbusJwtDecoderJwkSupport.class);
|
||||
assertThat(getBearerTokenFilter(context)).isNotNull();
|
||||
assertThat(context.containsBean("jwtDecoder")).isTrue();
|
||||
assertThat(context.containsBean("jwtDecoderByOidcIssuerLocation"))
|
||||
assertThat(context.containsBean("jwtDecoderByJwkKeySetUri")).isTrue();
|
||||
assertThat(context.containsBean("jwtDecoderByOidcIssuerUri"))
|
||||
.isFalse();
|
||||
});
|
||||
}
|
||||
@@ -131,7 +125,7 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jwtDecoderBeanIsConditionalOnMissingBean() {
|
||||
public void jwtDecoderByJwkSetUriIsConditionalOnMissingBean() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://jwk-set-uri.com")
|
||||
.withUserConfiguration(JwtDecoderConfig.class)
|
||||
@@ -139,9 +133,9 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jwtDecoderBeanIsConditionalOnMissingBeanOidcIssuerLocation() {
|
||||
public void jwtDecoderByOidcIssuerUriIsConditionalOnMissingBean() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.oidc-issuer-location=http://jwk-oidc-issuer-location.com")
|
||||
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://jwk-oidc-issuer-location.com")
|
||||
.withUserConfiguration(JwtDecoderConfig.class)
|
||||
.run((context) -> assertThat(getBearerTokenFilter(context)).isNotNull());
|
||||
}
|
||||
@@ -155,15 +149,6 @@ public class OAuth2ResourceServerAutoConfigurationTests {
|
||||
.run((context) -> assertThat(getBearerTokenFilter(context)).isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoConfigurationShouldBeConditionalOnJwtAuthenticationTokenClassOidcIssuerLocation() {
|
||||
this.contextRunner.withPropertyValues(
|
||||
"spring.security.oauth2.resourceserver.jwt.oidc-issuer-location=http://jwk-oidc-issuer-location.com")
|
||||
.withUserConfiguration(JwtDecoderConfig.class)
|
||||
.withClassLoader(new FilteredClassLoader(JwtAuthenticationToken.class))
|
||||
.run((context) -> assertThat(getBearerTokenFilter(context)).isNull());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Filter getBearerTokenFilter(AssertableWebApplicationContext context) {
|
||||
FilterChainProxy filterChain = (FilterChainProxy) context
|
||||
|
||||
@@ -539,7 +539,7 @@ content into your application. Rather, pick only the properties that you need.
|
||||
|
||||
# SECURITY OAUTH2 RESOURCE SERVER ({sc-spring-boot-autoconfigure}/security/oauth2/resource/OAuth2ResourceServerProperties.{sc-ext}[OAuth2ResourceServerProperties])
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri= # JSON Web Key URI to use to verify the JWT token.
|
||||
spring.security.oauth2.resource.jwt.oidc-issuer-location= # Location for issuer oidc
|
||||
spring.security.oauth2.resource.jwt.issuer-uri= # URI that an OpenID Connect Provider asserts as its Issuer Identifier.
|
||||
|
||||
# ----------------------------------------
|
||||
# DATA PROPERTIES
|
||||
|
||||
@@ -3320,14 +3320,19 @@ Provider can be configured with the `issuer-uri`:
|
||||
[[boot-features-security-oauth2-server]]
|
||||
==== Resource Server
|
||||
If you have `spring-security-oauth2-resource-server` on your classpath, Spring Boot can
|
||||
set up an OAuth2 Resource Server as long as a JWK Set URI is specified, as shown in the
|
||||
following example:
|
||||
set up an OAuth2 Resource Server as long as a JWK Set URI or OIDC Issuer URI is specified,
|
||||
as shown in the following examples:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
|
||||
----
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
|
||||
----
|
||||
|
||||
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