How do session time out and and ask for login again in Spring boot - spring

I am trying to build simple JSON rest API using spring boot, I have build the application it works fine, now I need to do the simple Basic authentication and I did this with Spring security. Please find the Code below, My pain point here is when I run the application, I ask for the login first time then I tried to reload the URL again it does not ask for user name password. How to make the URL session expired and ask to prompt for login again. Note : I am not using any UI, It just an API
Security Configuration Class
package com.erplogic.erp.topcon.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
public class SecurityConfiguration {
#Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()
).sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
)
.httpBasic();
return http.build();
}
#Bean
InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.builder().username("user").password(encoder().encode("pass")).roles("USER").build();
return new InMemoryUserDetailsManager(user);
}
#Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
#Bean
SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
}
Controller Class
package com.erplogic.erp.topcon.controller;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.erplogic.erp.topcon.service.SapApiService;
import com.erplogic.poc.objects.Root;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.erplogic.maven.plclog.wsdl2java.StandardFaultMessage_Exception;
#RestController
public class OutboundController {
#Autowired
private SapApiService sapApiService;
#RequestMapping(path ="/outbound",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET)
public Root getOutbound() throws KeyManagementException, NoSuchAlgorithmException, StandardFaultMessage_Exception, JsonProcessingException {
return ((SapApiService) sapApiService).processOutboudService();
}
#RequestMapping(value = "/outbound/{outboundId}",produces = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.GET)
public String getOutboundId(#PathVariable String outboundId) throws KeyManagementException, JsonProcessingException, NoSuchAlgorithmException, StandardFaultMessage_Exception {
return ((SapApiService) sapApiService).processOutboudServiceByID(outboundId);
}
}

Related

spring boot 3 - digest authentication not working

I am not able to create a simple rest API with digest authentication with spring boot 3. It was working with version 2, but with a different configuration, because WebSecurityConfigurerAdapter is not present anymore.
I create simple GitHub repository with the sample:
https://github.com/martinspudich/spring-boot-3-digest
I will appreciate any help you can provide. Thank you in advance.
I create simple HelloController:
package com.example.springboot3digest.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloController {
#GetMapping("/")
public String hello() {
return "Hello World!";
}
}
And WebSecurityConfig:
package com.example.springboot3digest.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.DigestAuthenticationFilter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http, UserDetailsService userDetailsService) throws Exception {
http
.authorizeHttpRequests(request -> {
request.anyRequest().authenticated();
})
.exceptionHandling(e -> e.authenticationEntryPoint(entryPoint()))
.addFilterBefore(digestAuthenticationFilter(userDetailsService), BasicAuthenticationFilter.class);
return http.build();
}
#Bean
UserDetailsService userDetailsService() {
UserDetails user = User.builder()
.username("user")
.password("user")
.roles("USER").build();
return new InMemoryUserDetailsManager(user);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
DigestAuthenticationEntryPoint entryPoint() {
DigestAuthenticationEntryPoint result = new DigestAuthenticationEntryPoint();
result.setRealmName("My App Realm");
result.setKey("3028472b-da34-4501-bfd8-a355c42bdf92");
return result;
}
DigestAuthenticationFilter digestAuthenticationFilter(UserDetailsService userDetailsService) {
DigestAuthenticationFilter result = new DigestAuthenticationFilter();
result.setUserDetailsService(userDetailsService);
result.setAuthenticationEntryPoint(entryPoint());
return result;
}
}
I was following spring.io documentation:
https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/digest.html
But authentication is not working. When I try to authenticate it returns the error 403 Forbidden.
The DigestAuthenticationFilter does not generate "authenticated" tokens unless you explicitly tell it to do so as described here.
Add the line:
result.setCreateAuthenticatedToken(true);
to your DigestAuthenticationFilter instantiation:
DigestAuthenticationFilter digestAuthenticationFilter(UserDetailsService userDetailsService) {
DigestAuthenticationFilter result = new DigestAuthenticationFilter();
result.setUserDetailsService(userDetailsService);
result.setCreateAuthenticatedToken(true);
result.setAuthenticationEntryPoint(entryPoint());
return result;
}

