Skip to content

Commit

Permalink
BFF gateway with resource server filter-chain
Browse files Browse the repository at this point in the history
  • Loading branch information
ch4mpy committed Jul 11, 2023
1 parent dbbbd73 commit 2725f35
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 133 deletions.
208 changes: 120 additions & 88 deletions README.MD

Large diffs are not rendered by default.

46 changes: 30 additions & 16 deletions samples/tutorials/bff/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Next, comes the Gateway configuration itself with:
* `/bff/greetings-api/v1/**` is forwarding requests to our resource server (`greetings` REST API) according to the BFF pattern (for front-ends secured with sessions):
- `TokenRelay` filter is applied to replace session cookies with OAuth2 access tokens
- `StripPrefix` filter removes the first 3 segments of request path (`/bff/greetings-api/v1/greeting/**` will be routed to greetings-api as `/greeting/**`)
* `/greetings-api/v1/**` is forwarding requests to our resource server (`greetings` REST API) for OAuth2 clients (requests should be authorized with an OAuth2 access token already, so no `TokenRelay filter`)
* `/resource-server/greetings-api/v1/**` is forwarding requests to our resource server (`greetings` REST API) for OAuth2 clients (requests should be authorized with an OAuth2 access token already, so no `TokenRelay filter`)
* `ui` is forwarding to the Angular app (angular dev server with current localhost conf)
* `letsencrypt` is needed only when deploying to Kubernetes to route HTTP-01 challenge request when requesting a valid SSL certificate
```yaml
Expand Down Expand Up @@ -178,9 +178,9 @@ Next, comes the Gateway configuration itself with:
- id: greetings-api-oauth2-clients
uri: ${greetings-api-uri}
predicates:
- Path=/greetings-api/v1/**
- Path=/resource-server/greetings-api/v1/**
filters:
- StripPrefix=2
- StripPrefix=3
# access to UI resources (Angular app in our case)
- id: ui
uri: ${ui-uri}
Expand All @@ -195,8 +195,11 @@ Next, comes the Gateway configuration itself with:

Then comes `spring-addons-starter-oidc` configuration:
- `ops` properties for each of the OIDC Providers we trust (issuer URI, authorities mapping and claim to use as username)
- two security filter chains:
* a "client" one for resources secured with a session. It contains a security matcher to define which requests it should process, as well as configuration for login and logout
* a "resource server" with lowest precedence which will process all requests not intercepted by the client filter-chain.
- `client-uri` is used to work with absolute URIs in login process
- `security-matchers` is an array of path matchers for routes processed by the auto-configured client security filter-chain. If null auto-configuration is turned off. Here, it will filter all traffic.
- `security-matchers` is an array of path matchers for routes processed by the auto-configured client security filter-chain. If it was left null or empty, client auto-configuration would be turned off.
- `permit-all` is a list of path matchers for resources accessible to all requests, even unauthorized ones (end-points not listed here like `/logout` will be accessible only to authenticated users)
* `/login/**` and `/oauth2/**` are used by Spring during the authorizatoin-code flow
* `/` and `/ui/**` are there so that unauthorized users can display the Angular app containing a landing page and login buttons
Expand Down Expand Up @@ -228,23 +231,25 @@ com:
authorities:
- path: $['https://c4-soft.com/user']['roles']
- path: $.permissions
# OAuth2 client specific configuration: mostly login, logout and CSRF protection
# Configuration for an OAuth2 client security filter-chain: mostly login, logout and CSRF protection
client:
client-uri: ${gateway-uri}
# For the sake of simplicity, all requests will be processed by the client filterchain
# A resource optimisation could be excluding actuator, swagger and cert-manager endpoints to save the creation of useless sessions
security-matchers: /**
# Intercept only requests which need a session
# Other requests will go through the resource server filter-chain (which has lowest precedence and no security matcher)
security-matchers:
- /login/**
- /oauth2/**
- /
- /login-options
- /logout
- /me
- /bff/**
permit-all:
- /login/**
- /oauth2/**
- /
- /login-options
- "/me"
- /ui/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
- /.well-known/acme-challenge/**
- /me
# The Angular app needs access to the CSRF cookie (to return its value as X-XSRF-TOKEN header)
csrf: cookie-accessible-from-js
login-path: /ui/
Expand All @@ -254,11 +259,11 @@ com:
back-channel-logout-enabled: true
# Auth0 and Cognito do not follow strictly the OpenID RP-Initiated Logout spec and need specific configuration
oauth2-logout:
cognito:
cognito-confidential-user:
uri: https://spring-addons.auth.us-west-2.amazoncognito.com/logout
client-id-request-param: client_id
post-logout-uri-request-param: logout_uri
auth0:
auth0-confidential-user:
uri: ${auth0-issuer}v2/logout
client-id-request-param: client_id
post-logout-uri-request-param: returnTo
Expand All @@ -267,6 +272,15 @@ com:
auth0-confidential-user:
- name: audience
value: demo.c4-soft.com
# Configuration for a resource server security filterchain
resourceserver:
permit-all:
- /resource-server/**
- /ui/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
- /.well-known/acme-challenge/**
```
After that, we have Boot configuration for actuator and logs
```yaml
Expand Down
35 changes: 23 additions & 12 deletions samples/tutorials/bff/gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ spring:
- id: greetings-api-oauth2-clients
uri: ${greetings-api-uri}
predicates:
- Path=/greetings-api/v1/**
- Path=/resource-server/greetings-api/v1/**
filters:
- StripPrefix=2
- StripPrefix=3
# access to UI resources (Angular app in our case)
- id: ui
uri: ${ui-uri}
Expand Down Expand Up @@ -122,23 +122,25 @@ com:
authorities:
- path: $['https://c4-soft.com/user']['roles']
- path: $.permissions
# OAuth2 client specific configuration: mostly login, logout and CSRF protection
# Configuration for an OAuth2 client security filter-chain: mostly login, logout and CSRF protection
client:
client-uri: ${gateway-uri}
# For the sake of simplicity, all requests will be processed by the client filterchain
# A resource optimisation could be excluding actuator, swagger and cert-manager endpoints to save the creation of useless sessions
security-matchers: /**
# Intercept only requests which need a session
# Other requests will go through the resource server filter-chain (which has lowest precedence and no security matcher)
security-matchers:
- /login/**
- /oauth2/**
- /
- /login-options
- /logout
- /me
- /bff/**
permit-all:
- /login/**
- /oauth2/**
- /
- /login-options
- "/me"
- /ui/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
- /.well-known/acme-challenge/**
- /me
# The Angular app needs access to the CSRF cookie (to return its value as X-XSRF-TOKEN header)
csrf: cookie-accessible-from-js
login-path: /ui/
Expand All @@ -161,6 +163,15 @@ com:
auth0-confidential-user:
- name: audience
value: demo.c4-soft.com
# Configuration for a resource server security filterchain
resourceserver:
permit-all:
- /resource-server/**
- /ui/**
- /v3/api-docs/**
- /actuator/health/readiness
- /actuator/health/liveness
- /.well-known/acme-challenge/**

management:
endpoint:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

import java.util.ArrayList;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.ReactiveAuthenticationManagerResolver;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
Expand All @@ -23,8 +24,11 @@
import com.c4_soft.springaddons.security.oauth2.test.AuthenticationFactoriesTestConf;
import com.c4_soft.springaddons.security.oauth2.test.webmvc.AddonsWebmvcTestConf;
import com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.configuration.IsNotServlet;
import com.c4_soft.springaddons.security.oidc.starter.properties.condition.configuration.IsOidcResourceServerCondition;

@TestConfiguration
@Conditional({ IsOidcResourceServerCondition.class, IsNotServlet.class })
@AutoConfiguration
@ImportAutoConfiguration(classes = { WebTestClientProperties.class, AuthenticationFactoriesTestConf.class }, exclude = { AddonsWebmvcTestConf.class })
public class AddonsWebfluxTestConf {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,2 @@
com.c4_soft.springaddons.security.oidc.starter.properties.SpringAddonsOidcProperties

com.c4_soft.springaddons.security.oidc.starter.reactive.ReactiveSpringAddonsOidcBeans
com.c4_soft.springaddons.security.oidc.starter.reactive.client.ReactiveSpringAddonsBackChannelLogoutBeans
com.c4_soft.springaddons.security.oidc.starter.reactive.client.ReactiveSpringAddonsOidcClientBeans
com.c4_soft.springaddons.security.oidc.starter.reactive.resourceserver.ReactiveSpringAddonsOidcResourceServerBeans

com.c4_soft.springaddons.security.oidc.starter.synchronised.SpringAddonsOidcBeans
com.c4_soft.springaddons.security.oidc.starter.synchronised.client.SpringAddonsBackChannelLogoutBeans
com.c4_soft.springaddons.security.oidc.starter.synchronised.client.SpringAddonsOidcClientBeans
com.c4_soft.springaddons.security.oidc.starter.synchronised.resourceserver.SpringAddonsOidcResourceServerBeans
com.c4_soft.springaddons.security.oauth2.test.webmvc.AddonsWebmvcTestConf
com.c4_soft.springaddons.security.oauth2.test.webflux.AddonsWebfluxTestConf
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.web.util.UriComponentsBuilder;
Expand Down Expand Up @@ -41,8 +39,10 @@ public class SpringAddonsOidcClientProperties {
private String postLogoutRedirectPath;

/**
* Map of logout properties indexed by client registration ID (must match a registration in Spring Boot OAuth2 client configuration). {@link OAuth2LogoutProperties} are configuration for authorization server not strictly following the <a href= "https://openid.net/specs/openid-connect-rpinitiated-1_0.html">RP-Initiated Logout</a>
* standard, but exposing a logout end-point expecting an authorized GET request with following request params:
* Map of logout properties indexed by client registration ID (must match a registration in Spring Boot OAuth2 client configuration).
* {@link OAuth2LogoutProperties} are configuration for authorization server not strictly following the
* <a href= "https://openid.net/specs/openid-connect-rpinitiated-1_0.html">RP-Initiated Logout</a> standard, but exposing a logout end-point expecting an
* authorized GET request with following request params:
* <ul>
* <li>"client-id" (required)</li>
* <li>post-logout redirect URI (optional)</li>
Expand Down

0 comments on commit 2725f35

Please sign in to comment.