diff --git a/README.MD b/README.MD index 412c4f9c9..22b7db95f 100644 --- a/README.MD +++ b/README.MD @@ -1,37 +1,43 @@ # Ease OAuth2 / OpenID Configuration & Tests in Spring Boot 3 -## What's new in `8.0.0` +## Latest news -`8.0.0`, is out. It is designed to work with Spring Boot `3.4.0` (Security `6.4.0` and Cloud `2024.0.0`). +:rocket: `8.0.0`, is out. It is designed to work with Spring Boot `3.4.0` (Security `6.4.0` and Cloud `2024.0.0`). See [the relaease notes](https://github.com/ch4mpy/spring-addons/blob/master/release-notes.md#800) for details. -- [`spring-addons-starter-rest`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-rest) now expose as `@Bean` some `RestClient` and `WebClient` instances (or builders) with the following configured using application properties: - - Base URI - - `Basic` or `Bearer` authorization. For the second, with a choice of using an OAuth2 client registration or forwarding the access token in the security context. - - Connection & read timeouts - - HTTP or SOCKS proxy, with consideration of the standard `HTTP_PROXY` and `NO_PROXY` environment variables (finer-grained configuration can be applied with custom properties) -- [`spring-addons-starter-oidc`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-oidc) auto-configuration for `oauth2Login` is improved with: - - Working [Back-Channel Logout](https://openid.net/specs/openid-connect-backchannel-1_0.html), even with cookie-based CSRF protection and `logout+jwt` tokens (which makes it finally usable with [OAuth2 BFF](https://www.baeldung.com/spring-cloud-gateway-bff-oauth2) & [Keycloak](https://www.baeldung.com/spring-boot-keycloak)). - - Configurable status for unauthorized requests. The default is still `302 Found` (redirect to login), but it's a snap to change it to `401 Unauthorized` (like REST APIs should return, even stateful ones). -- `OAuthentication` now extends `AbstractOAuth2TokenAuthenticationToken` for a better integration with the rest of the Spring Security ecosystem. See the [migration guide](https://github.com/ch4mpy/spring-addons/tree/master/migrate-to-8.0.0.md) for details. +Give a try to the new [`spring-addons-starter-rest`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-rest), it can be a game changer for inter-service calls when OAuth2 or an HTTP proxy is involved. ## [`spring-addons-starter-oidc`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-oidc) -A spring Boot starter to reduce Java Security conf to 0 in resource servers and clients with `oauth2Login`. The auto-configuration using application properties include: +`spring-boot-starter-oauth2-client` and `spring-boot-starter-resource-server` help a lot when it comes to configure a Spring application as an OAuth2 client or resource server. But their defaults very rarely statisfy a production use-case and we almost always need to write the `Security(Web)FilterChain` in application code, which can be a verbose, complicated, and error prone task. + +`spring-addons-starter-oidc` builds on top of _"offical"_ starters to significantly reduce the need for security configuration code. It even brings it down to 0 in most cases. + +It's important to note that we have a complete control over what `spring-addons-starter-oidc` auto-configures. The handles we have for that are application properties, of course, but also bean definitions: almost all auto-configured components are `@ConditionalOnMissingBean`, meaning that `spring-addons` backs off each time a component is explicitely defined in an application. + +Auto-configuration for resource servers: - accepting tokens issued by several trusted authorization servers - mapping authorities from a variety of claims (including nested ones), with custom prefix and case +- CORS configuration +- allowing anonymous preflight requests using the path-matchers in CORS configuration + +Auto-configuration for clients with `oauth2Login`: - customizing OAuth2 responses: - specify the URI in `Location` header to activate a route after login / logout (defaults can be defined in application properties and overridden by the frontend using headers or query parameters) - set the HTTP status in the `2xx` range to observe the response in Javascript code and trigger plain navigation instead of letting the browser follow a redirection with a cross-origin request - exposing CSRF token as a cookie accessible to a single-page application - logging out from an authorization server not strictly implementing RP-Initiated Logout (case of Auth0 and Amazon Cognito for instance) -- activating and configuring Back-Channel Logout in a Spring application with `oauth2Login` +- activating and configuring Back-Channel Logout - adding extra parameters to authorization & token requests (like the `audience` required by Auth0) -- having per environment CORS configuration (not allowing the same origins in staging and prod for instance) +- CORS configuration - allowing anonymous preflight requests using the path-matchers in CORS configuration ## [`spring-addons-starter-rest`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-rest) -A spring Boot starter to expose REST clients auto-configured with requests authorization, HTTP proxy settings, and more. For OAuth2 authorization, we have a choice of using a new token using any Spring OAuth2 client `registration`, or to re-use the access token in the security context of an `oauth2ResourceServer`. +At the age of OpenAPI and client code generation, the main challenge for inter-service communication is the configuration of REST clients. Spring promotes the usage of `RestClient` or `WebClient`, but configuring those for `Basic` or `Bearer` authentication, an HTTP proxy, and connection & read timeouts is pretty complicated, verbose, and error-prone. + +`spring-addons-starter-rest` makes this configuration a snap. It even exposes the clients or their builder as beans. + +For OAuth2 authorization, we have a choice of using a new token using any Spring OAuth2 client `registration`, or to re-use the access token in the security context of an `oauth2ResourceServer`. Sample usage ```yaml @@ -57,39 +63,9 @@ com: # Authorize outgoing requests with the Bearer token obtained using an OAuth2 client registration oauth2-registration-id: bidule-registration ``` -This exposes pre-configured beans that we can auto-wire in any kind of `@Component`, like `@Controller` or `@Service`, or use in `@Configuration`. For instance: -```java -@Configuration -public class RestConfiguration { - /** - * @param machinClient pre-configured by spring-addons-starter-rest using application properties - * @return a generated implementation of the {@link MachinApi} {@link HttpExchange @HttpExchange}, exposed as a bean named "machinApi". - */ - @Bean - MachinApi machinApi(RestClient machinClient) throws Exception { - return new RestClientHttpExchangeProxyFactoryBean<>(MachinApi.class, machinClient).getObject(); - } - - /** - * @param biduleClientBuilder pre-configured using application properties - * @return a {@link RestClient} bean named "biduleClient" - */ - @Bean - RestClient biduleClient(RestClient.Builder biduleClientBuilder) throws Exception { - // Fine-tune biduleClientBuilder configuration - return biduleClientBuilder.build(); - } - - /** - * @param biduleClient the bean exposed just above - * @return a generated implementation of the {@link BiduleApi} {@link HttpExchange @HttpExchange}, exposed as a bean named "biduleApi". - */ - @Bean - BiduleApi biduleApi(RestClient biduleClient) throws Exception { - return new RestClientHttpExchangeProxyFactoryBean<>(BiduleApi.class, biduleClient).getObject(); - } -} -``` +This exposes pre-configured `RestClient` or `WebClient` beans (or their builders) that we can auto-wire in any kind of `@Component` - like `@Controller` & `@Service` - or use in `@Configuration` - for instance to generate implementations of `@HttpExchange` interfaces and expose them as beans. + +Proxy configuration is applied by default to REST clients as soon as the `HTTP_PROXY` and `NO_PROXY` environment variables are set. This can be overridden and disabled with application properties. ## Unit & Integration Testing With Security diff --git a/release-notes.md b/release-notes.md index 366708c68..3602ab03e 100644 --- a/release-notes.md +++ b/release-notes.md @@ -6,18 +6,15 @@ For Spring Boot 3.4.x. `spring-addons-starter-rest` provides auto-configuration for `RestClient`, `WebClient` and tooling for `@HttpExchange` proxy generation. ### `8.0.0` -- `spring-addons-starter-oidc`: - - **[Back-Channel Logout](https://openid.net/specs/openid-connect-backchannel-1_0.html)** support. Enabled only if an `OidcBackChannel(Server)LogoutHandler` bean is present. A default `OidcBackChannel(Server)LogoutHandler` bean is provided if `com.c4-soft.springaddons.oidc.client.back-channel-logout.enabled` property is `true` (`false` by default). - - `authenticationEntryPoint` is now configurable with spring-addons for OAuth2 clients with `oauth2Login` (instead of `oauth2ResourceServer`). The default bean returns `302 redirect to login` unless another status is set with other OAuth2 responses statuses overrides in properties. Resource servers authentication entrypoint returns `401`. - - `authenticationSuccessHandler` and `authenticationFailureHandler` are now default beans for OAuth2 clients with `oauth2Login` with a status that can be overridden from properties. -- `spring-addons-starter-rest`: auto-configure `RestClient` and `WebClient` (or their builders) using properties and expose them as named beans. Configuration properties include: - - base URI: can be switched at each deployement. - - `Basic` or `Bearer` authorization. The `Bearer` token can be resolved using an OAuth2 client registration or, if the application is a resource server, from the security context. - - HTTP proxy. Supports `HTTP_PROXY` & `NO_PROXY` environment variables, but finer grained custom properties can be used. - - connect and read timeouts. - - force usage of `WebClient` in a servlet app (`RestClient` is the default for servlets). -- Boot `3.4.0` (with Security `6.4.0` as transitive dependencies). - +- [`spring-addons-starter-rest`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-rest) now expose as `@Bean` some `RestClient` and `WebClient` instances (or builders) with the following configured using application properties: + - Base URI + - `Basic` or `Bearer` authorization. For the second, with a choice of using an OAuth2 client registration or forwarding the access token in the security context. + - Connection & read timeouts + - HTTP or SOCKS proxy, with consideration of the standard `HTTP_PROXY` and `NO_PROXY` environment variables (finer-grained configuration can be applied with custom properties) +- [`spring-addons-starter-oidc`](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-starter-oidc) auto-configuration for `oauth2Login` is improved with: + - Working [Back-Channel Logout](https://openid.net/specs/openid-connect-backchannel-1_0.html), even with cookie-based CSRF protection and `logout+jwt` tokens (which makes it finally usable with [OAuth2 BFF](https://www.baeldung.com/spring-cloud-gateway-bff-oauth2) & [Keycloak](https://www.baeldung.com/spring-boot-keycloak)). + - Configurable status for unauthorized requests. The default is still `302 Found` (redirect to login), but it's a snap to change it to `401 Unauthorized` (like REST APIs should return, even stateful ones). +- `OAuthentication` now extends `AbstractOAuth2TokenAuthenticationToken` for a better integration with the rest of the Spring Security ecosystem. See the [migration guide](https://github.com/ch4mpy/spring-addons/tree/master/migrate-to-8.0.0.md) for details. ## `7.x` Branch For Spring Boot 3.3.x. diff --git a/spring-addons-starter-rest/README.md b/spring-addons-starter-rest/README.md index 3c43a217d..bb9e96f4c 100644 --- a/spring-addons-starter-rest/README.md +++ b/spring-addons-starter-rest/README.md @@ -44,12 +44,9 @@ com: springaddons: rest: client: + # this exposes a bean named "machinClient" machin-client: base-url: http://localhost:${machin-api-port} - # expose a WebClient instead of a RestClient in a servlet app - type: WEB_CLIENT - # expose the WebClient.Builder instead of an already built WebClient - expose-builder: true http: chunk-size: 1000 connect-timeout-millis: 1000 @@ -67,8 +64,11 @@ com: oauth2: # authorize outgoing requests with the Bearer token in the security (possible only in a resource server app) forward-bearer: true + # this exposes a bean named "biduleClientBuilder" (mind the "expose-builder: true" below) bidule-client: base-url: http://localhost:${bidule-api-port} + # expose the RestClient.Builder instead of an already built RestClient + expose-builder: true authorization: oauth2: # authorize outgoing requests with a Bearer obtained using an OAuth2 client registration @@ -78,9 +78,12 @@ com: # use HTTP_PROXY and NO_PROXY environment variables and add proxy authentication username: spring-backend password: secret + # this exposes a bean named "chose" (mind the "bean-name: chose" below) chose-client: base-url: http://localhost:${chose-api-port} - # change the bean name to "chose" (default would have bean "choseClient" because of the "chose-client" ID, or "choseClientBuilder" if expose-builder was true) + # expose a WebClient instead of a RestClient in a servlet app + type: WEB_CLIENT + # change the bean name to "chose" bean-name: chose authorization: # authorize outgoing requests with Basic auth @@ -91,30 +94,37 @@ com: proxy: enabled: false ``` -The builder for the first client can be used as follows: +The `biduleClientBuilder` bean can be used to define a `biduleClient` bean as follows: ```java -@Configuration -public class RestConfiguration { - @Bean - WebClient machinClient(WebClient.Builder machinClientBuilder) throws Exception { - // Add some configuration to the machinClientBuilder - return machinClientBuilder.build(); - } +/** + * @param biduleClientBuilder pre-configured using application properties + * @return a {@link RestClient} bean named "biduleClient" + */ +@Bean +RestClient biduleClient(RestClient.Builder biduleClientBuilder) throws Exception { + // Fine-tune biduleClientBuilder configuration + return biduleClientBuilder.build(); } ``` ## Exposing a generated `@HttpExchange` proxy as a `@Bean` Once the REST clients are configured, we may use it to generate `@HttpExchange` implementations: ```java -@Configuration -public class RestConfiguration { - /** - * @param machinClient might be auto-configured by spring-addons-starter-rest or a hand-crafted bean - * @return a generated implementation of the {@link MachinApi} {@link HttpExchange @HttpExchange}, exposed as a bean named "machinApi". - */ - @Bean - MachinApi machinApi(RestClient machinClient) throws Exception { - return new RestClientHttpExchangeProxyFactoryBean<>(MachinApi.class, machinClient).getObject(); - } +/** + * @param machinClient pre-configured by spring-addons-starter-rest using application properties + * @return a generated implementation of the {@link MachinApi} {@link HttpExchange @HttpExchange}, exposed as a bean named "machinApi". + */ +@Bean +MachinApi machinApi(RestClient machinClient) throws Exception { + return new RestClientHttpExchangeProxyFactoryBean<>(MachinApi.class, machinClient).getObject(); +} + +/** + * @param biduleClient the bean exposed just above + * @return a generated implementation of the {@link BiduleApi} {@link HttpExchange @HttpExchange}, exposed as a bean named "biduleApi". + */ +@Bean +BiduleApi biduleApi(RestClient biduleClient) throws Exception { + return new RestClientHttpExchangeProxyFactoryBean<>(BiduleApi.class, biduleClient).getObject(); } ```