diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20ad67759..09ecdbee1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Examples of behavior that contributes to creating a positive environment include Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks -- ublic or private harassment +- Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting diff --git a/README.MD b/README.MD index 531f6253b..9a9083b1c 100644 --- a/README.MD +++ b/README.MD @@ -2,9 +2,9 @@ You can now **test your OAuth2 / OpenID knowledge with a dedicated quiz** availa 7.x is a break through in usability: all 6 `spring-addons` Boot starters are merged into a single one: [`com.c4-soft.springaddons:spring-addons-starter-oidc`](https://repo1.maven.org/maven2/com/c4-soft/springaddons/spring-addons-starter-oidc/), and so are 4 of the test libs: [`com.c4-soft.springaddons:spring-addons-starter-oidc-test`](https://repo1.maven.org/maven2/com/c4-soft/springaddons/spring-addons-starter-oidc-test/). To use the test annotations without the starter, the dependency is unchanged: [`com.c4-soft.springaddons:spring-addons-oauth2-test`](https://repo1.maven.org/maven2/com/c4-soft/springaddons/spring-addons-oauth2-test/). -Please follow the [migration guide](https://github.com/ch4mpy/spring-addons/blob/master/7.0.0-migration-guide.md) to move from `6.x` to `7.1.1`. There is no urge to do so on existing projects as 6.2.x patches should be published untill the end of 2023. +Please follow the [migration guide](https://github.com/ch4mpy/spring-addons/blob/master/7.0.0-migration-guide.md) to move from `6.x` to `7.1.1`. There is no urge to do so on existing projects as 6.2.x patches should be published until the end of 2023. -All samples and tutorials sources are migrated to latest starter and test annotations, but some READMEs might still need a refresh. Please make sure you refer to source code for up to date configuration. +All samples and tutorials sources are migrated to latest starter and test annotations, but some READMEs might still need a refresh. Please make sure you refer to source code for up-to-date configuration. # Ease OpenID Configuration & Tests in Spring Boot 3 The libraries hosted in this repo shine in two domains: @@ -15,17 +15,17 @@ The libraries hosted in this repo shine in two domains: * more specialized annotations for specific authentication implementations (`@WithOAuth2Login`, `@WithOidcLogin`, etc.) or to use as elements for your own test annotations in applications using custom OAuth2 `Authentication` implementations - pushing OIDC auto-configuration to the next level in Spring Boot 3 applications. As shown in **[Tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials)**, with 0 Java conf (just properties), we can configure: * authorities mapping (source claims, prefix and case transformation), without having to provide authentication converter, user service or `GrantedAuthoritiesMapper` in each app - * fine grained CORS configuration (per path matcher), which enables to override allowed origins as environment variable when switching from `localhost` to `dev` or `prod` environments + * fine-grained CORS configuration (per path matcher), which enables to override allowed origins as environment variable when switching from `localhost` to `dev` or `prod` environments * sessions & CSRF disabled by default on resource server and enabled on clients. If a cookie repo is chosen for CSRF (as required by Angular, React, Vue, etc.), then the right request handler is configured and a filter to actually set the cookie is added - * basic access control: `permitAll` for a list of path matchers and `authenticated` as default (to be fine tuned with method security or a configuration post-processor bean) + * basic access control: `permitAll` for a list of path matchers and `authenticated` as default (to be fine-tuned with method security or a configuration post-processor bean) * for clients only: - logout success handler for OPs not strictly following the standard (exotic parameter names or missing `end_session_endpoint` in OpenID configuration). Auth0 and Amazon Cognito are samples of such OPs. - client host and port explicitly provided in login configuration to avoid [redirection issues when the client does not use 8080 (or 8443 if SSL is enabled)](https://github.com/spring-projects/spring-security/issues/12307) - - add custom params to authorization-code request (like the `audience` required by Auth0). This parameters are defined in application properties for each client registration. - - multi-tenancy: allow users to be logged in with more than one OpenID Provider and keep track of their different `Authentication` instances (one per OP, with most probably different `subject` and user name). + - add custom params to authorization-code request (like the `audience` required by Auth0). These parameters are defined in application properties for each client registration. + - multi-tenancy: allow users to be logged in with more than one OpenID Provider and keep track of their different `Authentication` instances (one per OP, with most probably different `subject` and username). Jump to: -- [0. Risks Of Using This Libs And Mitigations](#drawbacks) +- [0. Risks Of Using These Libs And Mitigations](#drawbacks) - [1. Spring Boot OIDC Starter](#oidc-starter) - [2. Unit & Integration Testing With Security](#unit-tests) - [3. Where to Start](#start) @@ -33,10 +33,10 @@ Jump to: - [5. Release Notes](#release-notes) - [6. Maven-Central Reminders](#maven-central) -## 0. Risks Of Using This Libs And Mitigations +## 0. Risks Of Using These Libs And Mitigations Neither the owner of this repo nor any of the contributors are part of Spring Security team. At best, some are occasional contributors to the "official" framework. -However, unless you have a deep knowledge of Spring Security for OAuth2, using `spring-addons-starter-oidc` might actually be safer than experimenting with the conf by yourself. And the more popularity this repo gets, the safer it is: more people detect potential issues, more people can keep it alive if its initiator disapears and, if some features where to become popular enough, Spring team could consider pulling it in the official framework. +However, unless you have a deep knowledge of Spring Security for OAuth2, using `spring-addons-starter-oidc` might actually be safer than experimenting with the conf by yourself. And the more popularity this repo gets, the safer it is: more people detect potential issues, more people can keep it alive if its initiator disappears and, if some features where to become popular enough, Spring team could consider pulling it in the official framework. Also, all you have to do to opt-out `spring-addons-starter-oidc` at any point in time is writing Spring Security Configuration by yourself. Refer to tutorials if you need some guidance to do that, the following are written without `spring-addons-starter-oidc` (just `spring-boot-starter-oauth2-client` or `spring-boot-starter-oauth2-resource-server`): - [reactive-client](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-client) @@ -47,15 +47,15 @@ Also, all you have to do to opt-out `spring-addons-starter-oidc` at any point in What are the identified risks of using the resources from such a repo and how can you protect against it? - *what if the updates to latest dependencies stop and no PR are merged anymore?* You can fork this repo and start a new branch from the last tag you like - *what if the library takes a direction I don't like?* Same as for a stale repo -- *what if the owner deletes this repo or makes it private?* The source code for each release is published to maven-central. You can get the source [there](https://repo1.maven.org/maven2/com/c4-soft/springaddons/) or from any of the forks on Github (about 50 in August 2023). -- *what is the risk of vulnerabilities introduced by the code in this libs?* This depends on the lib: +- *what if the owner deletes this repo or makes it private?* The source code for each release is published to maven-central. You can get the source [there](https://repo1.maven.org/maven2/com/c4-soft/springaddons/) or from any of the forks on GitHub (about 50 in August 2023). +- *what is the risk of vulnerabilities introduced by the code in these libs?* This depends on the lib: * libs to be used during tests (`spring-addons-oauth2-test` and `spring-addons-starter-oidc-test`) should be imported with `test` scope => it should not be present at runtime => no risk in production - * `spring-addons-starter-oidc` does some auto-configuration for you: it defines Spring beans involved in your application security. So yes, if a default is missconfigured in this lib, it can have an impact on your app. You should however consider that: + * `spring-addons-starter-oidc` does some auto-configuration for you: it defines Spring beans involved in your application security. So yes, if a default is miss-configured in this lib, it can have an impact on your app. You should however consider that: - an increasing number of user inspect it and open issues or PRs when detecting a problem (the community is probably much bigger than your team working at detecting Spring Security configuration issues in your own projects) - having code centralised at one place and reused at many places reduces the risk of a careless mistake in one of your app ## 1. Spring Boot Starter -**This starters is designed to push auto-configuration to the next level** and does nothing more than helping you to configure Spring Security beans using application properties. +**This starter is designed to push auto-configuration to the next level** and does nothing more than helping you to configure Spring Security beans using application properties. `spring-addons-oidc-starter` does not replace `spring-boot-starter-oauth2-resource-server` and `spring-boot-starter-oauth2-client`, it uses application properties to configure a few beans designed to be picked by Spring Boot official "starters". The aim is to reduce Java code and ease application deployment across environments. In most cases, you should need 0 Java conf. An effort was made to make [tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials), Javadoc as informative as possible. Please refer there for more details. @@ -68,7 +68,7 @@ You can refer to [module, dependency, class and other diagrams](https://sourcesp Add `com.c4-soft.springaddons:spring-addons-starter-oidc` to your dependencies, in addition to `org.springframework.boot:spring-boot-starter-oauth2-client` or `org.springframework.boot:spring-boot-starter-oauth2-resource-server`. -If configuring an Outh2 client (with `oauth2Login`), define the standard Spring Boot `provider` and `registration` properties for OAuth2 clients. +If configuring an OAuth2 client (with `oauth2Login`), define the standard Spring Boot `provider` and `registration` properties for OAuth2 clients. If configuring an OAuth2 resource server with access token introspection, define the standard Spring Boot `opaquetoken` properties. @@ -282,7 +282,7 @@ You can override about any `@Bean` defined by spring-addons (almost all are `@Co - `ClaimSetAuthoritiesConverter`: opt-out the `ConfigurableClaimSetAuthoritiesConverter`, responsible for authorities mapping - `GrantedAuthoritiesMapper`: in OAuth2 clients, opt-out the default `GrantedAuthoritiesMapper` (which delegates authorities mapping to the `ConfigurableClaimSetAuthoritiesConverter` just above) - `(Reactive)AuthenticationManagerResolver`: opt-out the authentication manager implementing static multi-tenancy for resource servers with JWT decoders -- `ResourceServerAuthorizeExchangeSpecPostProcessor`, `ClientAuthorizeExchangeSpecPostProcessor`, `ClientAuthorizeExchangeSpecPostProcessor` or `ResourceServerAuthorizeExchangeSpecPostProcessor`: fine grained access control from configuration (an alternative is using `@Enable(Reactive)MethodSecurity` and `@PreAuthorize` on controller methods) +- `ResourceServerAuthorizeExchangeSpecPostProcessor`, `ClientAuthorizeExchangeSpecPostProcessor`, `ClientAuthorizeExchangeSpecPostProcessor` or `ResourceServerAuthorizeExchangeSpecPostProcessor`: fine-grained access control from configuration (an alternative is using `@Enable(Reactive)MethodSecurity` and `@PreAuthorize` on controller methods) - `ResourceServerHttpSecurityPostProcessor` or `ClientHttpSecurityPostProcessor`: post-process spring-addons auto-configured `SecurityFilterChains` (this enables to change absolutely anything from it). ### 1.3. Disabling `spring-addons-oidc-starter` @@ -293,7 +293,7 @@ The easiest way is to exclude it from the classpath, but you may also turn the a ## 2. Unit & Integration Testing With Security Testing method security (`@PreAuthorize`, `@PostFilter`, etc.) requires to configure the security context. `Spring-security-test` provides with `MockMvc` request post-processors and `WebTestClient` mutators to do so, but this requires the context of a request, which limits its usage to testing secured controllers. -To test method security on any type of `@Component` (`@Controller`, off course, but also `@Service` and `@Repository`) there are only two options: build tests security context by yourself and populate it with stubbed / mocked authentications, or use annotations to do it for you. **This lib conatins annotations to configure test security context with OAuth2 authentication at your hand.** +To test method security on any type of `@Component` (`@Controller`, off course, but also `@Service` and `@Repository`) there are only two options: build tests security context by yourself and populate it with stubbed / mocked authentications, or use annotations to do it for you. **This lib contains annotations to configure test security context with OAuth2 authentication at your hand.** An [article covering the usage of OAuth2 test annotations from this lib](https://www.baeldung.com/spring-oauth-testing-access-control) was published on Baeldung. This, along with all [samples](https://github.com/ch4mpy/spring-addons/tree/master/samples) and [tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials) source-code (which contain a lot of unit and integration testing), should be enough to get you started. @@ -318,7 +318,7 @@ public class SecuredService { Now, let's assume that you have a staging environment with a few representative users ("personas" if you are familiar with UX), for which you can get sample access tokens, and dump the claims in JSON files in test resources in (by decoding JWTs with a tool like https://jwt.io or introspecting opaque tokens). In the following, we'll consider you have a user named `brice` with `NICE` authority and another one named `igor` without the `NICE` authority. We'll also consider you have dumped sample claim-sets in `brice.json` and `igor.json`. #### 2.1.1. Using `@WithMockAuthentication` -When testing RBAC (role-based access control), defining just authorities is frequently enough. Sometimes, defining the `Authentication#name` is necessary and in a few cases, application code needs a specific `Authentication` implementation. `@WithMockAuthentication` was designed to meet this requirements: +When testing RBAC (role-based access control), defining just authorities is frequently enough. Sometimes, defining the `Authentication#name` is necessary and in a few cases, application code needs a specific `Authentication` implementation. `@WithMockAuthentication` was designed to meet these requirements: ```java @SpringBootTest(classes = { SecurityConfig.class, MessageService.class }) class MessageServiceTests { @@ -400,10 +400,10 @@ There are we few things worth noting above: ### 2.2. Which Dependency / Annotation to Use `spring-addons-oauth2-test` is enough to use test annotations, but if you opted for `spring-addons-starter-oidc`, then `spring-addons-starter-oidc-test` is better suited as it comes with tooling to load spring-addons auto-configuration during tests (refer to the many samples for usage). -`@WithMockAuthentication` should be enough to test applications with RBAC (role-based access control): it allows to easily define `name` and `authorities`, as well as the Authentication an principal types to mock if your application code expects something specific. +`@WithMockAuthentication` should be enough to test applications with RBAC (role-based access control): it allows to easily define `name` and `authorities`, as well as the Authentication a principal types to mock if your application code expects something specific. In case your access-control uses more than just name and authorities, you'll probably need to define claim-set details. In this case, `@WithJwt` and `@WithOpaqueToken` can come pretty handy as it uses respectively the JWT or OpaqueToken authentication converter in your security configuration to build the authentication instance, using a JSON payload from the classpath (or a plain Java String): you might just dump payloads of access tokens for representative users in test resources (use a tool like https://jwt.io to easily get those payloads). -This starters are designed to push auto-configuration one step further. In most cases, you should need 0 Java conf. An effort was made to make [tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials), Javadoc and modules READMEs as informative as possible. Please refer there for more details. Additionally refer to [module, dependency, class and other diagrams](https://sourcespy.com/github/ch4mpyspringaddons/) for a general overview of the repository. +These starters are designed to push auto-configuration one step further. In most cases, you should need 0 Java conf. An effort was made to make [tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials), Javadoc and modules READMEs as informative as possible. Please refer there for more details. Additionally refer to [module, dependency, class and other diagrams](https://sourcespy.com/github/ch4mpyspringaddons/) for a general overview of the repository. ## 3. Where to Start [Tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials) which cover: @@ -470,7 +470,7 @@ I could forget to update README before releasing, so please refer to [maven cent - [gh-151](https://github.com/ch4mpy/spring-addons/issues/151) scan application context for `authenticationEntryPoint` and `accessDeniedHandler` to auto-configure resource servers (default returns `401` for unauthorized requests instead of `302 redirect to login`). #### `7.1.9` -- Spring boot `3.1.4` as transcient dependency +- Spring boot `3.1.4` as transient dependency - [gh-147](https://github.com/ch4mpy/spring-addons/issues/147) prevent addons test security conf to be auto-configured (complicates integration testing with test containers) #### `7.1.8` @@ -488,7 +488,7 @@ I could forget to update README before releasing, so please refer to [maven cent #### `7.1.1` - Remove Back-Channel Logout experimental support. Follow the [PR on Spring Security](https://github.com/spring-projects/spring-security/pull/12570) for official support. - Multi-tenancy support on OAuth2 clients is now optional and disabled by default. Set `com.c4-soft.springaddons.oidc.client.multi-tenancy-enabled=true` to keep it activated. -- [gh-140](https://github.com/ch4mpy/spring-addons/issues/140): use AOP instead of custom authorized-client repositories to support multi-tenancy on OAuth2 clients. That way, any configured authorized-client repository is instrumented (no need to proxy or extand spring-addons one). +- [gh-140](https://github.com/ch4mpy/spring-addons/issues/140): use AOP instead of custom authorized-client repositories to support multi-tenancy on OAuth2 clients. That way, any configured authorized-client repository is instrumented (no need to proxy or extend spring-addons one). #### `7.0.8` - client `SecurityFilterChain` with `LOWEST_PRIORITY - 1` (instead of `HIGHEST_PRIORITY + 1`) @@ -499,7 +499,7 @@ I could forget to update README before releasing, so please refer to [maven cent - force usage of `AntPathRequestMatcher` when defining `permit-all` in servlet implementations because of https://spring.io/security/cve-2023-34035 (Spring `6.1.2`) #### `7.0.6` -- Fix the a confusion between user subject and principal name in `SpringAddons(Server)OAuth2AuthorizedClientRepository` which could cause an authorized client not to be found when using another claim than subject as principal name. +- Fix a confusion between user subject and principal name in `SpringAddons(Server)OAuth2AuthorizedClientRepository` which could cause an authorized client not to be found when using another claim than subject as principal name. #### `7.0.3` - Fix the condition to add a filter inserting CSRF protection cookie to responses @@ -520,7 +520,7 @@ See the [migration guide](https://github.com/ch4mpy/spring-addons/blob/master/7. #### `6.2.1` - Spring Boot 3.1.2 -- Fix the a confusion between user subject and principal name in `SpringAddons(Server)OAuth2AuthorizedClientRepository` which could cause an authorized client not to be found when using another claim than subject as principal name. +- Fix a confusion between user subject and principal name in `SpringAddons(Server)OAuth2AuthorizedClientRepository` which could cause an authorized client not to be found when using another claim than subject as principal name. #### `6.2.0` - remove `OAuth2AuthenticationFactory`: instead, use `Converter`, `Converter>`, `OpaqueTokenAuthenticationConverter` or `ReactiveOpaqueTokenAuthenticationConverter` @@ -529,7 +529,7 @@ See the [migration guide](https://github.com/ch4mpy/spring-addons/blob/master/7. - remove the archetypes #### `6.1.16` -- [gh-133](https://github.com/ch4mpy/spring-addons/issues/133) Add a property to auto configure an `audience` JWT validator (if present, the `aud` claim in the token will be checked to contain the URI provided in the conf) +- [gh-133](https://github.com/ch4mpy/spring-addons/issues/133) Add a property to auto-configure an `audience` JWT validator (if present, the `aud` claim in the token will be checked to contain the URI provided in the conf) #### `6.1.15` - [gh-129](https://github.com/ch4mpy/spring-addons/issues/129) Auto-configure (with application properties) additional parameters for authorization-code request. This allows, for instance, to send an `audience` as required by Auth0. Additional parameters are defined for each client registration. In the following sample, `client-registration` `a` and `b` references an existing entries in spring.security.oauth2.client.registration: @@ -563,7 +563,7 @@ void givenUserIsAuthenticatedWithJsonClaims_whenGetClaims_thenOk() throws Except api.get("/greet").andExpect(status().isOk()).andExpect(content().string("Hello Ch4mp! You are granted with [ROLE_AUTHORIZED_PERSONNEL].")); } ``` -- [gh-127](https://github.com/ch4mpy/spring-addons/issues/127) add a `json` property to @OpenIdClaims to define all calims with a JSON string +- [gh-127](https://github.com/ch4mpy/spring-addons/issues/127) add a `json` property to @OpenIdClaims to define all claims with a JSON string ```java @WithMockJwtAuth( authorities = { "ROLE_AUTHORIZED_PERSONNEL" }, @@ -777,7 +777,7 @@ Use `JwtAuthenticationToken` or `BearerAuthenticationToken` by default in resou #### `5.0.0` Rename modules to: - have all module names start with `spring-addons` prefix, then intermediate module if any (`archetypes`, `samples`, `starters`, `webmvc` or `webflux`) and last what leaf module aims at -- better reflect what it do +- better reflect what it does For instance, `spring-security-oauth2-webmvc-addons` only applies to resource-servers secured with JWTs (not to opaque tokens) -> renamed to `spring-addons-webmvc-jwt-resource-server` @@ -923,12 +923,12 @@ Cleanup and prepare for spring-boot 3: - replace `name` from `@WithMockKeycloakAuth` with `preferedUsername` in `@WithAccessToken` - support for private claims in `@WithMockOidcId` and `@WithMockKeycloakAuth` (claims with values of type `int`, `long`, `String` and `String[]` only) - add missing subject claim in Keycloak access and ID tokens -- compose `@WithAccessToken` with `@WithKeycloakIDToken` instead of repeting properties (`AccessToken` extends `IDToken`) +- compose `@WithAccessToken` with `@WithKeycloakIDToken` instead of repeating properties (`AccessToken` extends `IDToken`) - add advanced `@WithMockKeycloakAuth` sample usage in [`spring-addons-oauth2-test` README](https://github.com/ch4mpy/spring-addons/tree/master/spring-addons-oauth2-test) #### `2.1.0` - fix Keycloak typo (was wrongly spelled Keycloack at many places) -- add samples with authrities retieved from a DB instead of the JWT for both OAuthentication and JwtAuthenticationToken +- add samples with authorities retrieved from a DB instead of the JWT for both OAuthentication and JwtAuthenticationToken - add sample involving `keycloak-spring-boot-starter` and `keycloak-spring-security-adapter` #### `2.0.0` @@ -942,13 +942,13 @@ This release is still focused on unit-testing Spring OAuth2 applications - Use Keycloak as authorisation-server for all resource-server samples, each of which configuring a specific `Authentication` impl Note that I chose Keycloak because it's a feature rich, easy to setup authorisation-server. -It should not be much of an effort to migrate sample resource-servers to another one, with an exception of those using `KeycloakAuthenticationToken` as authentication impl, of course. +It should not be much of an effort to migrate sample resource-servers to another one, with an exception to those using `KeycloakAuthenticationToken` as authentication impl, of course. ## 6. Maven-Central Reminders Cheat-sheets for me when setting up a new development environment -### 6.1. GPG Sigin Key +### 6.1. GPG Sign Key ``` bash gpg --list-keys # if key absent, then generate one with diff --git a/samples/README.md b/samples/README.md index f85153b37..6aaf98ba7 100644 --- a/samples/README.md +++ b/samples/README.md @@ -2,7 +2,7 @@ Please start with [tutorials](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials) and then clone this repo to run / hack samples. -Samples for different security scenari, with **configuration, unit and integration tests** for +Samples for different security scenarios, with **configuration, unit and integration tests** for - servlet (webmvc) / reactive (weblux) apps - JWT decoder / access token introspection - spring's `JwtAuthenticationToken` (JWT decoder) or `BearerTokenAuthentication` (introspection) / this repo `OAuthentication` @@ -14,8 +14,8 @@ All sample using of this repo starters `@AutoConfiguration`, there are 3 sources - auto-configured beans for servlet or reactive apps - @Bean overrides in main class -## `Authentication` implementations usablity -Samples makes use of three different `Authentication` but have the same structure: a simple @RestController retrieves messages from a @Service which in turn uses a @Repository. +## `Authentication` implementations usability +Samples makes use of three different `Authentication` but have the same structure: a simple `@RestController` retrieves messages from a `@Service` which in turn uses a `@Repository`. Here are the results for the `greet()` method accessing granted authorities and `preffered_username` OpenID claim: diff --git a/samples/tutorials/README.md b/samples/tutorials/README.md index 82aba9f42..9fb16d7ba 100644 --- a/samples/tutorials/README.md +++ b/samples/tutorials/README.md @@ -1,7 +1,7 @@ # Securing Spring Applications With OAuth2 -These tutorials are focused on configuring OAuth2 security in Spring Spring Boot 3 applications with OpenID Provider(s). +These tutorials are focused on configuring OAuth2 security in Spring Boot 3 applications with OpenID Provider(s). -**You should carefully read the [OAuth2 essentials](#oauth_essentials) section before rushing to a specific tutorial**. This might save you a lot of time and inform you with some of the latest recommandations (using only confidential clients, hiding tokens from users devices, ...) which have a strong impact on single-page applications and deprecate most of the tutorials available on the web. +**You should carefully read the [OAuth2 essentials](#oauth_essentials) section before rushing to a specific tutorial**. This might save you a lot of time and inform you with some of the latest recommendations (using only confidential clients, hiding tokens from users devices, ...) which have a strong impact on single-page applications and deprecate most of the tutorials available on the web. Once you have determined if the application to configure is an OAuth2 client or an OAuth2 resource server, and [setup at least one OIDC Provider](#prerequisites), then refer the [Tutorials scenarios](#scenarios) and pick one matching your needs. @@ -12,18 +12,18 @@ Jump to: ## 1. OAuth2 essentials -OAuth2 client and resource-server configuration are very different. **Spring provides with different starters for a reason**. If you're not sure about the definitions, needs and responsibilities of those two, please please take 5 minutes to read this section before you start. You may **test your OAuth2 / OpenID knowledge with the dedicated quiz** available at [https://quiz.c4-soft.com/ui/quizzes](https://quiz.c4-soft.com/ui/quizzes) +OAuth2 client and resource-server configuration are very different. **Spring provides with different starters for a reason**. If you're not sure about the definitions, needs and responsibilities of those two, please take 5 minutes to read this section before you start. You may **test your OAuth2 / OpenID knowledge with the dedicated quiz** available at [https://quiz.c4-soft.com/ui/quizzes](https://quiz.c4-soft.com/ui/quizzes) ### 1.1 Actors - **resource-owner**: think of it as end-user. Most frequently a physical person, but can be a batch or whatever trusted program authenticated with client-credential (or even a device authenticated with a flow we'll skip) -- **authorization-server**: the server issuing and certifying resource-owners and clients identities. It is sometimes refered to as *issuer* or *OIDC Provider* (*OP*). -- **client**: a piece of software which needs to access resources on one or more resource-servers. **It is responsible for acquiring tokens from the authorization server and authorizing its requests to resource-servers**, and as so to handle OAuth2 flows. It is sometimes refered to as *Relying Party* (*RP*). +- **authorization-server**: the server issuing and certifying resource-owners and clients identities. It is sometimes referred to as *issuer* or *OIDC Provider* (*OP*). +- **client**: a piece of software which needs to access resources on one or more resource-servers. **It is responsible for acquiring tokens from the authorization server and authorizing its requests to resource-servers**, and as so to handle OAuth2 flows. It is sometimes referred to as *Relying Party* (*RP*). - **resource-server**: an API (most frequently REST). **It should not care about login, logout or any OAuth2 flow.** From its point of view, all that matters is if a request is authorized with a valid access token and taking access decisions based on it. It is important to note that **a front-end is not necessarily an OAuth2 client**: in the **B**ackend **F**or **F**rontend pattern, the OAuth2 client is on the server, between resource server(s) (secured with access tokens) and web (Angular, React, Vue, ...) or mobile applications which are secured with sessions and never see OAuth2 tokens. ### 1.2. Client VS Resource Server Configuration -As already wrote, the responsibilities and security requirements are quite different. Lets explore that in more details. +As already wrote, the responsibilities and security requirements are quite different. Let's explore that in more details. #### 1.2.1. Need for Sessions **Resource servers can usually be configured as stateless (without session)**. The "state" is associated with the access token which is enough to restore the security context of a request. This has valuable benefits for scalability and fault tolerance: any resource server instance can process any request without the need of sharing a session. Also, the access token protects against CSRF attacks and, if it is rotated frequently enough (every minute or so), against BREACH attacks too! @@ -65,9 +65,9 @@ Resource-server validates the token and retrieves user details either by: **Used to authenticate a client on behalf of an end-user (physical persons).** 0. client and resource server fetch OpenID configuration from the OIDC Provider -1. the frontend "exits" to redirect the unauthorized user to the authorization server using system browser. If the user already has an opened session on the authorization server, the login succeeds silently. Otherwize, the user is prompted for credentials, biometry MFA tokens or whatever has been configured on the OP. -2. once user authenticated, the authorization-server redirects the user back to the client with a `code` to be used once. This redirection happens in the sytem browser used to initiate the `authorization_code` flow. -3. client contacts authorization-server to exchanges the `code` for an access token (and optionally ID & refresh tokens). +1. the frontend "exits" to redirect the unauthorized user to the authorization server using system browser. If the user already has an opened session on the authorization server, the login succeeds silently. Otherwise, the user is prompted for credentials, biometry MFA tokens or whatever has been configured on the OP. +2. once user authenticated, the authorization-server redirects the user back to the client with a `code` to be used once. This redirection happens in the system browser used to initiate the `authorization_code` flow. +3. client contacts authorization-server to exchange the `code` for an access token (and optionally ID & refresh tokens). 4. the frontend sends REST requests to the resource server by the intermediate of the OAuth2 client (which replaces the session cookie with an `Authorization` header containing a `Bearer` access token) 5. resource server validates access token (using JWT public key fetched once or introspecting each token on the OP) and takes access-control decision @@ -77,7 +77,7 @@ In the schematic above, the authorization-code flow starts at step 1 and ends wi In the case of a native application a mechanism like Android app links or iOS universal links can be used at step 2 to provide the frontend with the authorization-code. The frontend then uses its own user agent to forward the code to the OAuth2 client. As the tokens fetched at step 3 are stored by the client in the session associated with the user agent which provided the authorization-code, **it is important that the frontend uses the same user agent to send the authorization-code as the one it's going to use for the REST requests needing to be authorized**. -In the case of a SPA the user agent is the system browser, so no special care is needed at step 2 to send the authorization-code to the OAuth2 client. At the end of step 3, the OAuth2 client responds with a redirection to the frontend (the browser re-enters the SPA). +In the case of an SPA the user agent is the system browser, so no special care is needed at step 2 to send the authorization-code to the OAuth2 client. At the end of step 3, the OAuth2 client responds with a redirection to the frontend (the browser re-enters the SPA). In the case of a server-side rendered UI (Thymeleaf, JSF, etc.), the OAuth2 client is the frontend, so everything happens internally without you notice much. @@ -95,9 +95,9 @@ In OAuth2, **opaque tokens** can be used instead of JWTs, but it requires intros #### 1.4.2. access token Pretty much like a paper proxy you could give to someone else to vote for you. It contains as minimum following attributes: -- issuer: the authorization-server which emitted the token (police officer or alike who certified identities of people who gave and recieved proxy) +- issuer: the authorization-server which emitted the token (police officer or alike who certified identities of people who gave and received proxy) - subject: resource-owner unique identifier (person who grants the proxy) -- scope: what this token can be used for (did the resource owner grant a proxy for voting, managing a bank account, get a parcell at post-office, etc.) +- scope: what this token can be used for (did the resource owner grant a proxy for voting, managing a bank account, get a parcel at post-office, etc.) - expiry: until when can this token be used A token to be sent by client as Bearer `Authorization` header in its requests to resource-server. access tokens content should remain a concern of authorization and resource servers only (client should not try to read access tokens) @@ -147,22 +147,22 @@ There is a triple motivation behind this: ### 3.1. OAuth2 Resource Server With Just `spring-boot-starter-oauth2-resource-server` Configure Spring Boot 3 applications as OAuth2 resource server (REST API) with authorities mapping to enable RBAC using roles defined on OIDC Providers. -This tutorials are using only the "official" `spring-boot-starter-oauth2-resource-server` and are available for both +These tutorials are using only the "official" `spring-boot-starter-oauth2-resource-server` and are available for both [servlets](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-resource-server) and [reactive applications](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-resource-server). ### 3.2. OAuth2 Client With Just `spring-boot-starter-oauth2-client` Configure Spring Boot 3 applications as OAuth2 clients (Thymeleaf UI) with login, logout and authorities mapping to enable RBAC using roles defined on OIDC Providers. -This tutorials are using only the "official" `spring-boot-starter-oauth2-client` and are available for both [servlets](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-client) and [reactive applications](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-client) +These tutorials are using only the "official" `spring-boot-starter-oauth2-client` and are available for both [servlets](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-client) and [reactive applications](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-client) ### 3.3. [`resource-server_with_oauthentication`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/resource-server_with_oauthentication) -Demos how to use a custom OAuth2 `Authentication` implementation: `OAthentication` with typed accessors to OpenID claims. +Demos how to use a custom OAuth2 `Authentication` implementation: `OAuthentication` with typed accessors to OpenID claims. This tutorial introduces `spring-addons-starter-oidc`, which greatly simplifies Java configuration compared to section `3.1.`: all the Java configuration is replaced with application properties. ### 3.4. [`resource-server_with_specialized_oauthentication`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/resource-server_with_specialized_oauthentication) Builds on top of preceding, showing how to -- extend `OAthentication` implementation to add private claims of your own +- extend `OAuthentication` implementation to add private claims of your own - tweek `spring-addons-webmvc-jwt-resource-server` auto-configuration - enrich security SpEL @@ -177,14 +177,14 @@ Configure a Spring Boot 3 application as both OAuth2 client (Thymeleaf UI) and O This is done by defining two distinct and ordered security filter-chains: - the 1st with client configuration, with login, logout, and a security matcher limiting it to UI resources -- the 2nd with resource server configuration. As it has no security matcher and an higher order, it intercepts all requests that were not matched by the 1st filter chain and acts as default for all the remaining resources (REST API). +- the 2nd with resource server configuration. As it has no security matcher and a higher order, it intercepts all requests that were not matched by the 1st filter chain and acts as default for all the remaining resources (REST API). The Thymeleaf pages being secured with session cookies and the REST end-points with JWTs, the Thymeleaf `@Controller` internally uses `WebClient` to fetch data from the API and build the model for the template, authorizing its requests with tokens stored in session. ### 3.8. [BFF](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/bff) Introduction to the **B**ackend **F**or **F**rontend pattern with `spring-cloud-gateway` as middle-ware between a JS application (Angular) secured with sessions cookies and a Spring OAuth2 resource-server secured with JWTs. -The latest SNAPSHOT is deployed by CI / CD to a publicly available K8s cluster managed by [OVH](https://www.ovhcloud.com/fr/public-cloud/kubernetes/)): https://bff.demo.c4-soft.com/ui/ +The latest SNAPSHOT is deployed by CI / CD to a publicly available K8s cluster managed by [OVH](https://www.ovhcloud.com/fr/public-cloud/kubernetes/): https://bff.demo.c4-soft.com/ui/ ### 3.9. [Resource Server with dynamic tenants](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/resource-server_multitenant_dynamic) Sample of advanced customization of spring-addons auto-configuration: in this tutorial, the resource server should accept access tokens issued by any issuer hosted on a list of servers we trust (for instance dynamically generated Keycloak realms). For that, we'll customize the way issuer properties are resolved and also modify the authentication manager resolver to create a new authentication manager for each new issuer hosted on a server we trust. diff --git a/samples/tutorials/reactive-client/README.md b/samples/tutorials/reactive-client/README.md index 8c91e33ca..7a0b664f7 100644 --- a/samples/tutorials/reactive-client/README.md +++ b/samples/tutorials/reactive-client/README.md @@ -2,7 +2,7 @@ In this tutorial, we'll configure a reactive (WebFlux) Spring Boot 3 application as an OAuth2 client with login, logout and authorities mapping to enable RBAC using roles defined on OIDC Providers, **without `spring-addons-starter-oidc`**, which makes its security configuration quite more verbose compared to the configuration of the BFF gateway. ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Project Initialization We start after [prerequisites](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#2-prerequisites), and consider that we have a minimum of 1 OIDC Provider configured (2 would be better) and users with and without `NICE` role declared on eac OPh. @@ -172,7 +172,7 @@ logout: logout-uri: ${auth0-issuer}v2/logout post-logout-uri-parameter-name: returnTo ``` -Now, we can define a logout success handler parsing this configuration for non standard RP-Initiated Logout (taking "inspiration" from the `OidcClientInitiatedServerLogoutSuccessHandler`: +Now, we can define a logout success handler parsing this configuration for non-standard RP-Initiated Logout (taking "inspiration" from the `OidcClientInitiatedServerLogoutSuccessHandler`: ```java @RequiredArgsConstructor static class AlmostOidcClientInitiatedServerLogoutSuccessHandler implements ServerLogoutSuccessHandler { @@ -235,7 +235,7 @@ static class AlmostOidcClientInitiatedServerLogoutSuccessHandler implements Serv } } ``` -This handler is fine for non-standard OPs, but if want to keep Spring's logout success handler for Keycloak (and avoid defining logout properties for it), we need a facade for the two implementations we now have: +This handler is fine for non-standard OPs, but if we want to keep Spring's logout success handler for Keycloak (and avoid defining logout properties for it), we need a facade for the two implementations we now have: ```java @RequiredArgsConstructor static class DelegatingOidcClientInitiatedServerLogoutSuccessHandler implements ServerLogoutSuccessHandler { @@ -467,7 +467,7 @@ To demo RBAC, let's define a new `src/main/resources/static/nice.html` page whic ``` -This off course requires to update the security configuration as follow: +This off course requires to update the security configuration as follows: ```java http.authorizeExchange(ex -> ex .pathMatchers("/login/**", "/oauth2/**").permitAll() @@ -561,7 +561,7 @@ private WebFilter loginPageWebFilter() { }; } ``` -We can then update the security filter-chain configuration as follow: +We can then update the security filter-chain configuration as follows: ```java @Bean SecurityWebFilterChain clientSecurityFilterChain( @@ -591,4 +591,4 @@ But wait, what we did here is pretty verbose and we'll need it in almost any OAu Also, what if we actually need to users to have several authorized clients at the same time (for instance be authenticated on Google and Facebook at the same time to query Google API and Facebook graph from the same client)? Well, as suggested in previous section, you might have to provide with an alternate `ServerOAuth2AuthorizedClientRepository`. This repo client starters propose such an implementation storing an authentication per issuer in the user session and then resolving the right one (with its subject) before trying to retrieve an authorized client. Again, if you don't want to use those starters, you'll have to write [your own](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration). -Last, you might have a look a integration tests in source code to see how access control rules to `/`, `/login` and `nice.html` are verified with mocked security contexts. \ No newline at end of file +Last, you might have a look into integration tests in source code to see how access control rules to `/`, `/login` and `nice.html` are verified with mocked security contexts. \ No newline at end of file diff --git a/samples/tutorials/reactive-resource-server/README.md b/samples/tutorials/reactive-resource-server/README.md index 9fe2870c4..3011a0e6f 100644 --- a/samples/tutorials/reactive-resource-server/README.md +++ b/samples/tutorials/reactive-resource-server/README.md @@ -4,7 +4,7 @@ In this tutorial, we'll configure a reactive (WebFlux) Spring Boot 3 application We'll also see how to accept access tokens issued by several, potentially heterogeneous, OIDC Providers (or Keycloak realms). ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Project Initialization We start after [prerequisites](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#2-prerequisites), and consider that we have a minimum of 1 OIDC Provider configured (2 would be better) and users with and without `NICE` role declared on each OP. @@ -38,7 +38,7 @@ This is how we want our REST API to be configured: - state-less session management (no session, user state in access token only) - disabled CSRF (safe because there is no session) - public access to a limited list of resources -- non "public" routes require users to be authenticated, fine grained access-control being achieved with method-security (`@PreAuthrorize` and alike) +- non "public" routes require users to be authenticated, fine-grained access-control being achieved with method-security (`@PreAuthrorize` and alike) - 401 (unauthorized) instead 302 (redirecting to login) when a request to a protected resource is made with missing or invalid authorization ## 3.1. Security Properties @@ -194,7 +194,7 @@ To ease roles claims parsing, we'll use [json-path](https://central.sonatype.com ``` #### 3.3.2. Application Properties -Then, we need some additional configuration properties to provide with the flexibility to change, for each issuer the claims containing the user name and roles +Then, we need some additional configuration properties to provide with the flexibility to change, for each issuer the claims containing the username and roles ```java @Data @Configuration @@ -353,7 +353,7 @@ public Mono getRestricted() { ``` ### 4. Multi-Tenancy -So far, our resource server is able to accept identities issued by a any OIDC Provider, but only one per resource server instance. This is frequently enough, but not always. +So far, our resource server is able to accept identities issued by any OIDC Provider, but only one per resource server instance. This is frequently enough, but not always. For instance, when working with Keycloak, we can consider all realms as distinct OPs. We'll have to provide some additional configuration for a single resource server instance to accept requests from users identified on different realms. diff --git a/samples/tutorials/resource-server_multitenant_dynamic/README.md b/samples/tutorials/resource-server_multitenant_dynamic/README.md index 35f3efa5a..e758e1707 100644 --- a/samples/tutorials/resource-server_multitenant_dynamic/README.md +++ b/samples/tutorials/resource-server_multitenant_dynamic/README.md @@ -2,7 +2,7 @@ Sample of advanced customization of spring-addons auto-configuration: in this tutorial, the resource server should accept access tokens issued by any issuer hosted on a list of servers we trust (for instance dynamically generated Keycloak realms). For that, we'll customize the way issuer properties are resolved and also modify the authentication manager resolver to create a new authentication manager for each new issuer hosted on a server we trust. ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Prerequisites We assume that [tutorials main README prerequisites section](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#prerequisites) has been achieved and that you have a minimum of 1 OIDC Provider (2 would be better) with ID and secret for clients configured with authorization-code flow. diff --git a/samples/tutorials/resource-server_with_additional-header/README.md b/samples/tutorials/resource-server_with_additional-header/README.md index 02fb41d04..e38324c20 100644 --- a/samples/tutorials/resource-server_with_additional-header/README.md +++ b/samples/tutorials/resource-server_with_additional-header/README.md @@ -1,12 +1,12 @@ # Authentication containing data from both the access token and a custom header ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Overview -For this tutorial, we will assume that in addition to to a JWT **access token** in the `Authorization` header, the OAuth2 client provides with a JWT **ID token** in a `X-ID-Token` header. +For this tutorial, we will assume that in addition to a JWT **access token** in the `Authorization` header, the OAuth2 client provides with a JWT **ID token** in a `X-ID-Token` header. -Be sure your environment meets [tutorials prerequisits](https://github.com/ch4mpy/spring-addons/blob/master/samples/tutorials/README.md#prerequisites). +Be sure your environment meets [tutorials prerequisites](https://github.com/ch4mpy/spring-addons/blob/master/samples/tutorials/README.md#prerequisites). ## 2. Project Initialization We'll start a spring-boot 3 project with the help of https://start.spring.io/ @@ -32,7 +32,7 @@ Then add dependencies to: ``` -If for whatever reason you don't want to use `spring-addons-starter-oidc`, see [`servlet-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-resource-server) or [`reactive-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-resource-server) for basic configuration with `spring-boot-starter-oauth2-resource-server`. Spoiler, it is quite more verbose and error prone. +If for whatever reason you don't want to use `spring-addons-starter-oidc`, see [`servlet-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-resource-server) or [`reactive-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-resource-server) for basic configuration with `spring-boot-starter-oauth2-resource-server`. Spoiler, it is quite more verbose and error-prone. ## 3. Web-Security Configuration This configuration will use the pretty convenient [`com.c4_soft.springaddons.security.oauth2.config.synchronised.HttpServletRequestSupport`](https://github.com/ch4mpy/spring-addons/blob/master/webmvc/spring-addons-webmvc-core/src/main/java/com/c4_soft/springaddons/security/oauth2/config/synchronised/HttpServletRequestSupport.java) which provides tooling to access the current request, and in our case, its headers. If we were writing a WebFlux application, we'd use is reactive equivalent: [`com.c4_soft.springaddons.security.oauth2.config.reactive.ServerHttpRequestSupport`](https://github.com/ch4mpy/spring-addons/blob/master/webflux/spring-addons-webflux-core/src/main/java/com/c4_soft/springaddons/security/oauth2/config/reactive/ServerHttpRequestSupport.java). If you don't use `spring-addons-starter-oidc`, you might need to copy some code from one of this support classes. diff --git a/samples/tutorials/resource-server_with_introspection/README.md b/samples/tutorials/resource-server_with_introspection/README.md index 94978c77f..155cb3c05 100644 --- a/samples/tutorials/resource-server_with_introspection/README.md +++ b/samples/tutorials/resource-server_with_introspection/README.md @@ -1,12 +1,12 @@ # How to configure a Spring REST API with token introspection ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Overview -The aim here is to setup security for a Spring Boot 3 resource server access token introspection on **any OpenID authorization-server**: those exposing an introspection endpoint in their OpenID configuration (like Keycloak), but also those just exposing a `/userinfo` endpoint (like Auth0 and Amazon Cognito). +The aim here is to set up security for a Spring Boot 3 resource server access token introspection on **any OpenID authorization-server**: those exposing an introspection endpoint in their OpenID configuration (like Keycloak), but also those just exposing a `/userinfo` endpoint (like Auth0 and Amazon Cognito). -For each and every request it process, resource servers will send a request to authorization-server to get token details. This has **serious performance impact** compared to JWT-decoder based security where authorization-server is accessed only once to retrieve signing key. +For each and every request it processes, resource servers will send a request to authorization-server to get token details. This has **serious performance impact** compared to JWT-decoder based security where authorization-server is accessed only once to retrieve signing key. ## 2. Authorization-server requirements We assume that [tutorials prerequisites](https://github.com/ch4mpy/spring-addons/blob/master/samples/tutorials/README.md#prerequisites) are satisfied and that a minimum of 1 OIDC Provider is configured with a client and authorization-code to authenticate users. As it is hard to guess from which OP was issued an opaque token, we will accept identities from only one issuer. To provide with multi-tenancy and token introspection, we would need a custom header or something containing the issuer URI, for our resource server to know where it should introspect it. This additional complexity is out of the scope of this tutorial and, instead, we'll work with profiles to switch between OPs. @@ -44,10 +44,10 @@ Then add dependencies to spring-addons: ``` -If for whatever reason you don't want to use `spring-addons-starter-oidc`, see [`servlet-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-resource-server) or [`reactive-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-resource-server) for basic configuration with `spring-boot-starter-oauth2-resource-server`. Spoiler, it is quite more verbose and error prone. +If for whatever reason you don't want to use `spring-addons-starter-oidc`, see [`servlet-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/servlet-resource-server) or [`reactive-resource-server`](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/reactive-resource-server) for basic configuration with `spring-boot-starter-oauth2-resource-server`. Spoiler, it is quite more verbose and error-prone. ## 5. Application Properties -Let's first define some constants later used in configuration, and sometimes overriden in profiles: +Let's first define some constants later used in configuration, and sometimes overridden in profiles: ```yaml scheme: http origins: ${scheme}://localhost:4200 @@ -80,7 +80,7 @@ spring: Next is some spring-addons configuration with: - CORS configuration (enables for instance to switch allowed-origins when deploying to a new environment) - `issuers`: provide with authorities mapping configuration (claim(s) to pick, as well as case and prefix transformations) -- `permit-all`: path matchers for "public" resources (accessible to unauthorized requests). Path not matched here require requests to be authorized (access control fine tuned with method security) +- `permit-all`: path matchers for "public" resources (accessible to unauthorized requests). Path not matched here require requests to be authorized (access control fine-tuned with method security) ```yaml com: c4-soft: @@ -145,7 +145,7 @@ The reasons why we could prefer `OAuthentication` over `BearerTo The token introspection we have works just fine with OIDC Providers exposing an `introspection_endpoint` in their OpenID configuration (like Keycloak does), but some just don't provide one (like Auth0 and Amazon Cognito). Hopefully, almost any OP exposes a `/userinfo` endpoint returning the OpenID claims of the user for whom was issued the access token in the Authorization header. ### 6.1. Additional Application Properties -Let's first define spring profiles with `introspection-uri` setted with userinfo URI for the OPs without an `introspection_endpoint`: +Let's first define spring profiles with `introspection-uri` settled with userinfo URI for the OPs without an `introspection_endpoint`: ```yaml --- com: diff --git a/samples/tutorials/resource-server_with_oauthentication/README.md b/samples/tutorials/resource-server_with_oauthentication/README.md index f4b86cc26..2375c5703 100644 --- a/samples/tutorials/resource-server_with_oauthentication/README.md +++ b/samples/tutorials/resource-server_with_oauthentication/README.md @@ -1,8 +1,8 @@ # How to configure a Spring REST API with `OAuthentication` -The aim here is to setup security for a Spring Boot 3 resource server with JWT decoding and a custom `Authentication` implementation instead of the default `JwtAuthenticationToken` +The aim here is to set up security for a Spring Boot 3 resource server with JWT decoding and a custom `Authentication` implementation instead of the default `JwtAuthenticationToken` ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Prerequisites We assume that [tutorials main README prerequisites section](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#prerequisites) has been achieved and that you have a minimum of 1 OIDC Provider (2 would be better) with ID and secret for clients configured with authorization-code flow. diff --git a/samples/tutorials/resource-server_with_specialized_oauthentication/README.md b/samples/tutorials/resource-server_with_specialized_oauthentication/README.md index 366eef722..b9ad203dd 100644 --- a/samples/tutorials/resource-server_with_specialized_oauthentication/README.md +++ b/samples/tutorials/resource-server_with_specialized_oauthentication/README.md @@ -1,12 +1,12 @@ # How to extend `OAuthentication` ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Overview -Lets says that we have business requirements where security is not role based only. +Let's say that we have business requirements where security is not role based only. -Lets assume that the authorization server also provides us with a `proxies` claim that contains a map of permissions per user "preferredUsername" (what current user was granted to do on behalf of some other users). +Let's assume that the authorization server also provides us with a `proxies` claim that contains a map of permissions per user "preferredUsername" (what current user was granted to do on behalf of some other users). This tutorial will demo - how to extend `OAuthentication` to hold those proxies in addition to authorities @@ -38,12 +38,12 @@ Then add dependencies to spring-addons: ``` -An other option would be to use one of `com.c4-soft.springaddons` archetypes (for instance [`spring-addons-archetypes-webmvc-singlemodule`](https://github.com/ch4mpy/spring-addons/tree/master/archetypes/spring-addons-archetypes-webmvc-singlemodule) or [`spring-addons-archetypes-webflux-singlemodule`](https://github.com/ch4mpy/spring-addons/tree/master/archetypes/spring-addons-archetypes-webflux-singlemodule)) +Another option would be to use one of `com.c4-soft.springaddons` archetypes (for instance [`spring-addons-archetypes-webmvc-singlemodule`](https://github.com/ch4mpy/spring-addons/tree/master/archetypes/spring-addons-archetypes-webmvc-singlemodule) or [`spring-addons-archetypes-webflux-singlemodule`](https://github.com/ch4mpy/spring-addons/tree/master/archetypes/spring-addons-archetypes-webflux-singlemodule)) ## 3. Web-Security Configuration ### 3.1. `ProxiesClaimSet` and `ProxiesAuthentication` -Lets first define what a `Proxy` is: +Let's first define what a `Proxy` is: ```java @Data public class Proxy implements Serializable { @@ -380,5 +380,5 @@ class GreetingControllerTest { } ``` -# 6. Conclussion +# 6. Conclusion This sample was guiding you to build a servlet application (webmvc) with JWT decoder and an `Authentication` of your own. If you need help to configure a resource server for webflux (reactive) or access token introspection, please refer to [samples](https://github.com/ch4mpy/spring-addons/tree/master/samples). diff --git a/samples/tutorials/resource-server_with_ui/README.md b/samples/tutorials/resource-server_with_ui/README.md index 6c0e57f0a..f16d9ccba 100644 --- a/samples/tutorials/resource-server_with_ui/README.md +++ b/samples/tutorials/resource-server_with_ui/README.md @@ -2,18 +2,18 @@ The aim here is to **configure a Spring back-end as both OAuth2 client and resource server while allowing users to authenticate among a list of heterogeneous trusted authorization-servers**: a local Keycloak realm as well as remote Auth0 and Cognito instances. ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Preamble We'll define two distinct and ordered security filter-chains: - the 1st with client configuration, with login, logout, and a security matcher limiting it to UI resources -- the 2nd with resource server configuration. As it has no security matcher and an higher order, it intercepts all requests that were not matched by the 1st filter chain and acts as default for all the remaining resources (REST API). +- the 2nd with resource server configuration. As it has no security matcher and a higher order, it intercepts all requests that were not matched by the 1st filter chain and acts as default for all the remaining resources (REST API). It is important to note that in this configuration, **the browser is not an OAuth2 client**: it is secured with regular sessions. As a consequence, **CSRF and BREACH protection must be enabled** in the client filter-chain. The UI being secured with session cookies and the REST end-points with JWTs, the Thymeleaf `@Controller` internally uses `WebClient` to fetch data from the API and build the model for the template, authorizing its requests with tokens stored in session. -What we will see here is a rather long journey mostly because we chose to demo a scenario where users can login from more than just one identity provider: **have active sessions with Keycloak and Auth0 and Cognito at the same time** (not "Keycloak or Auth0 or Cognito"), which clearly wasn't a use-case spring-security developpers had in mind when creating `OAuth2AuthenticationToken`, the `Authentication` implementation for OAuth2 clients. We will get around this limitations by using the user session to store the identity data we need to retrieve the right authorized client and send logout requests with the right ID-Token. **If we were interested in single tenant scenario only, things would get much simpler and we'll see how too**. +What we will see here is a rather long journey mostly because we chose to demo a scenario where users can login from more than just one identity provider: **have active sessions with Keycloak and Auth0 and Cognito at the same time** (not "Keycloak or Auth0 or Cognito"), which clearly wasn't a use-case spring-security developers had in mind when creating `OAuth2AuthenticationToken`, the `Authentication` implementation for OAuth2 clients. We will get around this limitations by using the user session to store the identity data we need to retrieve the right authorized client and send logout requests with the right ID-Token. **If we were interested in single tenant scenario only, things would get much simpler and we'll see how too**. To run the sample, be sure your environment meets [tutorials prerequisites](https://github.com/ch4mpy/spring-addons/blob/master/samples/tutorials/README.md#prerequisites). @@ -29,14 +29,14 @@ We will implement a Spring back-end with * asking the user to choose between the 3 authentication sources trusted by the resource server * sessions are required as requests from browsers won't be authorized with a Bearer token (CSRF protection should be activated too) * returning the default 302 (redirect to login) if the user has no session yet - * an index page, loaded after authentication, with links to Thymeleaf page and Swager-UI index + * an index page, loaded after authentication, with links to Thymeleaf page and Swagger-UI index * a login page to select an authorization-server (aka tenant): a local Keycloak realm along with remote Auth0 and Cognito instances * defining access-control to all OAuth2 client & UI resources: login, logout, authorization callbacks and Swagger-UI * a "greet" page where the user can - - get a greeting for each of the identity providers he his connected to + - get a greeting for each of the identity providers he is connected to - add an identity from one of the configured identity providers he is not authenticated against yet - logout from the identity providers he is connected to either individually or all of it - - invalidate his session from the Thymeleaf client without disconecting from identity providers + - invalidate his session from the Thymeleaf client without disconnecting from identity providers Here is what we will build should look like: ![greeting page screen-shot](https://github.com/ch4mpy/spring-addons/blob/master/samples/tutorials/resource-server_with_ui/readme-resources/greet.png) @@ -54,8 +54,8 @@ And then add those dependencies: - [`spring-addons-webmvc-client`](https://central.sonatype.com/artifact/com.c4-soft.springaddons/spring-addons-webmvc-client/6.1.5) it is a thin wrapper around `spring-boot-starter-oauth2-client` which pushes auto-configuration from properties one step further. It provides with: * a `SecurityWebFilterChain` with high precedence which intercepts all requests matched by `com.c4-soft.springaddons.security.client.security-matchers` * CORS configuration from properties - * an authorization requests resolver with the hostname and port resolved from properties (necessary as soon as you enbale SSL) - * a logout request URI builder configured from properties for "almost" OIDC complient providers (Auth0 and Cognito do not implement standrad RP-Initiated Logout) + * an authorization requests resolver with the hostname and port resolved from properties (necessary as soon as you enable SSL) + * a logout request URI builder configured from properties for "almost" OIDC compliant providers (Auth0 and Cognito do not implement standard RP-Initiated Logout) * a logout success handler using the above logout request URI builder * an authorities mapper configurable per issuer (and source claim) * AOP to support multi-tenancy on OAuth2 client (Spring Security is designed to allow a user to be authenticated against only one OpenID Provider at a time) @@ -63,7 +63,7 @@ And then add those dependencies: - [`spring-addons-webmvc-jwt-test`](https://central.sonatype.com/artifact/com.c4-soft.springaddons/spring-addons-webmvc-jwt-test/6.1.5) ## 4. Web-Security Configuration -This tutorial uses `spring-addons-webmvc-jwt-resource-server` and `spring-addons-webmvc-client` Spring Boot starters, which both auto-configure `SecurityFilterChain` based on properties file. **These security filter-chains are not explicitly defined in security-conf, but are there!**. +This tutorial uses `spring-addons-webmvc-jwt-resource-server` and `spring-addons-webmvc-client` Spring Boot starters, which both auto-configure `SecurityFilterChain` based on properties file. **These security filter-chains are not explicitly defined in security-conf, but are there!** ### 4.1. Resource Server configuration As exposed, we rely mostly on auto-configuration to secure REST end-points. The only access-control rules that we have to insert in our Java configuration are those restricting access to actuator (OpenAPI specification is public as per application properties). With `spring-addons-webmvc-jwt-resource-server`, this is done as follow: @@ -231,7 +231,7 @@ spring: activate: on-profile: ssl ``` -Non-standard logouts are then registered with properties under `com.c4-soft.springaddons.security.client` for each issuer, spring OIDC handler being used as default for non listed ones. +Non-standard logouts are then registered with properties under `com.c4-soft.springaddons.security.client` for each issuer, spring OIDC handler being used as default for non-listed ones. To implement a single tenant scenario, we would keep just a single entry in `spring.security.oauth2.client.provider`, `com.c4-soft.springaddons.security.issuers` and `com.c4-soft.springaddons.security.client.oauth2-logout` arrays. That easy. @@ -338,10 +338,10 @@ public class WebSecurityConf { ### 4.4. Logout This one is tricky. It is important to have in mind that each user has a session on our client but also on each authorization server. -If we invalidate only the session on our client, it is very likely that the next login attempt with the same browser will complete silently. For a complete logout, **both client and authorization sessions should be terminatedt**. +If we invalidate only the session on our client, it is very likely that the next login attempt with the same browser will complete silently. For a complete logout, **both client and authorization sessions should be terminated**. OIDC specifies two logout protocols: -- [RP-initiated logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) where a client asks the authorization-server to terminate a user session +- [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) where a client asks the authorization-server to terminate a user session - [back-channel logout](https://openid.net/specs/openid-connect-backchannel-1_0.html) where the authorization-server brodcasts a logout event to a list of registered clients so that each can terminate its own session for the user #### 4.4.1 RP-Initiated Logout @@ -355,18 +355,18 @@ But this is not applicable here for two reasons: If we ever had a single identity provider that would "almost" comply with RP-Initiated Logout, instead of all that we'll do here, we could have used `SpringAddonsOAuth2LogoutSuccessHandler` which is auto-configured with `SpringAddonsOAuth2ClientProperties` (refer to the respective Javadoc for more details). -Now, let's address our use case: OAuth2 client with potentially several authorized clients simultaneously. [`spring-addons-webmvc-client`](https://central.sonatype.com/artifact/com.c4-soft.springaddons/spring-addons-webmvc-client/6.1.5) provides with a configurable logout request URI builder authorization-server implementing "close to [RP-initiated logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) standard", which is the case of both [Auth0](https://auth0.com/docs/api/authentication#logout) and [Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html) that will be of great help for us in the following 3 front-channel logout endpoints we'll expose: +Now, let's address our use case: OAuth2 client with potentially several authorized clients simultaneously. [`spring-addons-webmvc-client`](https://central.sonatype.com/artifact/com.c4-soft.springaddons/spring-addons-webmvc-client/6.1.5) provides with a configurable logout request URI builder authorization-server implementing "close to [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) standard", which is the case of both [Auth0](https://auth0.com/docs/api/authentication#logout) and [Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html) that will be of great help for us in the following 3 front-channel logout endpoints we'll expose: - `/logout`, the default Spring Boot endpoint, used to invalidate our client session only (and try the silent re-login exposed above) - `/ui/logut-idp` to invalidate the session on a specific identity provider and remove the corresponding entries in session and `OAuth2AuthorizedClientService` - `/ui/bulk-logout-idps` to terminate sessions on all the identity providers the user is authorized on, as well as our client session. -As RP-Initiated logout is using redirections to the authorization server (on logout URI) and then back to the client (on post-logout URI), we'll have to ensure that all our application `/`, `/ui/greet` and `/ui/bulk-logout-idps` endpoints are declared as allowed post-logout URIs on all identity providers. +As RP-Initiated Logout is using redirections to the authorization server (on logout URI) and then back to the client (on post-logout URI), we'll have to ensure that all our application `/`, `/ui/greet` and `/ui/bulk-logout-idps` endpoints are declared as allowed post-logout URIs on all identity providers. #### 4.4.2. Back-Channel Logout Back-channel logout [is not implemented yet in spring-security](https://github.com/spring-projects/spring-security/issues/7845) (vote there if you are interested in it). ### 4.5. `WebClient` in Servlet Applications -As we use `WebClient`, which is a reactive compenent, in a servlet application, we have to tweak its auto-configuration: +As we use `WebClient`, which is a reactive component, in a servlet application, we have to tweak its auto-configuration: ```java @Configuration public class WebClientConfig { @@ -660,12 +660,12 @@ We also need a `src/main/resources/templates/greet.html` template to display the ``` ## 7. Conclusion -In this tutorial we saw how to configure different security filter-chains and select to which routes each applies. We set-up +In this tutorial we saw how to configure different security filter-chains and select to which routes each applies. We set up - an OAuth2 client filter-chain with login, logout and sessions (and CSRF protection) for UI - a state-less (neither session nor CSRF protection) filter-chain for the REST API This was a rather long journey mostly because we chose to: -- enable multi-tenancy on a Spring OAuth2 client, which is very partly implemented by spring-security: `OAuth2AuthenticationToken` which is the implementation used for OAuth2 clientsclearly wasn't designed with that usage in mind +- enable multi-tenancy on a Spring OAuth2 client, which is very partly implemented by spring-security: `OAuth2AuthenticationToken`, which is the implementation used for OAuth2 clients, clearly wasn't designed with that usage in mind - use authorization-servers which do not comply with RP-Initiated Logout specifications We also saw how handy `spring-addons-webmvc-jwt-resource-server` and `spring-addons-webmvc-client` are when it comes to configuring respectively OAuth2 resource servers and OAuth2 clients, specially in multi-tenant scenario. But, after all, a single-tenant scenario is just the simplest case of multi-tenant ones and what we did here applies almost everywhere. diff --git a/samples/tutorials/servlet-client/README.md b/samples/tutorials/servlet-client/README.md index 6794b4cd7..e73769bd0 100644 --- a/samples/tutorials/servlet-client/README.md +++ b/samples/tutorials/servlet-client/README.md @@ -2,7 +2,7 @@ In this tutorial, we'll configure a servlet (WebMVC) Spring Boot 3 application as an OAuth2 client with login, logout and authorities mapping to enable RBAC using roles defined on OIDC Providers. ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Project Initialization We start after [prerequisites](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#2-prerequisites), and consider that we have a minimum of 1 OIDC Provider configured (2 would be better) and users with and without `NICE` role declared on each OP. @@ -110,15 +110,15 @@ To have something to see once we're authenticated, let's define this `src/main/r ``` We can now run the app and browse to [http://localhost:8080](http://localhost:8080). -At first glance, things seam to be working: we can login on any of the configured OIDC Providers: -- before login, we can't access index and are redirect to login instead +At first glance, things seem to be working: we can login on any of the configured OIDC Providers: +- before login, we can't access index and are redirected to login instead - after login on any of the configured, we can access the index - after logout, we can't access the index anymore But with a little more testing, we face a first issue: if we login again on an OIDC Providers we were already identified on, then we are not prompted for our credentials (login happens silently). To solve that, we'll have to configure [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) so that a session invalidation on our client is propagated to the OP. ## 2. RP-Initiated Logout -Spring provides with a `LogoutSuccessHandler` for OIDC Providers implementing the [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html): `OidcClientInitiatedLogoutSuccessHandler`. But do override some of the security filter-chain configuration, we have to provide a full `SecurityFilterChain` bean. +Spring provides with a `LogoutSuccessHandler` for OIDC Providers implementing the [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html): `OidcClientInitiatedLogoutSuccessHandler`. But to override some of the security filter-chain configuration, we have to provide a full `SecurityFilterChain` bean. ### 2.1. Standard RP-Initiated Logout An OAuth2 client security filter-chain for an application needing to authenticate users will contain: @@ -178,7 +178,7 @@ logout: logout-uri: ${auth0-issuer}v2/logout post-logout-uri-parameter-name: returnTo ``` -Now, we can define a logout success handler parsing this configuration for non standard RP-Initiated Logout (taking "inspiration" from Spring's `OidcClientInitiatedLogoutSuccessHandler`): +Now, we can define a logout success handler parsing this configuration for non-standard RP-Initiated Logout (taking "inspiration" from Spring's `OidcClientInitiatedLogoutSuccessHandler`): ```java @RequiredArgsConstructor static class AlmostOidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { @@ -231,7 +231,7 @@ static class AlmostOidcClientInitiatedLogoutSuccessHandler extends SimpleUrlLogo } } ``` -This handler is fine for non-standard OPs, but if want to keep Spring's logout success handler for Keycloak (and avoid defining logout properties for it), we need a facade for the two implementations we now have: +This handler is fine for non-standard OPs, but if we want to keep Spring's logout success handler for Keycloak (and avoid defining logout properties for it), we need a facade for the two implementations we now have: ```java static class DelegatingOidcClientInitiatedLogoutSuccessHandler implements LogoutSuccessHandler { private final Map delegates; @@ -458,7 +458,7 @@ To demo RBAC, let's define a new `src/main/resources/static/nice.html` page whic ``` -This off course requires to update the security configuration as follow: +This off course requires to update the security configuration as follows: ```java http.authorizeHttpRequests(ex -> ex .requestMatchers("/login/**", "/oauth2/**").permitAll() @@ -545,7 +545,7 @@ static class LoginPageFilter extends GenericFilterBean { } } ``` -We can then update the security filter-chain configuration as follow: +We can then update the security filter-chain configuration as follows: ```java @Bean SecurityFilterChain @@ -567,8 +567,8 @@ SecurityFilterChain ## 5. Conclusion In this tutorial we configured a servlet OAuth2 client with login, logout and roles mapping. -But wait, what we did here is pretty verbose and we'll need it in almost any OAuth2 client we write. Do we really have to write all that again and again? Not really: this repo provides with a [`spring-addons-webfmvc-client`](https://github.com/ch4mpy/spring-addons/tree/master/webmvc/spring-addons-webmvc-client) Spring Boot starter just for that, and if for whatever reason you don't want to use that one, you can still write [your own starter](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration) to wrap the configuration we wrote here. +But wait, what we did here is pretty verbose and we'll need it in almost any OAuth2 client we write. Do we really have to write all that again and again? Not really: this repo provides with a [`spring-addons-webmvc-client`](https://github.com/ch4mpy/spring-addons/tree/master/webmvc/spring-addons-webmvc-client) Spring Boot starter just for that, and if for whatever reason you don't want to use that one, you can still write [your own starter](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration) to wrap the configuration we wrote here. Also, what if we actually need to users to have several authorized clients at the same time (for instance be authenticated on Google and Facebook at the same time to query Google API and Facebook graph from the same client)? Well, as suggested in previous section, you can provide with an alternate `OAuth2AuthorizedClientRepository`. This repo client starters propose such an implementation storing an authentication per issuer in the user session and then resolving the right one (with its subject) before trying to retrieve an authorized client. Again, if you don't want to use those starters, you can still write [your own](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration). -Last, you might have a look a integration tests in source code to see how access control rules to `/`, `/login` and `nice.html` are verified with mocked security contexts. \ No newline at end of file +Last, you might have a look into integration tests in source code to see how access control rules to `/`, `/login` and `nice.html` are verified with mocked security contexts. diff --git a/samples/tutorials/servlet-resource-server/README.md b/samples/tutorials/servlet-resource-server/README.md index 6b6cf52ae..077435ce7 100644 --- a/samples/tutorials/servlet-resource-server/README.md +++ b/samples/tutorials/servlet-resource-server/README.md @@ -4,7 +4,7 @@ In this tutorial, we'll configure a servlet (WebMVC) Spring Boot 3 application a We'll also see how to accept access tokens issued by several, potentially heterogeneous, OIDC Providers (or Keycloak realms). ## 0. Disclaimer -There are quite a few samples, and all are part of CI to ensure that source compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. +There are quite a few samples, and all are part of CI to ensure that sources compile and all tests pass. Unfortunately, this README is not automatically updated when source changes. Please use it as a guidance to understand the source. **If you copy some code, be sure to do it from the source, not from this README**. ## 1. Project Initialization We start after [prerequisites](https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials#2-prerequisites), and consider that we have a minimum of 1 OIDC Provider configured (2 would be better) and users with and without `NICE` role declared on each OP. @@ -38,7 +38,7 @@ This is how we want our REST API to be configured: - state-less session management (no session, user state in access token only) - disabled CSRF (safe because there is no session) - public access to a limited list of resources -- non "public" routes require users to be authenticated, fine grained access-control being achieved with method-security (`@PreAuthrorize` and alike) +- non "public" routes require users to be authenticated, fine-grained access-control being achieved with method-security (`@PreAuthrorize` and alike) - 401 (unauthorized) instead 302 (redirecting to login) when a request to a protected resource is made with missing or invalid authorization ## 3.1. Security Properties @@ -186,7 +186,7 @@ To ease roles claims parsing, we'll use [json-path](https://central.sonatype.com ``` #### 3.3.2. Application Properties -Then, we need some additional configuration properties to provide with the flexibility to change, for each issuer the claims containing the user name and roles +Then, we need some additional configuration properties to provide with the flexibility to change, for each issuer the claims containing the username and roles ```java @Data @Configuration @@ -313,7 +313,7 @@ static class SpringAddonsJwtAuthenticationConverter implements Converter