Skip to content

Commit

Permalink
Single spring-addons starter
Browse files Browse the repository at this point in the history
  • Loading branch information
ch4mpy committed Jul 10, 2023
1 parent ee40e16 commit da37b7a
Show file tree
Hide file tree
Showing 333 changed files with 3,744 additions and 6,438 deletions.
47 changes: 47 additions & 0 deletions 7.0.0-migration-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Migration Guide from 6.x to 7.0.0

## Dependencies
- replace any spring-addons starter with `com.c4-soft.springaddons:spring-addons-starter-oidc`
- replace any spring-addons test starter with `com.c4-soft.springaddons:spring-addons-starter-oidc-test`
- depending or your needs, add a dependency to
* `org.springframework.boot:spring-boot-starter-oauth2-resource-server` for a REST API secured with access tokens
* `org.springframework.boot:spring-boot-starter-oauth2-client` when configuring `spring-cloud-gateway` as BFF or exposing server-side rendered templates with frameworks like Thymeleaf
* both of above when exposing publicly both a REST API secured with access tokens and other resources secured with sessions

## Java Sources

### Main Code
- rename `SpringAddonsSecurityProperties` to `SpringAddonsOidcProperties`. Also, if using nested properties, rename
* `getIssuers()` to `getOps()`
* `getLocation()` to `getIss()`
- replace `SpringAddonsOAuth2ClientProperties` with `SpringAddonsOidcProperties::getClient` (only `SpringAddonsOidcProperties` can be autowired)
- organize imports

### Tests
- replace `@AutoConfigureAddonsSecurity` with `@AutoConfigureAddonsMinimalSecurity`
- replace `@AutoConfigureAddonsWebSecurity` with one of:
* `@AutoConfigureAddonsWebmvcSecurity`
* `@AutoConfigureAddonsWefluxSecurity`

## Application Properties
This is probably the most tedious part of the migration. Hopefully, your IDE auto-completion and syntax highliting should help you there.

### Common Configuration
- rename `com.c4-soft.springaddons.security` to `com.c4-soft.springaddons.oidc`
- rename `issuers` to `ops` which stands for OpenID Providers (`com.c4-soft.springaddons.security.issuers` becomes `com.c4-soft.springaddons.oidc.ops`)
- rename OpenID Providers `location` to `iss`: if set, the is used to add an "issuer" (tokens `iss` claim) validator to JWT decoder (`com.c4-soft.springaddons.security.issuers[].location` becomes `com.c4-soft.springaddons.oidc.ops[].iss`)
- rename`audience` to `aud`: if set, the is used to add an "audience" (tokens `aud` claim) validator to JWT decoder (`com.c4-soft.springaddons.security.issuers[].aud` becomes `com.c4-soft.springaddons.oidc.ops[].aud`)

CORS configuration has also improved for both clients and resource servers: `allowed-origin-patterns` is used instead of `allowed-origins`. This is a requirement for using `allow-credentials` and is also more flexible: you can define ant patterns like `https://*.my-domain.pf`.
- rename `allowed-origins` to `allowed-origin-patterns`
- add `allow-credentials` and `max-age` if it makes sens (this are added configuration options)

### Resource Servers
Resource server `Security(Web)FilterChain` can now be completely disabled with `com.c4-soft.springaddons.security.resourceserver.enabled=false`

Resource server specific properties are grouped in a new `resourceserver` subset:
- move `cors` down 1 level into `resourceserver` (`com.c4-soft.springaddons.security.cors` becomes `com.c4-soft.springaddons.security.resourceserver.cors`)
- move `permit-all` down one level to `resourceserver` (`com.c4-soft.springaddons.security.permit-all` becomes `com.c4-soft.springaddons.security.resourceserver.permit-all`)

### Clients
- rename `allowed-origins` to `allowed-origin-patterns` (`com.c4-soft.springaddons.security.client.cors.allowed-origins` becomes `com.c4-soft.springaddons.security.client.cors.allowed-origin-patterns`)
284 changes: 254 additions & 30 deletions README.MD

Large diffs are not rendered by default.

93 changes: 9 additions & 84 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<connection>scm:git:git://github.com/ch4mpy/spring-addons.git</connection>
<developerConnection>scm:git:[email protected]:ch4mpy/spring-addons.git</developerConnection>
<url>https://github.com/ch4mpy/spring-addons</url>
<tag>spring-addons-6.1.14</tag>
<tag>HEAD</tag>
</scm>

<distributionManagement>
Expand Down Expand Up @@ -101,88 +101,15 @@
<artifactId>spring-addons-oauth2-test</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-web-test</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-introspecting-resource-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-client</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-introspecting-resource-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-jwt-resource-server</artifactId>
<artifactId>spring-addons-starter-oidc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-introspecting-test</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-jwt-test</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-test</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-test</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-introspecting-test</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webflux-jwt-test</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-keycloak</artifactId>
<artifactId>spring-addons-starter-oidc-test</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
Expand Down Expand Up @@ -392,12 +319,11 @@
<profile>
<id>release</id>
<modules>
<module>starters</module>
<module>spring-addons-oauth2</module>
<module>spring-addons-web-test</module>
<module>spring-addons-oauth2-test</module>
<module>webmvc</module>
<module>webflux</module>
<module>spring-addons-starter-oidc</module>
<module>spring-addons-starter-oidc-test</module>
<module>starters</module>
</modules>
<build>
<plugins>
Expand Down Expand Up @@ -432,12 +358,11 @@
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>starters</module>
<module>spring-addons-oauth2</module>
<module>spring-addons-web-test</module>
<module>spring-addons-oauth2-test</module>
<module>webmvc</module>
<module>webflux</module>
<module>spring-addons-starter-oidc</module>
<module>spring-addons-starter-oidc-test</module>
<module>starters</module>
<module>samples</module>
</modules>
</profile>
Expand Down
4 changes: 2 additions & 2 deletions samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@

<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<artifactId>spring-addons-starter-oidc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand All @@ -97,7 +97,7 @@
</dependency>
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<artifactId>spring-addons-webmvc-test</artifactId>
<artifactId>spring-addons-starter-oidc-test</artifactId>
<version>${project.version}</version>
</dependency>

Expand Down
16 changes: 9 additions & 7 deletions samples/tutorials/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Jump to:


## 1. <a name="oauth_essentials"/>OAuth2 essentials
OAuth2 client and resource-server configuration are quite 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.
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.

### 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)
Expand All @@ -21,17 +21,19 @@ OAuth2 client and resource-server configuration are quite different. **Spring pr
- **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.

### 1.2. Client VS Resource Server Configuration
As already wrote, the responsibilities and security requirements are quite different for the two. Lets explore that in more details.
As already wrote, the responsibilities and security requirements are quite different. Lets 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 quite a few valuable benefits for scalabilty 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!
**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 quite a few 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!

**Clients consumed by browsers are secured with session cookies, not access tokens**. This exposes it to CSRF and BREACH attacks, and we'll have to configure specific mitigations for that. Also, as soon as scalability and fault tolerance are a concern, we'll have to pull the session out of the client instances.

#### 1.2.2. Requests Authorization
Resource servers expect requests to protected resources to be authorized: have an `Authorization` header containing a `Bearer` access token. It's responsibilities are to check the validity of this token (issuer, audience, expiration time, etc.) and then decide if it should grant the requested resource based on the token claims (inside the token or introspected from it).
Resource servers expect requests to be authorized with an `Authorization` header containing a `Bearer` access token.

Clients are responsible for authorizing their requests: set the `Authorization` header of the requests it send to resource server. Clients have the choice of different OAuth2 flows to get tokens from the authorization server (see next section for details).
Clients are responsible for authorizing their requests to resource servers: set the `Authorization` header of the requests it send to resource server. Clients have the choice of different OAuth2 flows to get tokens from the authorization server (see next section for details).

Resource servers don't care how access tokens were obtained. Its responsibilities are limited to check the validity of this token (issuer, audience, expiration time, etc.) and then decide if it should grant the requested resource based on the token claims (inside the token or introspected from it).

User login is part of OAuth2 `authorization-code` flow. As a consequence, **OAuth2 login (and logout) only make sense on OAuth2 clients configured with `authorization-code` flow**.

Expand All @@ -44,9 +46,9 @@ To send requests to a secured resource server, you'll have to use a client capab
#### 1.2.3. Should I use `spring-boot-starter-oauth2-client` or `spring-boot-starter-oauth2-resource-server`?
If the application is a REST API it's a resource server. Configuring it as a client just to enable OAuth2 login and query its REST endpoints with a browser is a mistake: It breaks its "stateless" nature and would work only for GET endpoints. Use `spring-boot-starter-oauth2-resource-server`, do not configure OAuth2 login and require clients to authorize their requests (use Postman or alike for your tests).

Use `spring-boot-starter-oauth2-client` only if the application serves UI templates or is used as BFF. In that case only, will login & logout be configured in Spring application (otherwize, it's managed by Postman or whatever is the OAuth2 client).
Use `spring-boot-starter-oauth2-client` if the application serves UI templates or is used as BFF. In that case only, will login & logout be configured in Spring application (otherwise, it's managed by Postman or whatever is the OAuth2 client).

What if the application matches both cases above (for instance exposes publicly both a REST API and a Thymeleaf UI to manipulate it)? As seen earlier, the configuration requirements are too different to stand in the same security filter-chain, but **it is possible to define more than one filter-chain if the first(s) in `@Order` are defined with `securityMatcher` to define to which request it apply**: the path (or any other request attribute like headers) is checked against each security filter-chain "matchers" in order and the first match defines which `SecurityFilterChain` bean will be applied to the request.
What if the application matches both cases above (for instance exposes publicly both a REST API and a Thymeleaf UI to manipulate it)? As seen earlier, the configuration requirements are too different to stand in the same security filter-chain, but **it is possible to define more than one filter-chain if the first(s) in `@Order` are defined with `securityMatcher` to define to which requests it apply**: the path (or any other request attribute like headers) is checked against each security filter-chain "matchers" in order and the first match defines which `SecurityFilterChain` bean will be applied to the request.

### 1.3. Flows
There are quite a few but 3 are of interest for us: authorization-code, client-credentials and refresh-token.
Expand Down
Loading

0 comments on commit da37b7a

Please sign in to comment.