|
|
@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
|
|
|
|
|
|
|
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
|
|
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
|
|
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
|
|
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
@ -61,6 +62,7 @@ import org.springframework.security.oauth2.provider.token.ResourceServerTokenSer
|
|
|
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
|
|
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
|
|
|
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
|
|
|
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
|
|
|
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
|
|
|
|
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
|
|
|
|
|
|
|
|
import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore;
|
|
|
|
import org.springframework.social.connect.ConnectionFactoryLocator;
|
|
|
|
import org.springframework.social.connect.ConnectionFactoryLocator;
|
|
|
|
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
|
|
|
|
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
@ -73,6 +75,7 @@ import org.springframework.web.client.RestTemplate;
|
|
|
|
* Configuration for an OAuth2 resource server.
|
|
|
|
* Configuration for an OAuth2 resource server.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @author Dave Syer
|
|
|
|
* @author Dave Syer
|
|
|
|
|
|
|
|
* @author Madhura Bhave
|
|
|
|
* @since 1.3.0
|
|
|
|
* @since 1.3.0
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Configuration
|
|
|
|
@Configuration
|
|
|
@ -93,7 +96,7 @@ public class ResourceServerTokenServicesConfiguration {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration
|
|
|
|
@Configuration
|
|
|
|
@Conditional(NotJwtTokenCondition.class)
|
|
|
|
@Conditional(RemoteTokenCondition.class)
|
|
|
|
protected static class RemoteTokenServicesConfiguration {
|
|
|
|
protected static class RemoteTokenServicesConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration
|
|
|
|
@Configuration
|
|
|
@ -214,6 +217,30 @@ public class ResourceServerTokenServicesConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration
|
|
|
|
|
|
|
|
@Conditional(JwkCondition.class)
|
|
|
|
|
|
|
|
protected static class JwkTokenStoreConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final ResourceServerProperties resource;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public JwkTokenStoreConfiguration(ResourceServerProperties resource) {
|
|
|
|
|
|
|
|
this.resource = resource;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
|
|
|
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
|
|
|
|
|
|
|
|
public DefaultTokenServices jwkTokenServices() {
|
|
|
|
|
|
|
|
DefaultTokenServices services = new DefaultTokenServices();
|
|
|
|
|
|
|
|
services.setTokenStore(jwkTokenStore());
|
|
|
|
|
|
|
|
return services;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
|
|
|
|
public TokenStore jwkTokenStore() {
|
|
|
|
|
|
|
|
return new JwkTokenStore(this.resource.getJwk().getKeySetUri());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration
|
|
|
|
@Configuration
|
|
|
|
@Conditional(JwtTokenCondition.class)
|
|
|
|
@Conditional(JwtTokenCondition.class)
|
|
|
|
protected static class JwtTokenServicesConfiguration {
|
|
|
|
protected static class JwtTokenServicesConfiguration {
|
|
|
@ -341,30 +368,54 @@ public class ResourceServerTokenServicesConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static class NotTokenInfoCondition extends SpringBootCondition {
|
|
|
|
private static class JwkCondition extends SpringBootCondition {
|
|
|
|
|
|
|
|
|
|
|
|
private TokenInfoCondition tokenInfoCondition = new TokenInfoCondition();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
|
|
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
|
|
|
AnnotatedTypeMetadata metadata) {
|
|
|
|
AnnotatedTypeMetadata metadata) {
|
|
|
|
|
|
|
|
ConditionMessage.Builder message = ConditionMessage
|
|
|
|
|
|
|
|
.forCondition("OAuth JWK Condition");
|
|
|
|
|
|
|
|
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
|
|
|
|
|
|
|
context.getEnvironment(), "security.oauth2.resource.jwk.");
|
|
|
|
|
|
|
|
String keyUri = resolver.getProperty("key-set-uri");
|
|
|
|
|
|
|
|
if (StringUtils.hasText(keyUri)) {
|
|
|
|
return ConditionOutcome
|
|
|
|
return ConditionOutcome
|
|
|
|
.inverse(this.tokenInfoCondition.getMatchOutcome(context, metadata));
|
|
|
|
.match(message.foundExactly("provided jwk key set URI"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return ConditionOutcome
|
|
|
|
|
|
|
|
.noMatch(message.didNotFind("key jwk set URI not provided").atAll());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static class NotJwtTokenCondition extends SpringBootCondition {
|
|
|
|
private static class NotTokenInfoCondition extends SpringBootCondition {
|
|
|
|
|
|
|
|
|
|
|
|
private JwtTokenCondition jwtTokenCondition = new JwtTokenCondition();
|
|
|
|
private TokenInfoCondition tokenInfoCondition = new TokenInfoCondition();
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
|
|
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
|
|
|
AnnotatedTypeMetadata metadata) {
|
|
|
|
AnnotatedTypeMetadata metadata) {
|
|
|
|
return ConditionOutcome
|
|
|
|
return ConditionOutcome
|
|
|
|
.inverse(this.jwtTokenCondition.getMatchOutcome(context, metadata));
|
|
|
|
.inverse(this.tokenInfoCondition.getMatchOutcome(context, metadata));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class RemoteTokenCondition extends NoneNestedConditions {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RemoteTokenCondition() {
|
|
|
|
|
|
|
|
super(ConfigurationPhase.PARSE_CONFIGURATION);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Conditional(JwtTokenCondition.class)
|
|
|
|
|
|
|
|
static class HasJwtConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Conditional(JwkCondition.class)
|
|
|
|
|
|
|
|
static class HasJwkConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static class AcceptJsonRequestInterceptor implements ClientHttpRequestInterceptor {
|
|
|
|
static class AcceptJsonRequestInterceptor implements ClientHttpRequestInterceptor {
|
|
|
|