interface WebFilter {
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
}
class SampleWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange);
}
}
MetricsWebFilter
: métriques de success/error, temps, ...WebFilterChainProxy
: securitéHeadersFilter
: custom (sauvegarde des header pour forward au backend)LocaleFilter
: header Accept-Language
CurrentUserFilter
: header X-User
WebFilterChainProxy
@Bean
SecurityWebFilterChain configure(ServerHttpSecurity http) {
return http.oauth2ResourceServer()
.jwt()
//.jwkSetUri(...)
.and()
.and()
.build();
}
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: ${OAUTH2_URI}/pf/JWKS
Ordre : set > bean > auto-configuration
protected void configure(ServerHttpSecurity http) {
ReactiveAuthenticationManager authenticationManager = getAuthenticationManager();
// ...
}
private ReactiveAuthenticationManager getAuthenticationManager() {
if (this.authenticationManager != null) {
return this.authenticationManager;
}
ReactiveJwtDecoder jwtDecoder = getJwtDecoder();
// ...
}
protected ReactiveJwtDecoder getJwtDecoder() {
return (this.jwtDecoder != null) ? this.jwtDecoder : getBean(ReactiveJwtDecoder.class);
}
http.oauth2Login();
spring.security.oauth2.client:
provider:
adeo:
issuer-uri: ${OPENID_URI}
registration:
adeo:
provider: adeo
client-id: ${OPENID_CLIENT_ID}
client-secret: ${OPENID_CLIENT_SECRET}
authorization-grant-type: authorization_code
scope: [ openid, groups, profile ]
redirect-uri: ${FRONTEND_URL}/api/auth/login/oauth2/code/{registrationId}
http.opaqueToken();
spring.security.oauth2.resourceserver.opaquetoken:
issuer-uri: ${OPENID_URI}/as/introspect.oauth2
client-id: ${OPENID_CLIENT_ID}
client-secret: ${OPENID_CLIENT_SECRET}
401
Défaut de .oauthLogin()
: redirection vers /login
Besoin: error 401
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusServerEntryPoint(UNAUTHORIZED))
Exemple : /doLogin?redirect_uri=http://example.org
Défaut de oauthLogin()
:
quand AccessDeniedException
ServerRequestCache#saveRequest()
& redirect to /login
ServerRequestCache#getRedirectUri()
& redirectMais:
/oauth2/authorization/{registrationId}
: pas de AccessDeniedException
authenticationEntryPoint()
OAuth2AuthorizationRequestRedirectWebFilter
OAuth2LoginAuthenticationWebFilter
Uniquement si requête de login : authorizationRequestResolver.resolve()
Adapter/Proxy
Uniquement si succès : onAuthenticationSuccess()
Adapter/Proxy
Pas super customisable
Impossible de récupérer les composants pré-configurés
ServerOAuth2AuthorizationRequestResolver
& ServerAuthenticationSuccessHandler
Plutôt que bearer en clair côté frontend.
OAuth login :
ReactorContextWebFilter
ServerSecurityContextRepository
: WebSessionServerSecurityContextRepository
Resource server : header Authorization
Dans OAuth2LoginAuthenticationWebFilter
: ne garde que le Principal
contenant l'id_token
, et oublie l'access_token
Customisation : ServerOAuth2AuthorizedClientRepository
.oauth2Login().authorizedClientRepository(...)
Avant les requêtes : ServerAuthenticationConverter
.oauth2ResourceServer().bearerTokenConverter(...)
access_token
Ne contient pas d'information de l'utilisateur
Authorisé par le userinfo_endpoint
id_token
userinfo_endpoint
access_token
http.oauth2ResourceServer().opaqueToken()
Ne permet pas la convertion du Authentication
ni du user info
http.oauth2ResourceServer().authenticationManagerResolver()
Composant plus bas-niveau
user info + Authentication
custom
Sérialisation des données : string
Caractères autorisés
Taille limitée : ≈ 5000 caractères
Chiffrement : augmente la taille
Cookie
impossible
compliqué