hasRole("ROLE_USER") not working in spring boot3 with springsecurity6

I have created one LoginFilter in spring boot where i have created the user authentication object and after that redirected to dashboard page
my below files are:
LoginFilter.java
import jakarta.servlet.*;
/*import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;*/
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.GenericFilterBean;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
#Component
public class LoginFilter extends GenericFilterBean {
private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,ServletException
{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
updatedAuthorities.add(authority);
authentication = new UsernamePasswordAuthenticationToken("myemail.gamil.com", null, updatedAuthoritie
SecurityContextHolder.getContext().setAuthentication(authentication);
this.redirectStrategy.sendRedirect((HttpServletRequest) request, (HttpServletResponse) response,"/dashboard");
}
}
WebSecurityConfigDashboard.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
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.WebSecurityCustomizer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
public class WebSecurityConfigDashboard {
#Autowired
private LoginFilter loginFilter;
#Bean
//authentication
public UserDetailsService userDetailsService1(PasswordEncoder encoder) {
UserDetails admin = User.withUsername("user1")
.password(encoder.encode("123"))
.roles("ROLE_USER")
.build();
UserDetails user = User.withUsername("user2")
.password(encoder.encode("123"))
.roles("ROLE_USER")
.build();
return new InMemoryUserDetailsManager(admin, user);
}
#Bean
public SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeHttpRequests()
.requestMatchers("/dashboard*").hasRole("ROLE_USER")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.failureUrl("/loginError")
.and().logout()
.invalidateHttpSession(true)
.logoutSuccessUrl("/logout")
.logoutUrl("/j_spring_security_logout").and()
.sessionManagement()
.maximumSessions(12)
.expiredUrl("/logout");
http.addFilterAfter(loginFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public WebSecurityCustomizer webSecurityCustomizer1() {
return (web) -> web.ignoring().requestMatchers("/resources/images/**");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
LoginController.java
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.*;
#Controller
public class LoginController {
#RequestMapping(value = "/dashboard")
public String dashboard(Model model,Principal principal,HttpServletRequest request, HttpServletResponse response)
{
System.out.println("/dashboard called:------------------------>");
System.out.println("PRINCIPAL:--------------->"+principal.getName());
return 'dashboard';
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(ModelMap model) {
System.out.println("/login called:------------------------>");
return "login";
}
#RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(ModelMap model) {
System.out.println("/logout called:------------------------>");
return "logout";
}
#RequestMapping(value = "/loginError", method = RequestMethod.GET)
public String loginError(ModelMap model) {
model.addAttribute("error", "LOGIN FAILED");
return "login";
}
#RequestMapping(value = "/error", method = RequestMethod.GET)
public String error(ModelMap model,HttpServletRequest request, HttpServletResponse response) {
return "error";
}
}
when I calling /dashboard url in browser the it goes to login page instead of dashboard i have created UsernamePasswordAuthenticationToken in filter class.
If i remove .hasRole("ROLE_USER") and instead put .permitAll() and then if I hit /dashboard then the method with /dashboard is called but principle object getting null
I have using spring boot 3 with spring security 6
I dont't know why this is happening?
A common oversight is that roles() and hasRole() will add the ROLE_ prefix for you.
So, instead of doing hasRole('ROLE_USER'), please do hasRole('USER'). And instead of doing roles('ROLE_USER') when creating the user, do roles('USER').
I've added a Spring Security ticket to clarify this.

Missing bean in controller even after adding ComponentScan annotation

I am trying to run a spring boot application which gets a list of names of people from the database. I am getting the below error :
Description:
Field peopleserviceinterface in com.sample.lombpackdemo.controller.FriendController required a bean of type 'com.sample.lombpackdemo.service.FriendsServiceInterface' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.sample.lombpackdemo.service.FriendsServiceInterface' in your configuration.
package com.sample.lombpackdemo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sample.lombpackdemo.entity.Friends;
import com.sample.lombpackdemo.rowmapper.FriendsRowMapper;
import com.sample.lombpackdemo.service.FriendsServiceInterface;
#CrossOrigin(origins = { "http://localhost:3000"})//to allow access from other servers
#RestController
#RequestMapping("/code")
#ComponentScan(basePackages="com.sample.lombpackdemo.service")
public class FriendController {
#Autowired
private FriendsServiceInterface peopleserviceinterface;//autowire the service
#GetMapping("/all")
public ResponseEntity<List<Friends>> getAllPeople(){
List <Friends> listOfAllPpl = peopleserviceinterface.getAllFriends();
System.out.println("Getting all friends"+listOfAllPpl.toString());
return new ResponseEntity<List<Friends>>(listOfAllPpl,HttpStatus.OK);
}
}
The FriendServiceInterface class is as below:
package com.sample.lombpackdemo.service;
import java.util.List;
import org.springframework.stereotype.Component;
import com.sample.lombpackdemo.entity.Friends;
#Component
public interface FriendsServiceInterface {
public List<Friends> getAllFriends();
}
The FriendService class:
package com.sample.lombpackdemo.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.sample.lombpackdemo.entity.Friends;
import com.sample.lombpackdemo.repos.FriendsRepo;
import com.sample.lombpackdemo.rowmapper.FriendsRowMapper;
#Service
#Profile("devel")//added to disable CORS only on development time
#Configuration
#Component
public class FriendService implements FriendsServiceInterface {
#Autowired
private FriendsServiceInterface peopleserviceinterface;
#Autowired
private FriendsRepo pplRepo;//should always autowire repository
#Autowired
private JdbcTemplate jdbc;
private static long idCounter = 0;
//FriendsRowMapper fRowMap=new FriendsRowMapper();
#Override
public List<Friends> getAllFriends() {
String sql="select f_name from list_friends";
return jdbc.query(sql, new FriendsRowMapper() );
/*
List<Friends> ppList= (List<Friends>) fRowMap.findAll();
try {
System.out.println("Repository value"+pplRepo.findAll());
System.out.println("Inside findAll of service class" +ppList.toString() );
}
catch(Exception e)
{
}
return ppList;
//
*/}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
//registry.addMapping("/save-javaconfig").allowedOrigins("http://localhost:3000");
}
};
}
Please let me know what else needs to be changed. I have tried adding Component annotation to FriendService class and ComponentScan annotation to the controller class.
Edited to add JdbcConfig class
package com.sample.lombpackdemo.repos;
//import java.util.logging.Logger;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
#Configuration
#ComponentScan(basePackages = "com.sample.lombpackdemo")
public class SpringJdbcConfig {
protected final Logger log = LoggerFactory.getLogger(getClass());
#Bean
public DataSource mysqlDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/person_example");
dataSource.setUsername("root");
dataSource.setPassword("subfio");
return dataSource;
}
#Bean(name = "dbProductService")
#ConfigurationProperties (prefix = "spring.datasource")
#Primary public DataSource createProductServiceDataSource()
{ System.out.println("Inside db cofig ");
return DataSourceBuilder.create().build(); }
}
}

