-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add requestToken to CustomClaimController
- Loading branch information
Showing
7 changed files
with
308 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
...round-backend/src/main/java/ch/sbb/playgroundbackend/config/ApplicationConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package ch.sbb.playgroundbackend.config; | ||
|
||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.oauth2.client.JwtBearerOAuth2AuthorizedClientProvider; | ||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; | ||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; | ||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; | ||
import org.springframework.security.oauth2.client.endpoint.DefaultJwtBearerTokenResponseClient; | ||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; | ||
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; | ||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; | ||
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; | ||
import org.springframework.security.oauth2.core.OAuth2TokenValidator; | ||
import org.springframework.security.oauth2.jwt.Jwt; | ||
import org.springframework.security.oauth2.jwt.JwtClaimNames; | ||
import org.springframework.security.oauth2.jwt.JwtClaimValidator; | ||
import org.springframework.security.oauth2.jwt.JwtDecoder; | ||
import org.springframework.security.oauth2.jwt.JwtIssuerValidator; | ||
import org.springframework.security.oauth2.jwt.JwtTimestampValidator; | ||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; | ||
import org.springframework.util.StringUtils; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.function.Predicate; | ||
|
||
@Configuration | ||
public class ApplicationConfiguration { | ||
|
||
private final OAuth2ResourceServerProperties.Jwt properties; | ||
|
||
// The audience is important because the JWT token is accepted only if the aud claim in the JWT token received by the server is the same as the client ID of the server. | ||
@Value("${spring.security.oauth2.resourceserver.jwt.audience}") | ||
String audience; | ||
|
||
public ApplicationConfiguration(OAuth2ResourceServerProperties properties) { | ||
this.properties = properties.getJwt(); | ||
} | ||
|
||
@Bean | ||
JwtDecoder jwtDecoder() { | ||
NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder.withJwkSetUri(properties.getJwkSetUri()).build(); | ||
nimbusJwtDecoder.setJwtValidator(jwtValidator()); | ||
return nimbusJwtDecoder; | ||
} | ||
|
||
@Bean | ||
public OAuth2AuthorizedClientManager authorizedClientManager( | ||
ClientRegistrationRepository clientRegistrationRepository, | ||
OAuth2AuthorizedClientRepository authorizedClientRepository) { | ||
|
||
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() | ||
.provider(jwtBearerOAuth2AuthorizedClientProvider()) | ||
.build(); | ||
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository); | ||
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); | ||
return authorizedClientManager; | ||
} | ||
|
||
private JwtBearerOAuth2AuthorizedClientProvider jwtBearerOAuth2AuthorizedClientProvider() { | ||
JwtBearerOAuth2AuthorizedClientProvider provider = new JwtBearerOAuth2AuthorizedClientProvider(); | ||
provider.setAccessTokenResponseClient(oAuth2AccessTokenResponseClient()); | ||
return provider; | ||
} | ||
|
||
private DefaultJwtBearerTokenResponseClient oAuth2AccessTokenResponseClient() { | ||
DefaultJwtBearerTokenResponseClient client = new DefaultJwtBearerTokenResponseClient(); | ||
client.setRequestEntityConverter(new TokenExchangeJwtBearerGrantRequestEntityConverter()); | ||
return client; | ||
} | ||
|
||
private OAuth2TokenValidator<Jwt> jwtValidator() { | ||
List<OAuth2TokenValidator<Jwt>> validators = new ArrayList<>(); | ||
String issuerUri = properties.getIssuerUri(); | ||
if (StringUtils.hasText(issuerUri)) { | ||
validators.add(new JwtIssuerValidator(issuerUri)); | ||
} | ||
if (StringUtils.hasText(audience)) { | ||
validators.add(new JwtClaimValidator<>(JwtClaimNames.AUD, audiencePredicate(audience))); | ||
} | ||
validators.add(new JwtTimestampValidator()); | ||
return new DelegatingOAuth2TokenValidator<>(validators); | ||
} | ||
|
||
Predicate<Object> audiencePredicate(String audience) { | ||
return aud -> { | ||
if (aud == null) { | ||
return false; | ||
} else if (aud instanceof String) { | ||
return aud.equals(audience); | ||
} else if (aud instanceof List) { | ||
return ((List<?>) aud).contains(audience); | ||
} else { | ||
return false; | ||
} | ||
}; | ||
} | ||
|
||
} |
61 changes: 61 additions & 0 deletions
61
playground-backend/src/main/java/ch/sbb/playgroundbackend/config/SwaggerConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package ch.sbb.playgroundbackend.config; | ||
|
||
import io.swagger.v3.oas.models.Components; | ||
import io.swagger.v3.oas.models.OpenAPI; | ||
import io.swagger.v3.oas.models.info.Contact; | ||
import io.swagger.v3.oas.models.info.Info; | ||
import io.swagger.v3.oas.models.security.OAuthFlow; | ||
import io.swagger.v3.oas.models.security.OAuthFlows; | ||
import io.swagger.v3.oas.models.security.Scopes; | ||
import io.swagger.v3.oas.models.security.SecurityRequirement; | ||
import io.swagger.v3.oas.models.security.SecurityScheme; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import java.util.Collections; | ||
|
||
@Configuration | ||
public class SwaggerConfiguration { | ||
|
||
private static final String OAUTH_2 = "oauth2"; | ||
|
||
@Value("${info.app.version}") | ||
private String applicationVersion; | ||
|
||
@Value("${springdoc.swagger-ui.oauth.clientId}") | ||
private String clientId; | ||
|
||
@Value("${spring.security.oauth2.authorizationUrl}") | ||
private String authorizationUrl; | ||
|
||
@Bean | ||
public OpenAPI gleisspiegelOpenAPIConfiguration() { | ||
return new OpenAPI() | ||
.components(new Components().addSecuritySchemes(OAUTH_2, addOAuthSecurityScheme())) | ||
.security(Collections.singletonList(new SecurityRequirement().addList(OAUTH_2))) | ||
.info(apiInfo()); | ||
} | ||
|
||
private Info apiInfo() { | ||
final String versionInformation = StringUtils.isNotBlank(applicationVersion) ? " v " + applicationVersion : ""; | ||
return new Info() | ||
.title("Playground Backend" + versionInformation) | ||
.contact(new Contact() | ||
.name("Team Zug") | ||
.url("https://github.com/SchweizerischeBundesbahnen/DAS")); | ||
} | ||
|
||
private SecurityScheme addOAuthSecurityScheme() { | ||
final Scopes scopes = new Scopes().addString(clientId + "/.default", "Global access"); | ||
|
||
final OAuthFlows flowAuthorizationCode = new OAuthFlows().authorizationCode(new OAuthFlow() | ||
.authorizationUrl(authorizationUrl + "/authorize") | ||
.tokenUrl(authorizationUrl + "/token") | ||
.scopes(scopes)); | ||
|
||
return new SecurityScheme().name(OAUTH_2).type(SecurityScheme.Type.OAUTH2).flows(flowAuthorizationCode); | ||
} | ||
|
||
} |
16 changes: 16 additions & 0 deletions
16
...va/ch/sbb/playgroundbackend/config/TokenExchangeJwtBearerGrantRequestEntityConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package ch.sbb.playgroundbackend.config; | ||
|
||
import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest; | ||
import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequestEntityConverter; | ||
import org.springframework.util.MultiValueMap; | ||
|
||
public class TokenExchangeJwtBearerGrantRequestEntityConverter extends JwtBearerGrantRequestEntityConverter { | ||
|
||
@Override | ||
protected MultiValueMap<String, String> createParameters(JwtBearerGrantRequest jwtBearerGrantRequest) { | ||
MultiValueMap<String, String> parameters = super.createParameters(jwtBearerGrantRequest); | ||
parameters.add("requested_token_use", "on_behalf_of"); | ||
return parameters; | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
...round-backend/src/main/java/ch/sbb/playgroundbackend/config/WebSecurityConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package ch.sbb.playgroundbackend.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
|
||
import static org.springframework.security.config.Customizer.withDefaults; | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
public class WebSecurityConfiguration { | ||
|
||
@Bean | ||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { | ||
http | ||
.authorizeHttpRequests((authConfig) -> { | ||
authConfig.requestMatchers("/swagger-ui/**").permitAll(); | ||
authConfig.requestMatchers("/v3/api-docs/**").permitAll(); | ||
authConfig.requestMatchers("/actuator/health/*").permitAll(); | ||
authConfig.requestMatchers("/actuator/info").permitAll(); | ||
authConfig.requestMatchers("/customClaim").permitAll(); | ||
authConfig.requestMatchers("/**").authenticated(); | ||
} | ||
) | ||
// Disable csrf for now as it makes unauthenticated requests return 401/403 | ||
.csrf(AbstractHttpConfigurer::disable) | ||
.oauth2ResourceServer((oauth2) -> | ||
oauth2.jwt(withDefaults()) | ||
); | ||
return http.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters