I have
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/v1/account/import").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
I want that all users can come to /api/v1/account/import without any JWT token check. For all other endpoints I want a JWT token check in class JWTAuthenticationFilter. I tried many different scenarios but all failed. I always get to JWTAuthenticationFilter. I don't want to get to JWTAuthenticationFilter if I go to /api/v1/account/import.
My controller:
#RestController
#RequestMapping(value = "/api/v1/account")
public class AccountController {
private final AccountService accountService;
public AccountController(final AccountService accountService) {
this.accountService = accountService;
}
#PostMapping(path = "/import")
#ResponseStatus(HttpStatus.ACCEPTED)
public String importAccount(#Valid #RequestBody final ImportAccountDto importAccountDto) {
return this.accountService.importAccount(importAccountDto);
}
My JWT filter:
public class JWTAuthenticationFilter extends GenericFilterBean {
#Override
public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
final String token = request.getHeader("Authorization");
final JJWTService jjwtService = new JJWTService();
if (token == null || !jjwtService.parseJWTToken(token)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
filterChain.doFilter(req, res);
}
}
My test:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class AccountIT {
#Autowired
MockMvc mockMvc;
#Autowired
private AccountRepository accountRepository;
#Test
public void importAccount() throws Exception {
this.mockMvc.perform(post("/api/v1/account/import")
.contentType(MediaType.APPLICATION_JSON)
.content(toJson(importAccountDto)))
.andExpect(status().isAccepted())
.andReturn();
}
Try this
if (!request.getRequestURI().contains("/api/v1/account/import")) {
final JJWTService jjwtService = new JJWTService();
if (token == null || !jjwtService.parseJWTToken(token)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} else {
filterChain.doFilter(req, res);
}
}
Related
I am making a project for Register and Login operations. I am using spring security and jwt. It always returns 401 unauthorized to any request I throw in Postman. I couldn't find the reason. Could you help? I am using spring boot new version. 3.0.0 version.
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfiguration {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/auth/**").permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
#RestController
#RequestMapping("/auth")
#RequiredArgsConstructor
public class AuthenticationController {
private final AuthenticationService service;
#PostMapping("/register")
public ResponseEntity<AuthenticationResponse> register(
#RequestBody RegisterRequest request
) {
return ResponseEntity.ok(service.register(request));
}
#PostMapping("/authenticate")
public ResponseEntity<AuthenticationResponse> authenticate(
#RequestBody AuthenticationRequest request
) {
return ResponseEntity.ok(service.authenticate(request));
}
}
#Component
#RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
#Override
protected void doFilterInternal(
#NonNull HttpServletRequest request,
#NonNull HttpServletResponse response,
#NonNull FilterChain filterChain
) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
if (authHeader == null ||!authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
userEmail = jwtService.extractUsername(jwt);
if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
#Configuration
#RequiredArgsConstructor
public class ApplicationConfig {
private final CustomerRepository repository;
#Bean
public UserDetailsService userDetailsService() {
return username -> repository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
#Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I want to register and then login. I want to access some controllers based on role.
[SecurityConfig]
#Slf4j
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfig {
private final AuthenticationConfiguration authenticationConfiguration;
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
/*.headers().disable()*/
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager(authenticationConfiguration)), UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
[JwtAuthenticationFilter]
#RequiredArgsConstructor
#Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
log.info("Check Run");
ObjectMapper om = new ObjectMapper();
try {
AdvertiserUserDto.Read read = om.readValue(request.getInputStream(), AdvertiserUserDto.Read.class);
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(read.getUserLoginId(), read.getPassword());
log.info(authenticationToken.getPrincipal().toString());
log.info(authenticationToken.getCredentials().toString());
return authenticationManager.authenticate(authenticationToken);
}
catch (IOException e) {
e.printStackTrace();
log.error("IO Exception");
}
return null;
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
log.info("Success");
super.successfulAuthentication(request, response, chain, authResult);
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
log.info("Fail");
super.unsuccessfulAuthentication(request, response, failed);
}
}
[SecurityUserDetailsService]
#Slf4j
#RequiredArgsConstructor
#Service
public class SecurityUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
#Transactional
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("loadUserByUsername"); // **not Run**
UserEntity user = userRepository.findByUserLoginId(username).orElseThrow(() -> new UsernameNotFoundException("no Search User"));
return new SecurityUserDetails(
user,
/*Collections.singleton(new SimpleGrantedAuthority("ROLE_" + user.getType().getRoll()))*/
Collections.singleton(new SimpleGrantedAuthority("ROLE_" + "USER"))
);
}
}
[SecurityUserDetails]
#RequiredArgsConstructor
#Data
public class SecurityUserDetails implements UserDetails {
private final UserEntity user;
private final Collection<? extends GrantedAuthority> authorities;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getUserId().toString();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
Please note that I am struggling at a very basic level.
Here's the process I've tried so far:
Login attempt (user, pw)
Security Chain is executed
A filter that inherits from UsernamePasswordAuthenticationFilter is executed
It has been confirmed that ID and PW are normally passed as parameters.
Execute the authenticate() method of AuthenticationManager to check if ID and PW are correct.
The loadUserByUsername() method, which inherited UserDeatilsService, is not executed, and immediately the unsuccessfulAuthentication() method is executed and fails.
I attach the code.
According to my plan, validation should be done via loadUserByUsername().
But why does the validation job fail immediately without even being executed?
Result :
c.b.k.c.c.t.JwtAuthenticationFilter : Check Run
c.b.k.c.c.t.JwtAuthenticationFilter : test
c.b.k.c.c.t.JwtAuthenticationFilter : 1234
c.b.k.c.c.t.JwtAuthenticationFilter : Fail
I answer myself how I found it.
#Slf4j
#EnableWebSecurity
#RequiredArgsConstructor
public class SecurityConfig {
private final SecurityUserDetailsService securityUserDetailsService;
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(securityUserDetailsService);
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
httpSecurity
.cors()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.authenticationManager(authenticationManager)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
/*.headers().disable()*/
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Here's how I discovered and succeeded by other advice.
I think there are some things wrong with this method or something that needs to be improved.
I don't know if it's the right way, but I'm writing it down for others and for improvement.
AuthenticationManagerBuilder authenticationManagerBuilder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(securityUserDetailsService);
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
The key is here.
I approached the problem in that the userDetatilsService that I have customized and extended cannot be informed (cannot be injected) to the AuthenticationManager.
I'm trying pass filter JWTLoginFilter to WebSecurityConfig WebSecurityConfigurerAdapter by #Autowired annotation. The problem arise when JWTLoginFilter try get AuthenticationManager from WebSecurityConfig.
When I start server, I get this error:
Description:
The dependencies of some of the beans in the application context form
a cycle:
JWTLoginFilter defined in file
[C:\Users\user\workspace\backend\target\classes\pl\dn\schoolsystem\service\jwt\JWTLoginFilter.class]
webSecurityConfig (field
pl.dn.schoolsystem.service.jwt.JWTLoginFilter
pl.dn.schoolsystem.config.WebSecurityConfig.jwtLoginFilter)
error image
I think this circular dependency injection. I got stuck on this and i have no idea how to solve it.
WebSecurityConfig:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private UserSecurityService userSecurityService;
#Autowired
JWTLoginFilter jwtLoginFilter;
private static final String Salt = "salt"; // should be protected better
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12, new SecureRandom(Salt.getBytes()));
}
#Bean(name = BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
authorizeRequests().antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
//UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtLoginFilter,
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
}
}
JWTLoginFilter:
#Component
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{
#Autowired
UserService userService;
#Autowired
public JWTLoginFilter(#Value("/login") String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException,
IOException, ServletException {
System.out.println("Jestem w JwtLogginFilter.attemptAuthentication -------------------------------------");
AccountCredentials creds = new ObjectMapper()
.readValue(req.getInputStream(), AccountCredentials.class);
User user = userService.findByUsername(creds.getUsername());
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
user.getAuthorities()
)
);
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
System.out.println("Jestem w JWTLogginFilter.successfulAuthentication -------------------------------------- ");
System.out.println("authResult.getName(): " + authResult.getName());
TokenAuthenticationService.addAuthentication(response, authResult.getName());
}
}
I'm using Spring Boot 1.5.4. Thanks for suggestions
Your WebSecurityConfig explicitly requests JWTLoginFilter to be injected in it, and JWTLoginFilter requests AuthenticationManager to be injected in its constructor. AuthenticationManager is supplied by WebSecurityConfig, so you have a circular dependency.
Remove #Component annotation from JWTLoginFilter and define the filter as a bean in WebSecurityConfig:
#Bean
public JWTLoginFilter jwtLoginFilter() {
return new JWTLoginFilter("/login", authenticationManager());
}
You will probably also need to inject UserService manually in this method (for example, via constructor).
Thanks for help Roman Puchkovskiy I can correct my code. Final result of my code:
WebSecurityConfig:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private Environment env;
#Autowired
private UserSecurityService userSecurityService;
private static final String Salt = "salt"; // should be protected better
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12, new SecureRandom(Salt.getBytes()));
}
#Bean
public JWTLoginFilter jwtLoginFilter() throws Exception {
return new JWTLoginFilter("/login", authenticationManager());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
authorizeRequests().antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
// .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
// UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtLoginFilter(),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
}
}
JWTLoginFilter:
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{
#Autowired
UserService userService;
public JWTLoginFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException,
IOException, ServletException {
System.out.println("Jestem w JwtLogginFilter.attemptAuthentication -------------------------------------");
AccountCredentials creds = new ObjectMapper()
.readValue(req.getInputStream(), AccountCredentials.class);
User user = userService.findByUsername(creds.getUsername());
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
user.getAuthorities()
)
);
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
System.out.println("Jestem w JWTLogginFilter.successfulAuthentication -------------------------------------- ");
System.out.println("authResult.getName(): " + authResult.getName());
TokenAuthenticationService.addAuthentication(response, authResult);
}
}
I want to implement my own authentication with spring. To keep things simple at first I'm going to implement the first step without any session, but an HTTP-Authorization header sent in every request.
I've read the documentation, many tutorials and of course searched on stackoverflow, but I couldn't fix it.
What I have is a filter (RequestFilter), which extracts the Authorization header and initializes the security context with an own Authentication (AuthenticationToken). Then there is an AuthenticationProvider (TokenAuthenticationProvider) supporting my AuthenticationToken. The filter is working, the authentication provider is not. None of the methods in TokenAuthenticationProvider are invoked. Can you help me, thanks :).
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger LOGGER = Logger.getLogger(SecurityConfig.class.getName());
#Autowired
TokenAuthenticationProvider tokenAuthenticationProvider;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new RequestFilter(), BasicAuthenticationFilter.class)
.csrf().disable()
;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(tokenAuthenticationProvider)
;
}
}
#Component
public class TokenAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOGGER = Logger.getLogger(TokenAuthenticationProvider.class.getName());
#Autowired
ClientRepository clientRepository;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final String authToken = authentication.getCredentials().toString();
LOGGER.severe("AUTH TOKEN: " + authToken);
return Optional.ofNullable(clientRepository.findByAuthToken(authToken))
.map((Client client) -> new AuthenticationToken(client.getId(), client.getAuthToken()))
.orElseThrow(() -> new AccessDeniedException(""));
}
#Override
public boolean supports(Class<?> authentication) {
LOGGER.severe(authentication.getName());
return AuthenticationToken.class.isAssignableFrom(authentication);
}
}
public class RequestFilter extends OncePerRequestFilter {
private final Logger LOGGER = Logger.getLogger(RequestFilter.class.getName());
#Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
LOGGER.severe("RequestFilter works");
Optional.ofNullable(request.getHeader("Authorization"))
.ifPresent((String token) -> SecurityContextHolder
.getContext()
.setAuthentication(new AuthenticationToken(token))
);
chain.doFilter(request, response);
}
}
public class AuthenticationToken extends AbstractAuthenticationToken {
private final String credentials;
private final Long principal;
public AuthenticationToken(String credentials) {
this(null, credentials);
setAuthenticated(false);
}
public AuthenticationToken(Long principal, String credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(true);
}
#Override
public Object getCredentials() {
return credentials;
}
#Override
public Object getPrincipal() {
return principal;
}
}
#RestController
public class HttpGateController {
private static final Logger LOGGER = Logger.getLogger(HttpGateController.class.getName());
#RequestMapping(
name="/gate",
method= RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public String gateAction(#RequestBody String request) {
Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.map(Authentication::getCredentials)
.map(ObjectUtils::nullSafeToString)
.ifPresent(LOGGER::severe);
return request;
}
#RequestMapping("/status")
public String statusAction() {
return "It works.";
}
}
It looks very strange behavior, probably a bug.
I have a Spring boot 1.3.2 as backend API using Rest Service and I have another application using Angular 2 consuming these services.
All the security stuff is working ok with JWT Token, I can restricted my services for logged users, I can check the user logged and so on. Authorization is not working 100%, If I add on my services #Secured or #PreAuthorize with some user role this work with swagger and with my MockMvc tests using #WithMockUser(roles="ROLE_TEST") so it's configured OK.
The problem is that Authorization with #Secured or #PreAuthorize is not working when I'm accessing via angular application, All my requests that has #Secured or #PreAuthorize I receive Status 403.
authentication.getAuthorities() that all my roles is being loaded perfectly
Controller:
#RequestMapping(method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
#Secured("ROLE_MANTER_INSTITUICAO")
public List<HierarquiaInstituicao> getAll() {
return service.findAll();
}
Security Config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled=true, jsr250Enabled=true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private UserService userService;
private final TokenAuthenticationService tokenAuthenticationService;
public SpringSecurityConfig() {
super(true);
this.userService = new UserService();
tokenAuthenticationService = new TokenAuthenticationService(userService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().and().anonymous().and().servletApi().and()
.authorizeRequests()
// Allow anonymous logins
.antMatchers("/api/auth/**").permitAll()
// All other request need to be authenticated
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header
// previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
#Override
public UserService userDetailsService() {
return userService;
}
#Bean
public TokenAuthenticationService tokenAuthenticationService() {
return tokenAuthenticationService;
}
}
My filter:
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService authenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
Authentication authentication = authenticationService.getAuthentication(httpRequest);
if(authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
else {
httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
}
SecurityContextHolder.getContext().setAuthentication(null);
}
}