How to have unauthenticated endpoints with Spring Boot Resource Server - spring

I have a spring boot application annotated with #ResourceServer. I am trying to have unauthenticated endpoints as well as authenticated endpoints in my application, however all the endpoints return the same 401 response.
My SecurityConfig looks like this:
#Configuration
#EnableWebSecurity
class SecurityConfig: WebSecurityConfigurerAdapter() {
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/search").permitAll()
.anyRequest().authenticated()
.and().httpBasic()
}
}
But when I send a POST request to /api/search I get this response:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
I also tried having only anyRequest().permitAll() in my SecurityConfig, but it still returns the same response.

It was a pretty noobie mistake. I was actually configuring a WebSecurityConfigurerAdapter instead of a ResourceServerConfigurerAdapter.

Related

Spring Cloud Gateway + Keycloak CORS not working

I developed backend microservice application using Spring Boot and put API Gateway in front of microservices. To authenticate users I am using Keycloak.
Right now I am developing frontend application using Svelte, I configured my application.yml in gateway application like this:
spring:
cloud:
gateway:
default-filters:
- TokenRelay
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
add-to-simple-url-handler-mapping: true
However, when I am trying to send AJAX request I get the CORS error.
Also I Have spring security (through org.springframework.boot:spring-boot-starter-oauth2-client and org.springframework.boot:spring-boot-starter-oauth2-resource-server dependencies). I defined SecurityWebFilterChain as:
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.cors().and()
.authorizeExchange()
.pathMatchers("/actuator/**")
.permitAll()
.and()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login(); // to redirect to oauth2 login page.
return http.build();
}
When putting build of frontend in static folder there is no CORS error, but for development I need developer node.js server on localhost on different port.
So, how to fix this cors issue?
You can create a class to define the Cors mapping like this:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
The example above enables CORS requests from any origin to any endpoint in the application.
To lock this down a bit more, the registry.addMapping method returns a CorsRegistration object, which we can use for additional configuration. There’s also an allowedOrigins method that lets us specify an array of allowed origins. This can be useful if we need to load this array from an external source at runtime.
Additionally, there are also allowedMethods, allowedHeaders, exposedHeaders, maxAge and allowCredentials that we can use to set the response headers and customization options.
CORS With Spring Security:
If you use Spring Security in youproject, you must take an extra step to make sure it plays well with CORS. That's because CORS needs to be processed first. Otherwise, Spring Security will reject the request before it reaches Spring MVC.
Luckily, Spring Security provides an out-of-the-box solution:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}

How to validate tokens received from authorization server

