I'm making a spring boot webserver which has spring security and jwt for user authentication/authorization via username and password. But seems like spring recognize /api/users/signup and /api/users/signin
as must-be-authenticated URL.
UserController.java:
#PostMapping("/signin")
public ResponseEntity<String> login(#ApiParam("Username") #RequestParam String username, //
#ApiParam("Password") #RequestParam String password) {
return ResponseEntity.ok(userService.signin(username, password));
}
#PostMapping("/signup")
public void signUp(#ApiParam("SignUp User") #RequestBody SignUpRequest request) {
User user = User.of(request.getUsername(), bCryptPasswordEncoder.encode(request.getPassword()), request.getEmail());
Role userRole = roleRepository.findByName(RoleName.ROLE_MEMBER).orElse(null);
user.setRoles(Collections.singleton(userRole));
userRepository.save(user);
}
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenProvider jwtTokenProvider;
public WebSecurityConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// Disable CSRF (cross site request forgery)
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Entry points
http.authorizeRequests()//
.antMatchers("/api/users/signin").permitAll()//
.antMatchers("/api/users/signup").permitAll()//
.antMatchers("/api/test/**").permitAll()
.antMatchers("/h2-console/**/**").permitAll()
// Disallow everything else..
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
http.exceptionHandling().accessDeniedPage("/login");
// Apply JWT
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
http.cors().disable();
// Optional, if you want to test the API from a browser
// http.httpBasic();
super.configure(http);
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
JwtTokenFilter.java:
public class JwtTokenFilter extends OncePerRequestFilter {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
#Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
String token = jwtTokenProvider.resolveToken(httpServletRequest);
try {
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (CustomException ex) {
//this is very important, since it guarantees the user is not authenticated at all
SecurityContextHolder.clearContext();
httpServletResponse.sendError(ex.getHttpStatus().value(), ex.getMessage());
return;
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
MyUserDetailsService.java:
#Service
public class MyUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final User user = userRepository.findByUsername(username).orElseThrow(() -> new CustomException("User doesn't exist", HttpStatus.NOT_FOUND));
List<GrantedAuthority> authorities = user.getRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getName().getAuthority())
).collect(Collectors.toList());
if (user == null) {
throw new UsernameNotFoundException("User '" + username + "' not found");
}
return org.springframework.security.core.userdetails.User//
.withUsername(username)
.password(user.getPassword())
.authorities(authorities)
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
}
}
When I request to both of these links as I told above. It's done quickly by giving me 401 HTTP error code while testing on postman.
Both this link and this link are not helpful at all.
You might want to try excluding these URLs from the WebSecurity section, instead, so that they do not get processed by Spring Security and your JwtTokenFilter at all.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/api/users/signin").antMatchers("/api/users/signup");
}
}
Related
In order to protect my Rest API endpoints, I implemented Spring Security using JWT authentication. My code "works" without any issues/exceptions but it would be great if I could get my implementation validated to ensure it is implemented as expected.
WebSecurityConfig.java
#Configuration
#EnableWebSecurity
#RequiredArgsConstructor
public class WebSecurityConfig {
private final CustomAuthenticationManager customAuthenticationManager;
private final AuthTokenFilter authTokenFilter;
private final AuthEntryPoint authEntryPoint;
#Value("${api.prefix}")
private String apiPrefix;
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(null).and()
.authenticationManager(customAuthenticationManager)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(apiPrefix + "/auth/**").permitAll()
.antMatchers(apiPrefix + "/test/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling(
httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer
.authenticationEntryPoint(authEntryPoint)
);
http.addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
AuthTokenFilter.java
#Slf4j
#Component
#RequiredArgsConstructor
public class AuthTokenFilter extends OncePerRequestFilter {
private final JwtUtils jwtUtils;
private final UserDAO userDAO;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = parseJwt(request);
if (Objects.isNull(jwt)) {
throw new AuthenticationCredentialsNotFoundException("Unable to extract JWT token from authentication header");
}
try {
if (jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDAO.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken.authenticated(userDetails, null, new ArrayList<>()); // please check this line
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
} catch (AuthenticationException e) {
throw e;
} catch (Exception e) {
log.error("Cannot set user authentication: {}", e.getMessage(), e);
throw new CustomRTException("Error while validating jwt token", HttpStatus.UNAUTHORIZED);
}
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
}
CustomAuthenticationManager.java
#Slf4j
#Component
#RequiredArgsConstructor
public class CustomAuthenticationManager implements AuthenticationManager {
private final UserDAO userDAO;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UserDetails userDetails = userDAO.loadUserByUsername(authentication.getName());
if (passwordEncoder().matches(authentication.getCredentials().toString(), userDetails.getPassword())) {
throw new BadCredentialsException("Wrong Password");
}
return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword());
}
}
(If any other classes such as UserDAO or AuthEntryPoint is required, let me know. I just shared the classes that I thought were relevant since others were fairly straightforward)
One of the biggest issues that I had was, in AuthTokenFilter even after validating the JWT token, Spring tries to call CustomAuthenticationManager#authenticate again which caused a NullPointerException at this line
authentication.getCredentials().toString() // credentials is null because after parsing the JWT token, I am unable to get the password
This issue was fixed in this line
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken.authenticated(userDetails, null, new ArrayList<>());
(authorities is empty list as I am currently do not need to grant any)
This code was pieced together following some migration guides from the now deprecated WebSecurityConfigurerAdapter therefore I just want to make sure everything is correct.
my problem is that I get nothing in response after sending requests with wrong login credentials or when accessing the endpoint without authentication.
This is how it looks when I send a good request:
Good Response screen
And this is how it looks when the request body is invalid:
Invalid credentials request
MyUserDetails class:
public class MyUserDetailService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User("foo", "foo", List.of());
}
}
Security configure class:
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private MyUserDetailService myUserDetailService;
#Autowired
private JwtFilter jwtFilter;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailService);
}
#Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/auth").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().csrf().disable();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Jwt Filter class:
#Component
public class JwtFilter extends OncePerRequestFilter {
#Autowired
private JwtUtil jwtUtil;
#Autowired
private MyUserDetailService myUserDetailService;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
String username = null;
String requestToken = null;
if(authHeader != null && authHeader.startsWith("Bearer ")) {
requestToken = authHeader.substring(7);
username = jwtUtil.getUsernameFromToken(requestToken);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = myUserDetailService.loadUserByUsername(username);
if(jwtUtil.validateToken(requestToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request, response);
}
And finally my controller:
#PostMapping("/auth")
public AuthResponse auth(#RequestBody AuthRequest authRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
);
} catch (BadCredentialsException e) {
throw new Exception("Invalid Credentials", e);
}
final UserDetails userDetails = myUserDetailService.loadUserByUsername(authRequest.getUsername());
final String token = jwtUtil.generateToken(userDetails);
return new AuthResponse(token);
}
EDIT:
I forgot to paste dependancies.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.2.4'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
I also have AuthRequest and AuthResponse class which holds username, password, jwt token and all the constructors, getters and setters ( not worth to past it here imo)
You got to throw an exception while validating(following is what I use, just grab the concept, your classes and libraries might be different):
Jwts.parser().setSigningKey(your_jwt_secret).parseClaimsJws(token);
so if your token cannot get parsed throw this and send an error response:
httpServletResponse.setContentType("application/json");
httpServletResponse.getWriter().write("your_custom_error");
httpServletResponse.getWriter().flush();
I have a project which I had enabled jwt for authorization on it. The problem is that whenever I send an empty header request or expired authorization code in the header it doesn't send me the unauthorized error, it shows in the log that the token is not valid but allows the request to continue working. this is my configuration code:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private UserDetailsService jwtUserDetailsService;
#Autowired
private JwtRequestFilter jwtRequestFilter;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(BCryptVersion.$2Y);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate","/user","/swagger-ui.html","/swagger-ui/**"
,"/v3/api-docs/**").permitAll().
anyRequest().authenticated().and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
httpSecurity.logout().logoutSuccessUrl("/authenticate").logoutUrl("/logout").permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers(String.valueOf(HttpMethod.OPTIONS), "/**");
// ignore swagger
web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs");
}
}
and this is my jwt request filter:
#Component
public class JwtRequestFilter extends OncePerRequestFilter {
#Autowired
private JwtUserDetailsService jwtUserDetailsService;
private JwtTokenUtil jwtTokenUtil;
public JwtRequestFilter(JwtTokenUtil jwtTokenUtil) {
this.jwtTokenUtil = jwtTokenUtil;
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
}
else if (requestTokenHeader == null){
logger.info("Does not provide Authorization Header");
}
else if (!requestTokenHeader.startsWith("Bearer ")){
logger.warn("JWT Token does not begin with Bearer");
}
// Once we get the token validate it.
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
and finally here is JwtAuthenticationEntryPoint:
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -7858869558953243875L;
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
and this is the log that shows I did not send any token in header, but it allows the request:
any idea that what should I do?
for further information, I should say that this code was working but stopped working after a while and I didn't find any reason because I had no changes in these files for months.
The problem is the misconfiguration at this line
web.ignoring().mvcMatchers(String.valueOf(HttpMethod.OPTIONS), "/**");
It should be
web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**");
As you might have noticed now that your configuration is actually ignoring all request paths from Spring Security filters. That is the reason that all unauthorized requests (which you expect) are allowed now.
You are missing addFilterAfter and also update your code as below.
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate","/user","/swagger-ui.html","/swagger-ui/**"
,"/v3/api-docs/**").permitAll().
anyRequest().authenticated().and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class).logout().logoutSuccessUrl("/authenticate").logoutUrl("/logout").permitAll();
}
Please refer https://github.com/techiesantosh/taskmanager-service/blob/develop/src/main/java/com/web/taskmanager/config/TaskConfig.java
Getting 401 for "/register" endpoint even after defining it as permitAll in antMatcher.
I am new to spring security.
I have configured two endpoints "/login" and "/register". I want "/register" to be available public and there should be a username/password check on accessing "/login".
My server.servlet.context-path is set to "/todo/user".
I tried to search for the solution but nothing would explain why i am facing the issue or may be i wasnt able to comprehend it being new to this.
Controller class
#Controller
#RequestMapping(value = "/register")
public class RegistrationController {
#Autowired
UserService userService;
#RequestMapping(value = "", method = RequestMethod.POST,
produces = "application/json")
#ResponseBody
public ResponseEntity<String> registration(#RequestBody #Valid UserRegistration userRegistration) {
Optional<UserRegistration> user = Optional.ofNullable(userRegistration);
if(!user.isPresent()) {
throw new UserDataNotAvailableException("User data is not available");
}
//TO-DO Write implementation of isUserValid
Optional<Boolean> isRegistrationSuccess = user.map(userService::registerNewUser);
return new ResponseEntity<String>("This is temp", HttpStatus.OK);
}
}
SecurityConfig
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/register").permitAll()
.anyRequest().authenticated()
.and().addFilter(new
JwtAuthenticationFilter(authenticationManager()));
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
}
Authentication Filter
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static final int EXPIRATION_TIME = 3900;
private static final String HEADER_NAME = "auth";
private AuthenticationManager authenticationManager;
#Value("${jwt.secret}")
private String secret;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try{
UserLogin user = new ObjectMapper().readValue(request.getInputStream(), UserLogin.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmailId(), user.getPassword(),
new ArrayList<>()));
}catch (IOException e) {
throw new InternalServerException("There was a problem in processing the request");
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
String jwt = Jwts.builder().setSubject(((UserLogin)authResult.getPrincipal()).getEmailId())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.ES256, secret)
.compact();
response.addHeader(HEADER_NAME, jwt);
}
}
AS evident from security config class i have permitted all to access my "/register" endpoint.
But when i make a request on "/register" i get a 401.
This should not be the case and i should be able to access this particular endpoint without any JWT
I am having requirement where users of my application could be SSO users or non SSO users. Incase of SSO users he would not be redirected I would just pass him to page he requested for. (not authenticate) and while for Non SSO users I have to redirect to login page.
Hence I thought of writing my own custom AbstractAuthenticationProcessingFilter.
Here I would check if users is SSO users ( I check if there is a user id from in request header) if he is not SSO user then I would redirect him to login page else he will continue to page he accessed.
Custom AbstractAuthenticationProcessingFilter
public class UserTypeFilter extends AbstractAuthenticationProcessingFilter {
private static final String INTERCEPTOR_PROCESS_URL = "/index";
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
public UserTypeFilter() {
super(INTERCEPTOR_PROCESS_URL);
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String userId = request.getHeader("USERID");
try {
if (userId == null) {
throw new PreAuthenticatedCredentialsNotFoundException("EID param not found");
}
} catch (AuthenticationException e) {
unsuccessfulAuthentication(request, response, e);
}
/*if (userId == null) {
System.out.println(" THROWING EXCEPTION FILTER");
throw new PreAuthenticatedCredentialsNotFoundException("EID param not found");
}*/
PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(userId, "123456");
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
Authentication authResult = getAuthenticationManager().authenticate(authRequest);
return authResult;
}
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
SecurityContextHolder.clearContext();
if (logger.isDebugEnabled()) {
logger.debug("Authentication request failed: " + failed.toString());
logger.debug("Updated SecurityContextHolder to contain null Authentication");
// logger.debug("Delegating to authentication failure handler " +
// failureHandler);
}
String defaultFailureUrl = "/login";
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
}
}
My Security config
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login").anonymous().anyRequest().authenticated().and().formLogin().loginPage("/login")
.failureUrl("/login?error").usernameParameter("username").passwordParameter("password")
.and().logout().invalidateHttpSession(true).logoutUrl("/static/j_spring_security_logout")
.logoutSuccessUrl("/login?logout").and()
.exceptionHandling().accessDeniedPage("/403").and().csrf().and().addFilterBefore(new UserTypeFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Bean(name = "myAuthenticationManager")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public UserTypeFilter authenticationFilter() throws Exception {
UserTypeFilter authFilter = new UserTypeFilter();
authFilter.setAuthenticationManager(authenticationManager());
SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
handler.setDefaultFailureUrl("/login");
authFilter.setAuthenticationFailureHandler(handler);
return authFilter;
}
}
There are multiple problems/doubts that I have:
1) In case of Non SSO user i.e when userid is not present in header. Then as expected the redirection happens to login page. But is this way of redirection proper . Should I configure SimpleUrlAuthenticationFailureHandler?
3) Incase of SSO user my code where I am trying to create authenticate is throwing null pointer exception. I copied this code from an example online but i really don't know what to do there can someone help me with this?
2) I have configured my customfilter before UsernamePasswordAuthenticationFilter is this ok?
Is my approach of using customfilter right?