Spring WebFlux Request Principal is null in test

We have library which provides a custom filter for our requests, which we use to write information on the request to our logs. We previously only needed servlet support, but now need to add webflux support. I've created a new WebFilter, which works as expected.
However, trying to test this new filter has been difficult. We're relying on the principal in the request for user information for the log, but during the test, it is always null. I've tried many things, including following the examples here: https://docs.spring.io/spring-security/site/docs/5.1.0.RELEASE/reference/html/test-webflux.html
My Filter:
package com.project.utils.security.request.logging.config.autoconfig;
import com.project.utils.logging.LoggingUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
public class ReactiveRequestLoggingFilter implements WebFilter {
private static final Logger logger = LoggerFactory.getLogger(ReactiveRequestLoggingFilter.class);
#Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
return serverWebExchange
.getPrincipal()
.flatMap(
principal -> {
LoggingUtil loggingUtil =
new LoggingUtil(serverWebExchange.getRequest(), principal.getName());
loggingUtil.setEvent("Http Request");
logger.info(loggingUtil.toString());
return webFilterChain.filter(serverWebExchange);
});
}
}
My Test:
package com.project.utils.security.request.logging.config.autoconfig;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
import com.project.utils.security.request.logging.config.testcontrollers.ReactiveTestController;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {ReactiveTestController.class})
class ReactiveRequestLoggingFilterTest {
#Autowired ReactiveTestController controller;
ReactiveRequestLoggingFilter filter = new ReactiveRequestLoggingFilter();
#Test
void test() {
WebTestClient client =
WebTestClient.bindToController(controller)
.webFilter(filter)
.apply(springSecurity())
.configureClient()
.build()
.mutateWith(mockUser("User"));
client
.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("GET");
}
}
The controller I'm using for the test:
package com.project.utils.security.request.logging.config.testcontrollers;
import com.project.utils.security.request.logging.config.annotations.EnableReactiveRequestLogging;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
#RestController
#RequestMapping("/test")
#EnableReactiveRequestLogging
public class ReactiveTestController {
#GetMapping
Mono<ResponseEntity<String>> get() {
return Mono.just(ResponseEntity.ok("GET"));
}
}
We are using Spring Boot 2.1, which uses Spring Security 5.1. Like I said, the actual functionality works, but we need to get tests written for it, and I can't figure out how to get the principal into the request.
Thanks!
Okay, found a working solution from this answer: https://stackoverflow.com/a/55426458/1370823
My final test looked like:
package com.project.utils.security.request.logging.config.autoconfig;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
import com.project.utils.security.request.logging.config.testcontrollers.ReactiveTestController;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {ReactiveTestController.class, ReactiveRequestLoggingFilter.class})
#WebFluxTest(controllers = {ReactiveTestController.class})
#WithMockUser(value = "Test User", username = "TestUser")
class ReactiveRequestLoggingFilterTest {
#Autowired ReactiveTestController controller;
#Autowired ReactiveRequestLoggingFilter filter;
#Test
void test() {
WebTestClient client =
WebTestClient.bindToController(controller)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.webFilter(filter)
.apply(springSecurity())
.build();
client
.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("GET");
}
}

How do you setup a resource server in spring boot that only uses role from the jwt token to allow access?

I think I have some odd requirements here because no matter where I look, I can't a specific example for what I was asked to do. I created a dummy project called contacts to test this. I am suppose to secure my api with Oauth2, but the authorization server is not on the same box.
It is my understanding that the client will need to call the authorization to get a token and then the request with the token will be sent to my api.
In my server the scope will determine if the user has access. I am not doing any authentication on my server.
I can't seem to get this to work though.
Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(value = "/contacts")
#PreAuthorize("#oauth2.hasScope('ec.edm.mdm')")
public class ContactsController {
#Autowired
ContactRepository customerRepo;
#RequestMapping(method = RequestMethod.GET, produces = { "application/json" })
public Page<Contact> findAllContacts(Pageable pagable) {
return customerRepo.findAll(pagable);
}
}
Application
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
#EnableResourceServer
#SpringBootApplication
public class App {
private static final Logger LOG = LoggerFactory.getLogger(App.class);
#Autowired
private Environment environment;
public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
/**
* Allows for #PreAuthorize annotation processing.
*/
#EnableGlobalMethodSecurity(prePostEnabled = true)
protected static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
}

Resources