Gateway oauth2
Gateway implementado con Spring Cloud Gateway y Spring Security basado en oauth2.
Authorization Grant implementados:
- Request resource (sin access-token)
- Request access-token
- Response access-token
- Request resource (con access-token)
Gateway
Implementacion de gateway basada en Spring Cloud Gateway. Es responsable de brindar un unico punto de acceso a los recursos desplegados en una red de externa/interna (outbound/inbound). Gestiona todo lo relacionado con seguridad, enrutamiento, reintentos, caching, etc.
Los predicados usados para matchear las rutas definidas, asi como los filtros a aplicar a los request/response pueden encontrarse aqui
Existe un global filter responsable de enrutar las rutas bajo los schemas http/https usando webclient
@Bean
public WebClientHttpRoutingFilter webClientHttpRoutingFilter(WebClient webClient, ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
return new WebClientHttpRoutingFilter(webClient, headersFilters);
}
Security
Manejada por Spring Security e integrada con oauth2 usando Resource Owner Password Credentials y Client Credentials
Authorization Server
Componente encargado de generar access/refresh tokens para poder acceder a los recursos protegidos sobre el Resource Server
En esta demo el auth server se implemento sobre Okta. Hay algunas guias muy interesantes acerca de como desplegar y configurar un auth server sobre Okta
Los detalles del provider oauth2 configurado se puede encontrar aqui
Client
Componente encargado de consumir los recursos servidos por el Resource Server en nombre del Resource Owner
Esta implementacion esta basada en Reactive para poder integrarse con Spring Cloud Gateway (ver SecurityConfig)
El webclient utilizado por el WebClientHttpRoutingFilter esta configurado con oauth2 a traves de un ExchangeFilterFunction.
@Bean
WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth.setDefaultOAuth2AuthorizedClient(true);
oauth.setDefaultClientRegistrationId(client-registration-id);
return WebClient.builder()
.filter(oauth)
.build();
}
De esta manera cada peticion que necesite ser enrutada por el WebClientHttpRoutingFilter se hara a traves de este webclient, y el mismo gestionara los tokens de acceso a traves de un ReactiveOAuth2AuthorizedClientManager
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
//.refreshToken()
.password()
.clientCredentials()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// For the `password` grant, the `username` and `password` are supplied via request parameters,
// so map it to `OAuth2AuthorizationContext.getAttributes()`.
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
}
Los detalles de la configuracion de los clientes oauth2 se encuentra aqui
Resource Server
Componente encargado de servir los recursos protegidos y desplegado en http://resource:9000
La configuracion para validar la validez de los access tokens puede encontrarse aqui
Para acceder al endpoint /resource el cliente debera presentar un JWT con el scope 'openid' o 'my_scope' (ver SecurityConfig)
Pruebas
Hay un set de pruebas que puede utilizarse para:
- Probar el acceso a los recursos protegidos en http://resource:9000/resource a traves del gateway
- Probar el acceso a los recursos protegidos en http://resource:9000/resource sin pasar por el gateway
Run
Para levantar el resource server y el gateway (client) ejecutar docker-compose up -d
Pre-requisitos
Un authorization server y dos aplicaciones clientes registradas (una basada en client credentials y otra en password grant)
Configuracion
Por medio de la config client-registration-id
es posible configurar cual cliente utilizar para la autorizacion