Skip to content

Commit

Permalink
conditional OAuth2AuthorizedClientBeans
Browse files Browse the repository at this point in the history
  • Loading branch information
ch4mpy committed Feb 10, 2024
1 parent 72efbff commit a02614e
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ spring:
provider:
keycloak:
issuer-uri: ${keycloak-issuer}
cognito:
issuer-uri: ${cognito-issuer}
auth0:
issuer-uri: ${auth0-issuer}
registration:
Expand All @@ -52,13 +50,6 @@ spring:
client-secret: ${keycloak-secret}
provider: keycloak
scope: openid,offline_access
cognito-confidential-user:
authorization-grant-type: authorization_code
client-name: Amazon Cognito
client-id: 12olioff63qklfe9nio746es9f
client-secret: ${cognito-secret}
provider: cognito
scope: openid,profile,email
auth0-confidential-user:
authorization-grant-type: authorization_code
client-name: Auth0
Expand All @@ -77,10 +68,6 @@ com:
authorities:
- path: $.realm_access.roles
- path: $.resource_access.*.roles
- iss: ${cognito-issuer}
username-claim: $.username
authorities:
- path: $.cognito:groups
- iss: ${auth0-issuer}
aud: demo.c4-soft.com
username-claim: $['https://c4-soft.com/user']['name']
Expand Down Expand Up @@ -127,6 +114,10 @@ com:
auth0-confidential-user:
- name: audience
value: demo.c4-soft.com
token-request-params:
auth0-confidential-user:
- name: audience
value: demo.c4-soft.com

logging:
level:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.c4_soft.springaddons.security.oidc.starter.properties.condition;