I have a oauth flow in my project.
I retrieve in the front-end a jwt token and add it to each request in the authorization header.
Now I need to validate said token and verify the signature in my back-end which is a kotlin spring boot app.
I know how to validate the token with the jjwt library but I don't understand where the validation is done.
I have a certificate to validate the tokens with and just want to let the requests with a valid token to be treated.
I saw online that some people do it with a OncePerRequestFilter that they add to their SecurityConfiguration but I don't understand what's going on and how it works.
I tried searching for tutorials online but many of them make a backend that's both the authorization server and resource server. I just want the backend to be the resource server that checks with the certificate if the token is valid and treats the request if it is. How can I do that ?
For now this is my SecurityConfiguration :
package com.renaulttrucks.transfertprotocolbackend.security.config
import org.springframework.beans.factory.annotation.Value
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
#EnableWebSecurity
class SecurityConfig : WebSecurityConfigurerAdapter() {
#Value("\${security.enabled}")
val securityEnabled : Boolean? = false
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
if(!securityEnabled!!) {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/**").permitAll()
.and()
.csrf().disable()
.formLogin().disable()
} else {
http.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/**").permitAll()
.and()
.csrf().disable()
.formLogin().disable()
}
}
}
Spring Security supports resource servers out-of-the-box when including the correct dependencies and configuration.
As #sdoxsee mentioned, there is a Spring Security sample that outlines how to create a resource server with a public key; however, I'll briefly summarize it here, though you can find more detail in the Spring Security reference.
First, you need to add the appropriate dependency. If you are a Spring Boot application, then you can add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
Second, you either specify your key as a Boot property:
spring:
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:my-key.pub
or, you configure a JwtDecoder with your public key directly:
#Configuration
class SecurityConfig {
#Value("${public.key.property}") val key : RSAPublicKey;
#Bean
fun jwtDecoder() : JwtDecoder {
return NimbusJwtDecoder.withPublicKey(this.key).build();
}
}
Either the Boot property or the JwtDecoder #Bean will introduce a filter automatically into the filter chain called BearerTokenAuthenticationFilter, so you don't need to create your own.

Ignore authorization for some endpoints in Spring Boot

I have my OAuth server and client which is being authorized by Oauth2.
Now if I need to call my service I need to:
Generate access token from the server using below API :
localhost:9191/oauth/token?grant_type=password&username=krish&password=kpass
Which is giving response like :
"access_token": "ee41435d-8ad9-432e-82c1-07477e2b6956",
"token_type": "bearer",
"refresh_token": "ea6d83b4-62f6-4eaf-9f89-8600bd36690d",
"expires_in": 3429,
"scope": "READ WRITE"
Now I am passing access token, to run the client service like below:
So this is manually I am doing it. But I need to run it from the client code. When I am trying to hit the first API itself (server) to get the token, it is saying unauthorized.
My service code is below :
I need to skip the authentication from the /getToken controller. How can I do that? Can anyone please help
My WebSecurityConfigurerAdapter class is as below:
I added highlighted code after reading one answer below, but that also not working.
You may want to create a new configuration extending the WebSecurityConfigurerAdapter and override the configure method.
Have a look at this guide for a practical example.
Want you want to focus on is this part
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
As you can see in the example the path "/login","/","/home" are excluded from authentication.
Check this other answer also: Spring Security exclude url patterns in security annotation configurartion

Spring Boot handle JWT manually

I'm currently working with OpenID and the JWT for authentication and try to work it out manually - just for understandy .. dont worry ;-)
So i created a Filter which extends AbstractAuthenticationProcessingFilter but it is not called after getting the JWT token. This is my security config:
#Configuration
#EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
#Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http
.addFilterAfter(OpenIdConnectFilter("/secure"), OpenIDAuthenticationFilter::class.java)
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
having a breakpoint in the attemptAuthentication of the OpenIdConnectFilter but it is never called, even no exception nothing .. just 403 on client side.
Edit:
So do you have any idea how to "intercept" the incoming request with my OpenIDConnectFilter to do the verification there?

Spring Boot Custom Authorization Header request not going through at all

So I have a Spring Boot application and I am sending a request to it using PostMan. It is using Spring Security along with JWT for authentication. I'm trying to get authorization to work but am running into issues. Spring is able to login the user and return a token fine. But when I put the token in the header it's not working at all. I get no response from the server. When the token is removed, it works fine. Right now all requests should be able to go through regardless of being logged in or not.
My Spring Web Configuration:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()));
}
}
The REST path I'm trying to access:
#RestController("threadService")
#RequestMapping("/api/thread")
public class ThreadService {
#RequestMapping(value="/list", method=RequestMethod.GET)
public List<ThreadDetails> getThreadList() {
logger.info("getThreadList");
return threadDao.getThreadList();
}
}
The failed GET request I'm issuing after I have logged in and gotten a token:
GET /api/thread/list HTTP/1.1
Host: localhost:8080
Authorization : Bearer (JWT token here)
Cache-Control: no-cache
Postman-Token: 69565839-4806-b4f6-9a03-11382a80c7da
The above request works fine when there is no Authorization in the header.
Not sure it is exactly the problem I was facing.
When I want to communicate with the restservice exposed by spring boot application, the "Authorization" is not set. I followed the steps which are required to communicate but the value wont be passes through header.
The solution I found, the "common-codec" library was missing. Once I add the dependency in my web application, it start sending the "Authorization" in header to my spring boot application.
Hope this helps to someone.

Resources