How to only check for Authentication by "Bearer" header in Spring Boot using Spring Security? - spring

I want to authenticate a server. I want to make sure the user is giving a header key, I am not checking for login or anything.
I want the header key to check with my hardcoded one,
If its equal pass it,
Else no
I wrote two filters.
SecurityConfig.java
package com.company.framework.filter;
import javax.servlet.http.HttpServletResponse;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
public class SecurityConfig{
#Autowired private AuthFilter filtet;
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
System.out.println("reaching here3 ");
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/open/**").permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error here")
)
.and()
.sessionManagement()
.and()
.httpBasic().disable();
http
.addFilter(filtet);
return http.build();
}
}
Authfilter.java
package com.company.framework.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
#Component
public class AuthFilter extends OncePerRequestFilter{
#Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
System.out.println("here ");
System.out.println(authHeader+"1");
if (authHeader != null && authHeader.length() == 0 && authHeader.startsWith("Bearer ")) {
String jwt = authHeader.substring(7);
System.out.println(authHeader+"2");
if (jwt == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token in Bearer Header");
} else {
String rev = "bfrek";
if (jwt.equals(rev)) {
response.setStatus(200);
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token");
}
}
}
filterChain.doFilter(request, response);
}
}
But, after all days of try and error, I am still getting 401 unauthorised.
I have seen articles telling how to connect it with users database but I just want to check for header token and pass it through. (Using filter)
Edit 1:
Now after reading many articles and documentation, I understand that there are 15 filters, But how do I make sure that the system just checks for my header key and ignore everything else.

Seems you missed overriding the configure method of WebSecurityConfigurerAdapter class. This is the main logic to override the default spring security logic. This is the main problem i guess. try to extend that class(WebSecurityConfigurerAdapter) and override that method(configure) in SecurityConfig.java.
SecurityConfig.java
package com.company.framework.filter;
import javax.servlet.http.HttpServletResponse;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurer{
#Autowired private AuthFilter filtet;
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
System.out.println("reaching here3 ");
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/open/**").permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error here")
)
.and()
.sessionManagement()
.and()
.httpBasic().disable();
http.addFilter(filtet);
return http.build();
}
}

Related

Validate captcha before logging

I am trying to validate a captcha image before validating the user.
In order to validate the captcha I have created the following class that will process POST requests from /mvc/login
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
public class CaptchaAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private final Logger logger = LoggerFactory.getLogger(getClass());
private String processUrlString;
protected CaptchaAuthenticationFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
this.processUrlString=defaultFilterProcessesUrl;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req =(HttpServletRequest) request;
HttpServletResponse res =(HttpServletResponse) response;
logger.info("doFilter.method " + req.getMethod() + " .doFilter.getRequestURI " + req.getRequestURI());
if(processUrlString.equals(req.getRequestURI()) && "POST".equalsIgnoreCase(req.getMethod())) {
String expected = req.getSession().getAttribute("captcha").toString();
req.getSession().removeAttribute("captcha");
if (expected!=null && !expected.equals(req.getParameter("answer"))) {
unsuccessfulAuthentication(req, res, new InsufficientAuthenticationException("Wrong code"));
return;
}
}
chain.doFilter(request, response);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
return null;
}
}
In order to associate the filter to the requests I have created the following configuration class, where I specified the filter to use with: addFilterBefore
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new CaptchaAuthenticationFilter("/mvc/login"), UsernamePasswordAuthenticationFilter.class);
http.authorizeRequests()
.antMatchers("/assets/**").permitAll()
.antMatchers(HttpMethod.POST, "/mvc/login").permitAll() // Is this necessary?
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/mvc/index")
.usernameParameter("j_user")
.passwordParameter("j_password")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
public UserDetailsService users() {
UserBuilder users = User.withDefaultPasswordEncoder();
UserDetails user = users
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
Am I following the right path in order to validate the request? Or should I follow a different strategy?
One issue that I have detected is that with every logging attempt it is displaying the following request doFilter.method POST .doFilter.getRequestURI /mvc/error instead of doFilter.method POST .doFilter.getRequestURI /mvc/login
This is my login form too:
<form action="/mvc/login" method="post">
<input type="text" id="j_user" name="j_user">
<input type="text" id="j_password" name="j_password">
<input type="text" id="answer" name="answer">
<input type="submit">
</form>
This seems like right way to validate captcha. Most likly CSRF filter in intercepting the request and because of missing CSRF, it is redrecting you to error page (URL) that you see in the logs.

POST operation on /logout and getting No mapping for GET /login

I'm trying to perform logout so I send POST on /logout but what I get is:
{
"timestamp": 1590427554418,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/login"
}
I'm using POSTMAN. Despite having error logout perform correclly, because I cannot make any actions on other endpoints when I'm not logged.
The point is when code is uploaded on the server I got timeout:
I thought it might be somehow related.
WebSecurityConfiguration
package odd.jobs.configuration;
import odd.jobs.configuration.authentication.JsonObjectAuthenticationFilter;
import odd.jobs.configuration.authentication.RestAuthenticationFailureHandler;
import odd.jobs.configuration.authentication.RestAuthenticationSuccessHandler;
import odd.jobs.services.user.UserCrudService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.Collections;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserCrudService userService;
private final RestAuthenticationSuccessHandler authenticationSuccessHandler;
private final RestAuthenticationFailureHandler authenticationFailureHandler;
#Autowired
public WebSecurityConfiguration(UserCrudService userService, RestAuthenticationSuccessHandler authenticationSuccessHandler, RestAuthenticationFailureHandler authenticationFailureHandler) {
this.userService = userService;
this.authenticationSuccessHandler = authenticationSuccessHandler;
this.authenticationFailureHandler = authenticationFailureHandler;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll();
http.cors();
}
#Bean
public JsonObjectAuthenticationFilter authenticationFilter() throws Exception {
JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
filter.setAuthenticationFailureHandler(authenticationFailureHandler);
filter.setAuthenticationManager(super.authenticationManagerBean());
return filter;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.unmodifiableList(Arrays.asList("*")));
configuration.setAllowedMethods(Collections.unmodifiableList(Arrays.asList("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH")));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(Collections.unmodifiableList(Arrays.asList("Authorization", "Cache-Control", "Content-Type")));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
It seems you used postman but with wrong method type as postman exception implies
Please change postman HTTP method from GET to POST from here :
Hope it should work!
If you want to use POST /logout, configure Spring Security with new AntPathRequestMatcher("/logout", "POST") instead of new AntPathRequestMatcher("/logout") (GET is used by default)

I want to see the login page first even any user want access any other page need to redirect to login page in spring security

Here is the sample controller. My problem is basically when i am entering the base url it is redirecting to inner page not in the log in page. What i want. What should i do to achieve this.
Here is the sample controller. My problem is basically when i am entering the base url it is redirecting to inner page not in the log in page. What i want. What should i do to achieve this.
package com.sushovan.security.controller;
import javax.validation.groups.ConvertGroup;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
#RequestMapping("/")
public String home() {
return "home.jsp";
}
#RequestMapping("/login")
public String loginPage() {
return "login.jsp";
}
#RequestMapping("/logout-success")
public String logoutPage() {
return "logout.jsp";
}
}
Here is the sample Security Configuration class.Mostly all configuration have been done here.
package com.sushovan.security.config;
import java.util.ArrayList;
import java.util.Collection;
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.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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;
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.NoOpPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.AntPathMatcher;
#Configuration
#EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
/**This is for authentication from database**/
#Bean
public AuthenticationProvider authProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
//provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());//This is for not use any encryption
provider.setPasswordEncoder(new BCryptPasswordEncoder());//This is for BCryptPasswordEncoder
return provider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/login")
.permitAll()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("userName").passwordParameter("password")
.permitAll()
.and()
.logout().invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/logout-success").permitAll();
}
}
Spring security filters algorithm works like this ;
is web resource protected ?
is user authenticated ?
is user authorized ?
So if its not authenticated it redirect request to login page, which is what you want.
So you should update your configure method
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("userName").passwordParameter("password")
.permitAll()
.and()
.logout().invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/logout-success").permitAll();
}
can you please try this and let me know if it works ?