public class HasOAuth2RegistrationPropertiesCondition extends HasPropertyPrefixCondition {

public HasOAuth2RegistrationPropertiesCondition() {
super("spring.security.oauth2.client.registration");
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean;
package com.c4_soft.springaddons.security.oidc.starter.properties.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
Expand All @@ -7,11 +7,14 @@
import org.springframework.core.env.PropertySource;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class HasOAuth2RegistrationPropertiesCondition implements Condition {
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class HasPropertyPrefixCondition implements Condition {
private final String prefix;

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
final String prefix = "spring.security.oauth2.client.registration";
if (context.getEnvironment() instanceof ConfigurableEnvironment env) {
for (PropertySource<?> propertySource : env.getPropertySources()) {
if (propertySource instanceof EnumerablePropertySource enumerablePropertySource) {
Expand All @@ -25,4 +28,4 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
}
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.c4_soft.springaddons.security.oidc.starter.properties.condition;

public class HasTokenEdpointParametersPropertiesCondition extends HasPropertyPrefixCondition {

public HasTokenEdpointParametersPropertiesCondition() {
super("com.c4-soft.springaddons.oidc.client.token-request-params");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.context.annotation.Conditional;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;

import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasOAuth2RegistrationPropertiesCondition;

public class DefaultOAuth2AuthorizedClientManagerCondition extends AllNestedConditions {

public DefaultOAuth2AuthorizedClientManagerCondition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.context.annotation.Conditional;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;

import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasOAuth2RegistrationPropertiesCondition;

public class DefaultOAuth2AuthorizedClientProviderCondition extends AllNestedConditions {

public DefaultOAuth2AuthorizedClientProviderCondition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.context.annotation.Conditional;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;

import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasOAuth2RegistrationPropertiesCondition;

public class DefaultReactiveOAuth2AuthorizedClientManagerCondition extends AllNestedConditions {

public DefaultReactiveOAuth2AuthorizedClientManagerCondition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.context.annotation.Conditional;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;

import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasOAuth2RegistrationPropertiesCondition;

public class DefaultReactiveOAuth2AuthorizedClientProviderCondition extends AllNestedConditions {

public DefaultReactiveOAuth2AuthorizedClientProviderCondition() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,34 @@
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;

import com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasTokenEdpointParametersPropertiesCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean.DefaultReactiveOAuth2AuthorizedClientManagerCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean.DefaultReactiveOAuth2AuthorizedClientProviderCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.configuration.IsReactiveOauth2ClientCondition;

@Conditional(IsReactiveOauth2ClientCondition.class)
@Conditional({ IsReactiveOauth2ClientCondition.class, HasTokenEdpointParametersPropertiesCondition.class })
@AutoConfiguration
public class ReactiveSpringAddonsOAuth2AuthorizedClientBeans {

@Conditional(DefaultReactiveOAuth2AuthorizedClientManagerCondition.class)
@Bean
ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository,
ReactiveOAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider) {

final var authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(oauth2AuthorizedClientProvider);

return authorizedClientManager;
}

@Conditional(DefaultReactiveOAuth2AuthorizedClientProviderCondition.class)
@Bean
ReactiveOAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider(
SpringAddonsOidcProperties addonsProperties,
InMemoryReactiveClientRegistrationRepository clientRegistrationRepository) {
return new PerRegistrationReactiveOAuth2AuthorizedClientProvider(clientRegistrationRepository, addonsProperties, Map.of());
}
@Conditional(DefaultReactiveOAuth2AuthorizedClientManagerCondition.class)
@Bean
ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository,
ReactiveOAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider) {

final var authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(oauth2AuthorizedClientProvider);

return authorizedClientManager;
}

@Conditional(DefaultReactiveOAuth2AuthorizedClientProviderCondition.class)
@Bean
ReactiveOAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider(
SpringAddonsOidcProperties addonsProperties,
InMemoryReactiveClientRegistrationRepository clientRegistrationRepository) {
return new PerRegistrationReactiveOAuth2AuthorizedClientProvider(clientRegistrationRepository, addonsProperties, Map.of());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ ResourceServerReactiveHttpSecurityPostProcessor httpPostProcessor() {
return serverHttpSecurity -> serverHttpSecurity;
}

@ConditionalOnMissingBean
@Bean
SpringAddonsReactiveJwtDecoderFactory springAddonsJwtDecoderFactory() {
return new DefaultSpringAddonsReactiveJwtDecoderFactory();
}

/**
* Provides with multi-tenancy: builds a ReactiveAuthenticationManagerResolver per provided OIDC issuer URI
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@

import com.c4_soft.springaddons.security.oidc.starter.OpenidProviderPropertiesResolver;
import com.c4_soft.springaddons.security.oidc.starter.synchronised.resourceserver.JWTClaimsSetAuthenticationManager.JWTClaimsSetAuthenticationManagerResolver;
import com.c4_soft.springaddons.security.oidc.starter.synchronised.resourceserver.SpringAddonsJwtDecoderFactory;

import reactor.core.publisher.Mono;

/**
* <p>
* An {@link ReactiveAuthenticationManagerResolver} always resolving the same {@link ReactiveJWTClaimsSetAuthenticationManager} which relies on
* {@link JWTClaimsSetAuthenticationManagerResolver}, itself using {@link SpringAddonsJwtDecoderFactory} and a {@link Converter Converter@lt;Jwt,
* {@link JWTClaimsSetAuthenticationManagerResolver}, itself using {@link SpringAddonsReactiveJwtDecoderFactory} and a {@link Converter Converter@lt;Jwt,
* AbstractAuthenticationToken&gt;}.
* </p>
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,33 @@
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;

import com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.HasTokenEdpointParametersPropertiesCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean.DefaultOAuth2AuthorizedClientManagerCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.bean.DefaultOAuth2AuthorizedClientProviderCondition;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.configuration.IsServletOauth2ClientCondition;

@Conditional(IsServletOauth2ClientCondition.class)
@Conditional({ IsServletOauth2ClientCondition.class, HasTokenEdpointParametersPropertiesCondition.class })
@AutoConfiguration
public class SpringAddonsOAuth2AuthorizedClientBeans {

@Conditional(DefaultOAuth2AuthorizedClientManagerCondition.class)
@Bean
OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository,
OAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider) {

final var authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(oauth2AuthorizedClientProvider);

return authorizedClientManager;
}

@Conditional(DefaultOAuth2AuthorizedClientProviderCondition.class)
@Bean
OAuth2AuthorizedClientProvider
oauth2AuthorizedClientProvider(SpringAddonsOidcProperties addonsProperties, InMemoryClientRegistrationRepository clientRegistrationRepository) {
return new PerRegistrationOAuth2AuthorizedClientProvider(clientRegistrationRepository, addonsProperties, Map.of());
}
@Conditional(DefaultOAuth2AuthorizedClientManagerCondition.class)
@Bean
OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository,
OAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider) {

final var authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(oauth2AuthorizedClientProvider);

return authorizedClientManager;
}

@Conditional(DefaultOAuth2AuthorizedClientProviderCondition.class)
@Bean
OAuth2AuthorizedClientProvider oauth2AuthorizedClientProvider(
SpringAddonsOidcProperties addonsProperties,
InMemoryClientRegistrationRepository clientRegistrationRepository) {
return new PerRegistrationOAuth2AuthorizedClientProvider(clientRegistrationRepository, addonsProperties, Map.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
* configuration. It applies to all routes not listed in "permit-all" property configuration. Default requires users to be authenticated. <b>This is a bean to
* provide in your application configuration if you prefer to define fine-grained access control rules with Java configuration rather than methods
* security.</b></li>
* <li>httpPostProcessor: a bean of type {@link ResourceServerSynchronizedHttpSecurityPostProcessor} to override anything from above auto-configuration. It is called just
* before the security filter-chain is returned. Default is a no-op.</li>
* <li>httpPostProcessor: a bean of type {@link ResourceServerSynchronizedHttpSecurityPostProcessor} to override anything from above auto-configuration. It is
* called just before the security filter-chain is returned. Default is a no-op.</li>
* <li>jwtAuthenticationConverter: a converter from a {@link Jwt} to something inheriting from {@link AbstractAuthenticationToken}. The default instantiate a
* {@link JwtAuthenticationToken} with username and authorities as configured for the issuer of thi token. The easiest to override the type of
* {@link AbstractAuthenticationToken}, is to provide with an Converter&lt;Jwt, ? extends AbstractAuthenticationToken&gt; bean.</li>
Expand Down Expand Up @@ -183,6 +183,12 @@ ResourceServerSynchronizedHttpSecurityPostProcessor httpPostProcessor() {
return httpSecurity -> httpSecurity;
}

@ConditionalOnMissingBean
@Bean
SpringAddonsJwtDecoderFactory springAddonsJwtDecoderFactory() {
return new DefaultSpringAddonsJwtDecoderFactory();
}

/**
* Provides with multi-tenancy: builds a AuthenticationManagerResolver<HttpServletRequest> per provided OIDC issuer URI
*
Expand Down

0 comments on commit a02614e

Please sign in to comment.