Passing auth header to permitAll path throws 401 - spring

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?

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

hasAuthority() with Okta bearer token for Spring Cloud Gateway

I am having multiple downstream services to which I am routing via a spring cloud gateway service which also has okta auth. Currently I am able to route authenticate users at the gateway and return 401 for all requests without a valid bearer token. However when I try to implement role based auth, i.e. GET requests can be sent downstream for everyone group, but POST requests require 'admin' group membership in okta. This does not work as any authenticated user is currently able to make post requests. I have added claims to the access/id tokens and checked them in the Token preview section of my default Authorisation server in okta. Following is my security configuration.
#EnableWebSecurity
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests -> authorizeRequests
.antMatchers(HttpMethod.POST,"/*").hasAuthority("admin")
.anyRequest().authenticated())
.oauth2ResourceServer().jwt();
}
}
Due to only the gateway having okta auth and downstream services being protected by api token, I cannot implement preAuthorize and have to rely on httpsecurity, but I seem to be missing something

Keycloak Springboot bearer only for specific endpoint and non bearer for another

I am trying to use keycloak springboot adapter. I want to make some endpoints with "/api" work with bearer only to true.
But I also want the endpoint "/login" to not be a bearer only endpoint and redirect the user to the keycloak OIDC login page if he is not authenticated.
How can I achieve that ?
All I have now is just bearer only for every endpoints in my application properties.
Thanks in advance for your answers :)
In web-security conf,
enable anonymous
in http-security ant-matchers, add an entry for your public routes with permitAll()
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.anonymous();
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
return http.build();
}
PS
Keycloak spring adapters are deprecated
As an alternative, you can use:
spring-addons-webmvc-jwt-resource-server tutorial here
spring-boot-starter-oauth2-resource-server tutorial there (it requires more Java conf)

Handling token response in spring oauth2 client

I am using Spring Cloud Gateway as a API Gateway for our system. We would like to delegate all authentication (oauth) to that component. I was looking at the source code of Spring Oauth2 Client but I don't see any place where I can "plug in" to do what I need.
I would like to catch the moment, when the code exchange is successful and make a redirect with id_token and refresh_token in cookie or query param. We don't store any session as well - whole authentication is meant to stateless.
I am configuring SecurityWebFilterChain (security for WebFlux) like this:
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(Customizer.withDefaults())
.oauth2Login();
http.csrf().disable();
return http.build();
}
I tried to use successHandler
.oauth2Login(c -> c.authenticationSuccessHandler(successHandler));, but in that moment I don't access to refresh_token (have only WebFilterExchange, Authentication in arguments) and I am not even sure how should I perform the redirect form that place.
Is there any way to achieve this?

Angular ts (front-end) + spring boot (back-end) OAuth2 flow

I want to implement authorization via Google and Microsoft in my full stack app (Angular 6 for front-end, Spring boot for back-end) and I've got a problem.
I follow this scheme which describes how the flow should be implemented:
OAuth2 Authorization Flow:
The problem is with Step 4 where front-end should send authorization code to back-end. I just don't know which endpoint to use and how to configure it in Spring Security configuration.
This endpoint should get authorization code, check it on OAuth provider side, request access and refresh token and remember the authorized user.
Maybe there is an example of how it should be done? Google answers do not seem appropriate.
What I already did:
Added #EnableOAuth2Sso annotation to the security configuration. But this is not what I actually need, because it enables authorization on back-end side. (redirecting to Google page works from back-end, but I need from front-end)
#EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
Tried configuring Oauth2Login by myself.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.oauth2Login()
.clientRegistrationRepository(clientRegistrationRepository)
.authorizedClientService(new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository));
}
Gradle dependencies:
<pre>
compile 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.0.RELEASE'
compile 'org.springframework.security:spring-security-oauth2-jose'
compile 'org.springframework.security:spring-security-oauth2-client'
</pre>
What I expect:
Some endpoint on back-end side, which accepts authorization code. For example:
URL: localhost:8080/oauth2/authcode/google
<pre>
{
"authorization_code": "...."
}
</pre>
And returns access token:
<pre>
{
"access_token": "...",
"expires": "..."
}
</pre>
And what is happening in the middle: back-end exchanges authorization code to access token and refresh token and saves it to own DB.
Thank you!

Resources