JHipster - How to add route to external microservices in application.yml - microservices

I'm using Jhipster 5.5.0 to build a zuul gateway capable to route rest request to different microservices.
Some of this microservices are developed in different languages, deployed and running on different server. Every microservices is protected via OIDC using the same keycloak server, under different realms.
Now I need to configure zuul route on application.yml properties file of my gateway app, to access this service by external rest client (customers) and using zuul for filtering request and keycloak as oidc token provider.
Then I modify gateway application.yml adding the following zuul route to a sample external service (this type of configuration work well with another zuul gateway developed for another project without using jhipster):
# zuul routing:
zuul:
ignored-services: "*"
routes:
# external endpoints
myapi-v2-test:
path: /my-api/mypackage/v2/add
sensitiveHeaders: Cookie, Set-Cookie
url: http://192.168.3.148:8080/server/rest/api/mypackage_2.0.0/add
When I try to test the call using a soap-ui client with Auth Bearer token in header, provided by the keycloak server using the jhipster realm (and client_id "web_app"), I always receive the response error code 403 - Forbidden for path
"/my-api/mypackage/v2/add".
What is the right way to configure the application.yml of the gateway app?
Thank in advance for any help.
I'm not using registry service (e.g Spring Cloud Eureka or Jhipster Registry).

I post my solution in case someone have the same question. To solve my problem I added in OAuth2SsoConfiguration.java this line of code in configure(WebSecurity web) method:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.
.antMatchers("/my-api/**")
.
}
and the following in configure(HttpSecurity http):
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.
.
.and()
.
.antMatchers("/my-api/**").permitAll()
.
.
}

Related

Handling authentication of microservice at Gateway service in Spring boot

