Reputation: 447
I'm creating a MicroServices-based project. I'm using Angular 15
for Frontend and Spring 3.0.2
for Backend. I'm using Keycloack 20.0.3
for authentication for both frontend & backend. I have multiple micro-services running on different spring projects. I'm using a Spring Cloud Gateway
as an entry point for my front-end so I don't need to manage ports with angular. I'm also using Eureka
for my gateway.
Note: My gateway is configured with YAML file only. It is NOT configured with neither
Spring Security
norKeycloak
. CORS are disabled.
spring:
application:
name: gateway
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "https://localhost:4200"
allowedMethods: "*"
allowedHeaders: "*"
routes:
- id: users
uri: lb://micro-service-1/api/users
predicates:
- Method=GET,POST,PUT,DELETE
- Path=/api/users/**
- id: assets
uri: lb://micro-service-2/api/assets
predicates:
- Method=GET,POST,PUT,DELETE
- Path=/api/assets/**
server:
port: 8100
eureka:
client:
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
I'm building a BREAD api (Browse, Read, Edit, Add, Delete). Browse & Read (Http GET requests in general) Works fine but the rest throws 403 Error in Angular
.
Note: I tried using Postman for testing and somehow NO Error is thrown
When I tried to skip the gateway and directly communicate with the micro-service every everything works fine, NO Error is thrown
Note: My Backend is RESTful APIs Only, Keycloak Auth handles all login/logout/register...
My gateway is NOT configured with neither Spring Security
nor Keycloak
. CORS are disabled.
security.enable-csrf: false
It didn't work!
Spring Security
& Disabling CSRF on gateway<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable().cors().disable().httpBasic().disable()
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
Cridentials still required & Conflict with Keycloak
Keycloak
for gatewayKeycloak required Spring Web
resulted in Conflict with Spring Cloud Gateway
I Spent 2 weeks, Can't find any thing on the internet. Everything is either depricated or simply doesn't work. any clue?
Note: I know I can use angular Proxy Config to replace the gateway but this breaks the Spring cloud architecture, and is only a work-around for dev purposes
Upvotes: 4
Views: 4442
Reputation: 12835
I won't answer to your current problem, but try to give you elements for the next steps: I guess that in the end, you want your app to be secured (implement some sort of user based access-control) and as you mention Keycloak it's going to involve OpenID.
Keycloak adapters for spring were deprecated in early 2022 and are not compatible with Spring Boot 3. Do not use it, even in servlet applications (and , as you already figured out, spring-cloud-gateway
is a reactive application, so this are two good reasons for not using it).
Are you aware that storing OAuth2 tokens in public-clients (browser applications not solely Angular, but also React, Vue, etc.) is now discouraged? The fact is that if you inspect any major web service (Gmail, Facebook, Github, etc.) you won't find any OAuth2 access-token but just a regular session (implemented with Secured Http-Only cookies).
Have you heard of the BFF (backend for frontend) pattern? To help you make your own idea, I quite liked this article from the author of my prefered OpenID client lib for Angular (which isn't of any use when you implement BFF).
If you intend to configure your gateway as BFF, you need spring-boot-starter-oauth2-client
, not spring-boot-starter-security
. I wrote a tutorial for that on Baeldung
Upvotes: 2
Reputation: 447
After some playing around with different configurations I ended up with this one working.
spring:
application:
name: gateway
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
routes:
- id: users
uri: lb://micro-service-1
predicates:
- Path=/api/users/**
filters:
- RewritePath=/api/users/(?<segment>.*),/api/users/$\{segment}
- id: assets
uri: lb://micro-service-2
predicates:
- Path=/api/assets/**
filters:
- RewritePath=/api/assets/(?<segment>.*),/storage/$\{segment}
server:
port: 8100
eureka:
client:
registerWithEureka: true
serviceUrl:
defaultZone: http://localhost:8761/eureka
CHANGES: in
uri
I set the base uri only, removed methods from routes and added RewritePath filters
Gateway Projet have no authentication nor security library included in POM. Only Spring Cloud
In each individual micro-service I added the following SecurityConfig
class
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
Upvotes: 1