Getting problem authenticationProvider in jwt authorization

I am getting error in configure method of SecurityConfig class whose code is here:
package com.sumit.Security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.sumit.Repo.UserRepository;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
private UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// remove csrf and state in session because in jwt we do not need them
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager(),userRepository))
.authorizeRequests()
// configure access rules
.antMatchers("/register").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.antMatchers("/user").hasAnyRole("ADMIN","USER")
.antMatchers("/management").hasAnyRole("MANAGER","ADMIN")
.antMatchers("/page1").hasAnyAuthority("ROLE_ADMIN","ACCESS_PAGE1")
.antMatchers("/page2").hasAnyAuthority("ROLE_ADMIN","ACCESS_PAGE2")
.anyRequest().authenticated();
// .and()
// .formLogin()
// .loginPage("/login")
// .usernameParameter("username")
// .passwordParameter("password").successForwardUrl("/welcome")
// .permitAll();
}
#Bean
DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setUserDetailsService(this.userDetailsService);
return daoAuthenticationProvider;
}
#Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
in above code, error lies here auth.authenticationProvider(authenticationProvider());
code is getting compiled fine but due to this i am getting 403 forbidden. Flow is getting broken here
JwtAutheticationFilter class is here
package com.sumit.Security;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.auth0.jwt.JWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sumit.Repo.UserRepository;
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
LoginModel credentials = null;
try {
credentials = new ObjectMapper().readValue(request.getInputStream(), LoginModel.class);
} catch (Exception e) {
e.printStackTrace();
}
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
credentials.getUsername(), credentials.getPassword(), new ArrayList<>());
Authentication auth = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
return auth;
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
UserPrincipal principal = (UserPrincipal) authResult.getPrincipal();
String token = JWT.create()
.withSubject(principal.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + JWTProperties.EXPIRATION_TIME))
.sign(HMAC512(JWTProperties.SECRET.getBytes()));
response.addHeader(JWTProperties.HEADER_STRING, JWTProperties.TOKEN_PREFIX + token);
}
}
JwtAuthorizationFilter class is here
package com.sumit.Security;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.auth0.jwt.JWT;
import com.sumit.Repo.UserRepository;
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
#Autowired
private UserRepository userRepository;
public JwtAuthorizationFilter(AuthenticationManager authenticationManager,UserRepository userRepository
) {
super(authenticationManager);
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// Read the Authorization header, where the JWT token should be
String header = request.getHeader(JWTProperties.HEADER_STRING);
// If header does not contain BEARER or is null delegate to Spring impl and exit
if (header == null || !header.startsWith(JWTProperties.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
// If header is present, try grab user principal from database and perform authorization
Authentication authentication = getUsernamePasswordAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Continue filter execution
chain.doFilter(request, response);
}
private Authentication getUsernamePasswordAuthentication(HttpServletRequest request) {
String token = request.getHeader(JWTProperties.HEADER_STRING)
.replace(JWTProperties.TOKEN_PREFIX,"");
if (token != null) {
// parse the token
String userName = JWT.require(HMAC512(JWTProperties.SECRET.getBytes()))
.build()
.verify(token)
.getSubject();
if (userName != null) {
User user = userRepository.findByUsername(userName);
UserPrincipal principal = new UserPrincipal(user);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userName, null, principal.getAuthorities());
return auth;
}
return null;
}
return null;
}
}
User registration process is working fine but authentication is not working because of above mentioned code.
I am using postman to verify it.
Don't know what trouble i am facing and totally frustrated.

Thymeleaf tries to authenticate again when loading template from a controller

I want to render a navigation view from a controller using Thymeleaf. However, the navigation should be based on user's authorities so I do not want to exclude it from Spring Security. I therefore use a UrlTemplateResolver:
package it.vertyze.platform.web.controllers;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.templateresolver.UrlTemplateResolver;
#Configuration
public class VZMVCConfig extends WebMvcConfigurerAdapter {
#Autowired
private SpringTemplateEngine templateEngine;
#PostConstruct
public void templateResolverExtension(){
UrlTemplateResolver urlTemplateResolver = new UrlTemplateResolver();
urlTemplateResolver.setOrder(20);
templateEngine.addTemplateResolver(urlTemplateResolver);
}
}
However, when I log into my site, the link does not even get resolved. Instead, I am being redirected to the login page. When I disable the security, I get a template not found error, so the template resolver does not render the controller's output, but when I navigate to it, it renders precisely the HTML I want.
Here is my security config:
package it.vertyze.platform.web.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebMvcSecurity
public class VZWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
VZUserDetailsService userDetailsService;
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
public PasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
}
And here is where I call the link in the enclosing template:
<div th:replace="${topNavLinks.getHref()}"></div>

Resources