I am learning authentication at gateway service in a microservices architecture. What i understood is
When the client makes a request, it needs to have a valid access token
The authentication of the requests is happening at the gateway level, the authorization at the microservice application level
Request is processed if authentication is success (Jwt token is valid)
My Questions are :
Is it really needed to have authentication at gateway service as well as individual microservice ? Because its redundant to have the same logic at both places (JWT Validation)
If not (only at gateway service), how can the individual microservice can be protected if the call is not via gateway ?
Assuming that the Microservices are accessed only via the gateway, the authentication can be delegated to the Gateway that then send the informations relative to the caller to the recipient microservice(via an header for instance).
It is important to restrict the access to the microservices to the Gateway only.
This can be done at network level if there is a firewall or a router in between or via code configuring the microservice with soething like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/foos/**").hasIpAddress("11.11.11.11")
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.csrf().disable();
}
// ...
}
This is the whitelisting part. Then you need to verify how to pass the information of the logged in user to the microservices from the Gateway. If you need more infow about the white listing check this article: https://www.baeldung.com/spring-security-whitelist-ip-range

Spring Boot Security and Keycloak - receive 403 forbidden /sso/login after successfull login when using HTTPS

I have a Spring Boot App using Spring Security and Keycloak as IDP.
Keycloak is available under https://auth.example.com, having a realm backo with a client backo-core and a testuser configured with the required roles.
If I configure my local app, using
keycloak.enabled=true
keycloak.auth-server-url=https://auth.example.com/auth
keycloak.realm=backo
keycloak.public-client=true
keycloak.resource=backo-core
keycloak.ssl-required=external
keycloak.confidential-port=443
Everything works fine.
If I deploy it to my DEV environment under https://backo.example.com/backo with https://backo.example.com/sso/login, when accessing the app I get redirect to the Keycloak login. After successful login I get redirected to the redirect URL with the state, session-state and code parameters but receive 403.
https://backo.example.com/sso/login?state=...&session_state=...&code=...
with request initiator chain coming from https://auth.example.com/auth/realms/backo/login-action/authenticate?...
If I set locally keycloak.ssl-required=all, the redirect_url parameter when accessing the login page is https://localhost/sso/login, so I can change it manually to http://localhost:8080/sso/login. After a successful login I have the exact same problem with a 403 Forbidden response for
http://localhost:8080/sso/login?state=...&session_state=...&code=...
with request initiator chain coming from https://auth.example.com/auth/realms/backo/login-action/authenticate?...
This is how my security config looks like
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/backo").hasAnyRole(ROLE_ADMIN, ROLE_BACKOFFICE)
.anyRequest().permitAll();
http.csrf().disable();
http.headers().frameOptions().disable(); // otherwise Vaadin doesn't work properly
http
.logout()
.addLogoutHandler(keycloakLogoutHandler())
.logoutUrl("/sso/logout").permitAll()
.logoutSuccessUrl("/");
}
You can ignore this Vaadin workaround, as it fails in /sso/login already.
http.csrf().disable(); is required to prevent other 403 Forbidden errors on post request while authorization.
One thing that could be worth mentioning:
The Spring Boot App has no HTTPS enabled, in our dev environment it sits behind an AWS Application loadbalancer ALB. HTTPS is terminated in the ALB.
We have faced the similar problem three days ago with spring boot thymeleaf application. We have used keycloak adapter (13.0.1) for spring boot.
After successful login it was redirecting to /sso/login page with 403 error.
After lots of effort we finally got the configuration required to fix this issue. you need to use the below application properties :
server.use-forward-headers=true
keycloak.public-client=true
keycloak.ssl-required=all
keycloak.confidential-port=443

Passing auth header to permitAll path throws 401

I have an API configured with Spring Security's permitAll():
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api").permitAll()
.and().httpBasic();
}
}
While this works, I noticed if you include an Authorization Basic header, Spring Security will still try to process and validate the auth header.
I'm using AWS API gateway for authorization. AWS will then forward the request to my application. The thing is, AWS API gateway forwards the auth header to the app.
What's the best way to solve this, do I remove the header before AWS sends the request to the app? or I configure Spring Security to disregard the auth header if an API is public?

Spring boot admin: Full authentication is required to access this resource

we are using netflix oss for reverse proxying and security of microservices, we are following the jhipster pattern mentioned here https://www.jhipster.tech/microservices-architecture/, where request from UI application goes to gateway which is Api Gateway and it proxies the request to our backend microservices , we are using jwt for authentication, we wanted a dashboard to monitor our microservices and api gateway which registers with eureka server , we started a separate spring boot admin server so that it registers with eureka server and poll microservices and gateway for metrics endpoint but we are getting exception
Full authentication is required to access this resource
which is thrown by filters which are filtering for jwts at both api gateway and microservices level,
we also tried disabled
management.security.enabled: false
but still no luck ,can some one please help to guide what changes i need to make to enable spring boot admin to successfully poll the microservices and api gateway?
I tried the following approach
firstly i enabled web.ignoring().antMatchers("/actuator/**"), so that actuator endpoints are ignored by spring security but this approach will risk my api's
Second idea:
if i enable 2 filters in spring security , the first filter would be for spring boot admin with basic authentication for actuator endpoints and second filter will be of my jwt authentication for rest all api's and downstream api's not sure will it be feasible?
i enabled the 2 filters one filter for actuator end points and 1 filter for api's but these filters are working perfectly but not able to connect to SBA
public class SpringSecurityAdminFilter extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
String password = passwordEncoder().encode("xxxx");
auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).withUser("sam").password(password).roles("ADMIN");
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/actuator/**").hasRole("ADMIN")
.and().httpBasic()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created.
}
}
i enabled basic authentication for spring boot admin server added the property in microservices
eureka.instance.metadata-map.user.name:
eureka.instance.metadata-map.user.password:
now actuator endpoints are protected by basic authentication
I have had a similar issue. On my spring boot application we had a cors filter to block Http Head requests. So head requests cannot be accepted from spring boot admin.
Check maybe filter is blocking HEAD Http requests .
Setting management.security.enabled=false in the application.properties also necessary.

Spring Security Oauth2 SSO with Zuul Proxy

I'm modifying the oauth2-vanilla sample from Springs excellent security tutorials. The oauth2-vanilla combines the Zuul Proxy and the UI into a single application. I would like to seperate the Zuul Proxy and the UI. (The Zuul Proxy should act as an API gateway and as a reverse proxy for several UIs).
When accessing the UI via the zuul proxy, it should be able to do SSO based on Oauth2 between the UI and the resource backend.
The oauth2-vanilla looks like this
Where I want to move to something like this :
I've removed the UI part from the gateway, and added a zuul route for the ui
zuul:
routes:
resource:
url: http://localhost:9000
user:
url: http://localhost:9999/uaa/user
ui:
url: http://localhost:8080
I created a new UI webapp containing the UI (Angular stuff) with an #EnableOAuth2Sso annotation.
So I'm accessing the UI via http://localhost:8888 (through the zuul proxy).
After authenticating and doing through the UI flow, I can access the /user endpoint that returns me the user. (During debugging, I see that when I access the /user endpoint that I have an HTTP Session with an OAuth2Authentication.
When I access the /resource endpoint however, the HttpSessionSecurityContextRepository cannot find a session and is unable to build a context with the OAuth2Authentication.
I've created a git repository with the modified sample.
I'm guessing there is something wrong with the gateway configuration.
I've tried changing cookie paths, changing HttpSecurity rules in the proxy but I cannot get it to work.
What I don't understand is why the UI, when accessed through the proxy is able to resolve the /user endpoint fine (with an HTTP session and a OAuth2Authentication), but it is unable to access the /resource endpoint.
Also, as the UI is now running in the /ui context, it seems that I need to have the following code in the gateway for it to load up the angular css / js files.
.antMatchers("/ui/index.html", "/ui/home.html", "ui/css/**", "/ui/js/**").permitAll().anyRequest().authenticated();
It also doesn't seem right that I need to prefix it with the zuul ui route.
Any help would be appreciated.
I was never able to get the #EnableOauthSso to work. Instead, I annotated as an #EnableResourceServer and created a security config for Zuul.
#Configuration
#EnableResourceServer
public class JwtSecurityConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
.antMatchers("/**").hasAuthority("ROLE_API")
.and()
.csrf().disable();
}
}

Resources