Spring Security – Authentication

First you need to the spring-boot-starter-security in you pox.xml

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Configure Spring security using java. This configuration is for APIs.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
private CustomLogoutHandler customLogoutHandler;
@Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
@Autowired
private CustomAcccessDeniedHandler customAcccessDeniedHandler;
@Bean
public CustomLoginFilter customUsernamePassworAuthenticationFilter() throws Exception {
return new CustomLoginFilter(PathConstantUtil.LOGIN_URL,authenticationManagerBean());
}
@Bean
public CustomAuthenticationFilter customAuthenticationFilter() {
return new CustomAuthenticationFilter();
}
@Bean
public RegistrationBean jwtAuthFilterRegister(CustomAuthenticationFilter customAuthenticationFilter) {
FilterRegistrationBean<CustomAuthenticationFilter> registrationBean = new FilterRegistrationBean<CustomAuthenticationFilter>(
customAuthenticationFilter);
registrationBean.setEnabled(false);
return registrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// rest call rules
http
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers(PathConstantUtil.PING_URL).permitAll()
.antMatchers(PathConstantUtil.LOGIN_URL).permitAll()
.antMatchers(PathConstantUtil.SIGNUP_URL).permitAll()
.anyRequest().permitAll();
// logout
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher(PathConstantUtil.LOGOUT_URL))
.addLogoutHandler(customLogoutHandler)
.logoutSuccessHandler(customLogoutSuccessHandler);
// filter
http.addFilterBefore(customUsernamePassworAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
// stateless
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// handler access denied calls
http.exceptionHandling().accessDeniedHandler(customAcccessDeniedHandler);
}
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(customAuthenticationProvider);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(PathConstantUtil.SIGNUP_URL)
.antMatchers(PathConstantUtil.LOGIN_URL)
.antMatchers(PathConstantUtil.PING_URL)
.antMatchers(PathConstantUtil.AUTH_TOKEN_URL)
.antMatchers(PathConstantUtil.SWAGGER_DOC_URLS)
.antMatchers("/actuator/**");
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
return methodInvokingFactoryBean;
}
}
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomAuthenticationProvider customAuthenticationProvider; @Autowired private CustomLogoutHandler customLogoutHandler; @Autowired private CustomLogoutSuccessHandler customLogoutSuccessHandler; @Autowired private CustomAcccessDeniedHandler customAcccessDeniedHandler; @Bean public CustomLoginFilter customUsernamePassworAuthenticationFilter() throws Exception { return new CustomLoginFilter(PathConstantUtil.LOGIN_URL,authenticationManagerBean()); } @Bean public CustomAuthenticationFilter customAuthenticationFilter() { return new CustomAuthenticationFilter(); } @Bean public RegistrationBean jwtAuthFilterRegister(CustomAuthenticationFilter customAuthenticationFilter) { FilterRegistrationBean<CustomAuthenticationFilter> registrationBean = new FilterRegistrationBean<CustomAuthenticationFilter>( customAuthenticationFilter); registrationBean.setEnabled(false); return registrationBean; } @Override protected void configure(HttpSecurity http) throws Exception { // rest call rules http .cors().and().csrf().disable() .authorizeRequests() .antMatchers(PathConstantUtil.PING_URL).permitAll() .antMatchers(PathConstantUtil.LOGIN_URL).permitAll() .antMatchers(PathConstantUtil.SIGNUP_URL).permitAll() .anyRequest().permitAll(); // logout http.logout() .logoutRequestMatcher(new AntPathRequestMatcher(PathConstantUtil.LOGOUT_URL)) .addLogoutHandler(customLogoutHandler) .logoutSuccessHandler(customLogoutSuccessHandler); // filter http.addFilterBefore(customUsernamePassworAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); // stateless http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // handler access denied calls http.exceptionHandling().accessDeniedHandler(customAcccessDeniedHandler); } @Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { builder.authenticationProvider(customAuthenticationProvider); } @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers(PathConstantUtil.SIGNUP_URL) .antMatchers(PathConstantUtil.LOGIN_URL) .antMatchers(PathConstantUtil.PING_URL) .antMatchers(PathConstantUtil.AUTH_TOKEN_URL) .antMatchers(PathConstantUtil.SWAGGER_DOC_URLS) .antMatchers("/actuator/**"); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public BCryptPasswordEncoder passwordEncoder() { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); return encoder; } @Bean public MethodInvokingFactoryBean methodInvokingFactoryBean() { MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean(); methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class); methodInvokingFactoryBean.setTargetMethod("setStrategyName"); methodInvokingFactoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); return methodInvokingFactoryBean; } }
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private CustomAuthenticationProvider customAuthenticationProvider;
	
	@Autowired
	private CustomLogoutHandler customLogoutHandler;
	
	@Autowired
	private CustomLogoutSuccessHandler customLogoutSuccessHandler;
	
	@Autowired
	private CustomAcccessDeniedHandler customAcccessDeniedHandler;
	
	@Bean
	public CustomLoginFilter customUsernamePassworAuthenticationFilter() throws Exception {
		return new CustomLoginFilter(PathConstantUtil.LOGIN_URL,authenticationManagerBean());
	}
	
	@Bean
	public CustomAuthenticationFilter customAuthenticationFilter() {
		return new CustomAuthenticationFilter();
	}
	
	@Bean
	public RegistrationBean jwtAuthFilterRegister(CustomAuthenticationFilter customAuthenticationFilter) {
		FilterRegistrationBean<CustomAuthenticationFilter> registrationBean = new FilterRegistrationBean<CustomAuthenticationFilter>(
				customAuthenticationFilter);
		registrationBean.setEnabled(false);
		return registrationBean;
	}
	
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// rest call rules
		http
			.cors().and().csrf().disable()
			.authorizeRequests()
				.antMatchers(PathConstantUtil.PING_URL).permitAll()
				.antMatchers(PathConstantUtil.LOGIN_URL).permitAll()
				.antMatchers(PathConstantUtil.SIGNUP_URL).permitAll()
				.anyRequest().permitAll();
					
		// logout
		http.logout()
			.logoutRequestMatcher(new AntPathRequestMatcher(PathConstantUtil.LOGOUT_URL))
			.addLogoutHandler(customLogoutHandler)
			.logoutSuccessHandler(customLogoutSuccessHandler);
		
		// filter
		http.addFilterBefore(customUsernamePassworAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
		
		http.addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
		
		// stateless
		http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
		
		// handler access denied calls
		http.exceptionHandling().accessDeniedHandler(customAcccessDeniedHandler);
	}

	@Override
	protected void configure(AuthenticationManagerBuilder builder) throws Exception {
		builder.authenticationProvider(customAuthenticationProvider);
	}
	
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring()
			.antMatchers(PathConstantUtil.SIGNUP_URL)
			.antMatchers(PathConstantUtil.LOGIN_URL)
			.antMatchers(PathConstantUtil.PING_URL)
			.antMatchers(PathConstantUtil.AUTH_TOKEN_URL)
			.antMatchers(PathConstantUtil.SWAGGER_DOC_URLS)
			.antMatchers("/actuator/**");
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		return encoder;
	}

	@Bean
	public MethodInvokingFactoryBean methodInvokingFactoryBean() {
	    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
	    methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
	    methodInvokingFactoryBean.setTargetMethod("setStrategyName");
	    methodInvokingFactoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
	    return methodInvokingFactoryBean;
	}
	
}

Here we configure our AuthenticationManager, PasswordEncoder, and web security for http routes.

Configure your Authentication Provider

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private UserService userService;
/**
* Authenticate user by credentials
*
* @author fkaveinga
* @return Authentication
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
log.info("authenticate(...)");
String email = authentication.getPrincipal().toString();
String password = authentication.getCredentials().toString();
log.info("email: {}", email);
log.info("password: {}", password);
Map<String, String> details = (Map) authentication.getDetails();
log.debug("details: {}", ObjectUtils.toJson(details));
return loginWithPassword(email, password);
}
private Authentication loginWithPassword(String email, String password) {
log.info("loginWithPassword({})", email);
Optional<User> optUser = userService.findByEmail(email);
if (!optUser.isPresent()) {
log.info("user not found");
throw new UsernameNotFoundException("Username or password is invalid");
}
log.info("user found for {}", email);
User user = optUser.get();
log.info("user: {}", ObjectUtils.toJson(user));
if (user.getPassword() == null || !PasswordUtils.verify(password, user.getPassword())) {
log.info("login credentials not matched");
throw new BadCredentialsException("Username or password is invalid");
}
return new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), generateAuthorities(user.getRoles()));
}
/**
* Get Authorities for User
*
* @param user
* @return List<GrantedAuthority>
*/
private List<GrantedAuthority> generateAuthorities(Set<Role> roles) {
List<GrantedAuthority> authorities = new ArrayList<>();
if (roles.isEmpty()) {
throw new InsufficientAuthenticationException("No role");
} else {
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getAuthority().toUpperCase()));
}
}
return authorities;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
@Component public class CustomAuthenticationProvider implements AuthenticationProvider { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private UserService userService; /** * Authenticate user by credentials * * @author fkaveinga * @return Authentication */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { log.info("authenticate(...)"); String email = authentication.getPrincipal().toString(); String password = authentication.getCredentials().toString(); log.info("email: {}", email); log.info("password: {}", password); Map<String, String> details = (Map) authentication.getDetails(); log.debug("details: {}", ObjectUtils.toJson(details)); return loginWithPassword(email, password); } private Authentication loginWithPassword(String email, String password) { log.info("loginWithPassword({})", email); Optional<User> optUser = userService.findByEmail(email); if (!optUser.isPresent()) { log.info("user not found"); throw new UsernameNotFoundException("Username or password is invalid"); } log.info("user found for {}", email); User user = optUser.get(); log.info("user: {}", ObjectUtils.toJson(user)); if (user.getPassword() == null || !PasswordUtils.verify(password, user.getPassword())) { log.info("login credentials not matched"); throw new BadCredentialsException("Username or password is invalid"); } return new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), generateAuthorities(user.getRoles())); } /** * Get Authorities for User * * @param user * @return List<GrantedAuthority> */ private List<GrantedAuthority> generateAuthorities(Set<Role> roles) { List<GrantedAuthority> authorities = new ArrayList<>(); if (roles.isEmpty()) { throw new InsufficientAuthenticationException("No role"); } else { for (Role role : roles) { authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getAuthority().toUpperCase())); } } return authorities; } @Override public boolean supports(Class<?> authentication) { return authentication.equals(UsernamePasswordAuthenticationToken.class); } }
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private UserService userService;

	/**
	 * Authenticate user by credentials
	 * 
	 * @author fkaveinga
	 * @return Authentication
	 */
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		log.info("authenticate(...)");
		
		String email = authentication.getPrincipal().toString();
		String password = authentication.getCredentials().toString();
		
		log.info("email: {}", email);
		log.info("password: {}", password);
		
		Map<String, String> details = (Map) authentication.getDetails();
		log.debug("details: {}", ObjectUtils.toJson(details));
		
		return loginWithPassword(email, password);
	}

	private Authentication loginWithPassword(String email, String password) {
		log.info("loginWithPassword({})", email);
		Optional<User> optUser = userService.findByEmail(email);

		if (!optUser.isPresent()) {
			log.info("user not found");
			throw new UsernameNotFoundException("Username or password is invalid");
		}
		
		log.info("user found for {}", email);
		
		User user = optUser.get();
		
		log.info("user: {}", ObjectUtils.toJson(user));
		
		if (user.getPassword() == null || !PasswordUtils.verify(password, user.getPassword())) {
			log.info("login credentials not matched");
			throw new BadCredentialsException("Username or password is invalid");
		}

		return new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), generateAuthorities(user.getRoles()));
	}
	

	/**
	 * Get Authorities for User
	 * 
	 * @param user
	 * @return List<GrantedAuthority>
	 */
	private List<GrantedAuthority> generateAuthorities(Set<Role> roles) {
		List<GrantedAuthority> authorities = new ArrayList<>();

		if (roles.isEmpty()) {
			throw new InsufficientAuthenticationException("No role");
		} else {
			for (Role role : roles) {
				authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getAuthority().toUpperCase()));
			}
		}
		return authorities;
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return authentication.equals(UsernamePasswordAuthenticationToken.class);
	}

}

Configure your Login Filter to handle login

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class CustomLoginFilter extends AbstractAuthenticationProcessingFilter {
private Logger log = LoggerFactory.getLogger(this.getClass());
private Map<String,String> authenticationDetails = new HashMap<>();
@Autowired
private UserService userService;
public CustomLoginFilter(String loginUrl, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(loginUrl));
setAuthenticationManager(authManager);
}
/**
* Attemp Authentication process. Pass username and password to authentication provider
* @author fkaveinga
* @return Authentication
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String authorizationHeader = request.getHeader("authorization");
log.info("Login Authorization Header: {}",authorizationHeader);
if(authorizationHeader==null) {
throw new InsufficientAuthenticationException("Authorization Header is null");
}
String email = getUsername(authorizationHeader);
String password = getPassword(authorizationHeader);
log.debug("email: {}",email);
log.debug("password: {}",password);
if(email == null || email.isEmpty()) {
log.info("username is null");
throw new InsufficientAuthenticationException("Username is null");
}
if(password == null || password.isEmpty()) {
log.info("password is null");
throw new InsufficientAuthenticationException("Password is null");
}
authenticationDetails.put("test", "good");
return authenticateWithPassword(email, password);
}
private Authentication authenticateWithPassword(String email, String password) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(email, password);
usernamePasswordAuthenticationToken.setDetails(authenticationDetails);
return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
}
/**
* Write response when request was successful.
* @author fkaveinga
* @return HttpServletResponse
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
log.debug("successfulAuthentication(...)");
String clientIpAddress = HttpUtils.getRequestIP(request);
String clientUserAgent = HttpUtils.getRequestUserAgent(request);
String email = authResult.getPrincipal().toString();
User user = this.userService.getByEmail(email);
JwtPayload jwtpayload = new JwtPayload(user, RandomGeneratorUtils.getUuid());
jwtpayload.setDeviceId(clientUserAgent);
String jwtToken = JwtTokenUtils.generateToken(jwtpayload);
SessionDTO sessionDto = new SessionDTO();
sessionDto.setEmail(email);
sessionDto.setName(user.getName());
sessionDto.setUserUid(user.getUid());
sessionDto.setToken(jwtToken);
response.setStatus(HttpStatus.OK.value());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
ObjectUtils.getObjectMapper().writeValue(response.getWriter(),sessionDto);
}
/**
* Write response when request was unsuccessful.
* @author fkaveinga
* @return HttpServletResponse
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
log.debug("unsuccessfulAuthentication(...)");
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpStatus.BAD_REQUEST.value());
String message = failed.getLocalizedMessage();
log.debug("Error message: {}",message);
response.setStatus(HttpStatus.BAD_REQUEST.value());
ObjectNode result = ObjectUtils.getObjectNode();
result.put("status", "invalid email or password");
ObjectUtils.getObjectMapper().writeValue(response.getWriter(), result);
}
/**
* Parse token for username
* @param authorizationHeader
* @return String username
*/
private String getUsername(String authorizationHeader) {
log.debug("getUsername(..)");
String username = null;
try {
String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim();
//log.info("usernamePasswordToken: {}",usernamePasswordToken);
String rawToken = this.decodeBase64Token(usernamePasswordToken);
log.debug("rawToken: {}",rawToken);
username = StringUtils.substringBefore(rawToken, ":");
log.debug("username: {}",username);
return username;
} catch (Exception e) {
e.printStackTrace();
}
return username;
}
/**
* Parse token for password
* @param authorizationHeader
* @return String password
*/
private String getPassword(String authorizationHeader) {
log.debug("getPassword(..)");
String password = null;
try {
String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim();
String rawToken = this.decodeBase64Token(usernamePasswordToken);
log.debug("rawToken: {}",rawToken);
password = StringUtils.substringAfter(rawToken, ":");
log.debug("username: {}",password);
return password;
} catch (Exception e) {
e.printStackTrace();
}
return password;
}
/**
* Parse for access token
* @param authorizationHeader
* @return String access token
*/
private String getAccessToken(String authorizationHeader) {
log.debug("getAccessToken(..)");
String bearerToken = null;
try {
bearerToken = StringUtils.substringAfter(authorizationHeader, " ").trim();
log.info("bearerToken: {}",bearerToken);
} catch (Exception e) {
e.printStackTrace();
}
return bearerToken;
}
/**
* Decode authentication token
* @param usernamePasswordToken
* @return String
*/
private String decodeBase64Token(String usernamePasswordToken) {
byte[] decodedBytes = Base64.getDecoder().decode(usernamePasswordToken);
return new String(decodedBytes);
}
}
public class CustomLoginFilter extends AbstractAuthenticationProcessingFilter { private Logger log = LoggerFactory.getLogger(this.getClass()); private Map<String,String> authenticationDetails = new HashMap<>(); @Autowired private UserService userService; public CustomLoginFilter(String loginUrl, AuthenticationManager authManager) { super(new AntPathRequestMatcher(loginUrl)); setAuthenticationManager(authManager); } /** * Attemp Authentication process. Pass username and password to authentication provider * @author fkaveinga * @return Authentication */ @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { String authorizationHeader = request.getHeader("authorization"); log.info("Login Authorization Header: {}",authorizationHeader); if(authorizationHeader==null) { throw new InsufficientAuthenticationException("Authorization Header is null"); } String email = getUsername(authorizationHeader); String password = getPassword(authorizationHeader); log.debug("email: {}",email); log.debug("password: {}",password); if(email == null || email.isEmpty()) { log.info("username is null"); throw new InsufficientAuthenticationException("Username is null"); } if(password == null || password.isEmpty()) { log.info("password is null"); throw new InsufficientAuthenticationException("Password is null"); } authenticationDetails.put("test", "good"); return authenticateWithPassword(email, password); } private Authentication authenticateWithPassword(String email, String password) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(email, password); usernamePasswordAuthenticationToken.setDetails(authenticationDetails); return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken); } /** * Write response when request was successful. * @author fkaveinga * @return HttpServletResponse */ @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { log.debug("successfulAuthentication(...)"); String clientIpAddress = HttpUtils.getRequestIP(request); String clientUserAgent = HttpUtils.getRequestUserAgent(request); String email = authResult.getPrincipal().toString(); User user = this.userService.getByEmail(email); JwtPayload jwtpayload = new JwtPayload(user, RandomGeneratorUtils.getUuid()); jwtpayload.setDeviceId(clientUserAgent); String jwtToken = JwtTokenUtils.generateToken(jwtpayload); SessionDTO sessionDto = new SessionDTO(); sessionDto.setEmail(email); sessionDto.setName(user.getName()); sessionDto.setUserUid(user.getUid()); sessionDto.setToken(jwtToken); response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); ObjectUtils.getObjectMapper().writeValue(response.getWriter(),sessionDto); } /** * Write response when request was unsuccessful. * @author fkaveinga * @return HttpServletResponse */ @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { log.debug("unsuccessfulAuthentication(...)"); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setStatus(HttpStatus.BAD_REQUEST.value()); String message = failed.getLocalizedMessage(); log.debug("Error message: {}",message); response.setStatus(HttpStatus.BAD_REQUEST.value()); ObjectNode result = ObjectUtils.getObjectNode(); result.put("status", "invalid email or password"); ObjectUtils.getObjectMapper().writeValue(response.getWriter(), result); } /** * Parse token for username * @param authorizationHeader * @return String username */ private String getUsername(String authorizationHeader) { log.debug("getUsername(..)"); String username = null; try { String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim(); //log.info("usernamePasswordToken: {}",usernamePasswordToken); String rawToken = this.decodeBase64Token(usernamePasswordToken); log.debug("rawToken: {}",rawToken); username = StringUtils.substringBefore(rawToken, ":"); log.debug("username: {}",username); return username; } catch (Exception e) { e.printStackTrace(); } return username; } /** * Parse token for password * @param authorizationHeader * @return String password */ private String getPassword(String authorizationHeader) { log.debug("getPassword(..)"); String password = null; try { String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim(); String rawToken = this.decodeBase64Token(usernamePasswordToken); log.debug("rawToken: {}",rawToken); password = StringUtils.substringAfter(rawToken, ":"); log.debug("username: {}",password); return password; } catch (Exception e) { e.printStackTrace(); } return password; } /** * Parse for access token * @param authorizationHeader * @return String access token */ private String getAccessToken(String authorizationHeader) { log.debug("getAccessToken(..)"); String bearerToken = null; try { bearerToken = StringUtils.substringAfter(authorizationHeader, " ").trim(); log.info("bearerToken: {}",bearerToken); } catch (Exception e) { e.printStackTrace(); } return bearerToken; } /** * Decode authentication token * @param usernamePasswordToken * @return String */ private String decodeBase64Token(String usernamePasswordToken) { byte[] decodedBytes = Base64.getDecoder().decode(usernamePasswordToken); return new String(decodedBytes); } }
public class CustomLoginFilter extends AbstractAuthenticationProcessingFilter {

	private Logger log = LoggerFactory.getLogger(this.getClass());
	
	private Map<String,String> authenticationDetails = new HashMap<>();

	@Autowired
	private UserService userService;
	
	public CustomLoginFilter(String loginUrl, AuthenticationManager authManager) {
		super(new AntPathRequestMatcher(loginUrl));
		setAuthenticationManager(authManager);
	}

	
	/**
	 * Attemp Authentication process. Pass username and password to authentication provider
	 * @author fkaveinga
	 * @return Authentication
	 */
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException, IOException, ServletException {
		
		String authorizationHeader = request.getHeader("authorization");
		log.info("Login Authorization Header: {}",authorizationHeader);
		
		if(authorizationHeader==null) {
			throw new InsufficientAuthenticationException("Authorization Header is null");
		}
		
		String email = getUsername(authorizationHeader);
		String password = getPassword(authorizationHeader);
		log.debug("email: {}",email);
		log.debug("password: {}",password);
		
		if(email == null || email.isEmpty()) {
			log.info("username is null");
			throw new InsufficientAuthenticationException("Username is null");
		}
		
		if(password == null || password.isEmpty()) {
			log.info("password is null");
			throw new InsufficientAuthenticationException("Password is null");
		}
		
		authenticationDetails.put("test", "good");
		
		return authenticateWithPassword(email, password);
		
	}
	
	private Authentication authenticateWithPassword(String email, String password) {
		UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(email, password);
		usernamePasswordAuthenticationToken.setDetails(authenticationDetails);
		return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
	}
	

	/**
	 * Write response when request was successful.
	 * @author fkaveinga
	 * @return HttpServletResponse
	 */
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException, ServletException {
		log.debug("successfulAuthentication(...)");
		String clientIpAddress = HttpUtils.getRequestIP(request);
		String clientUserAgent = HttpUtils.getRequestUserAgent(request);
		
		String email = authResult.getPrincipal().toString();
		
		User user = this.userService.getByEmail(email);
		
		JwtPayload jwtpayload = new JwtPayload(user, RandomGeneratorUtils.getUuid());
		jwtpayload.setDeviceId(clientUserAgent);
		
		String jwtToken = JwtTokenUtils.generateToken(jwtpayload);
		
		SessionDTO sessionDto = new SessionDTO();
		sessionDto.setEmail(email);
		sessionDto.setName(user.getName());
		sessionDto.setUserUid(user.getUid());
		sessionDto.setToken(jwtToken);
		
		response.setStatus(HttpStatus.OK.value());
		response.setContentType(MediaType.APPLICATION_JSON_VALUE);
		
		ObjectUtils.getObjectMapper().writeValue(response.getWriter(),sessionDto);
	}

	/**
	 * Write response when request was unsuccessful.
	 * @author fkaveinga
	 * @return HttpServletResponse
	 */
	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException failed) throws IOException, ServletException {
		log.debug("unsuccessfulAuthentication(...)");
		
		response.setContentType(MediaType.APPLICATION_JSON_VALUE);
		response.setStatus(HttpStatus.BAD_REQUEST.value());
		
		String message = failed.getLocalizedMessage();
		log.debug("Error message: {}",message);

		response.setStatus(HttpStatus.BAD_REQUEST.value());
		
		ObjectNode result = ObjectUtils.getObjectNode();
		
		result.put("status", "invalid email or password");
		
		ObjectUtils.getObjectMapper().writeValue(response.getWriter(), result);
	}
	
	/**
	 * Parse token for username
	 * @param authorizationHeader
	 * @return String username
	 */
	private String getUsername(String authorizationHeader) {
		log.debug("getUsername(..)");
		String username = null;
		try {
			String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim();
			//log.info("usernamePasswordToken: {}",usernamePasswordToken);
			String rawToken = this.decodeBase64Token(usernamePasswordToken);
			log.debug("rawToken: {}",rawToken);
			username  = StringUtils.substringBefore(rawToken, ":");
			log.debug("username: {}",username);
			return username;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return username;
	}
	
	/**
	 * Parse token for password
	 * @param authorizationHeader
	 * @return String password
	 */
	private String getPassword(String authorizationHeader) {
		log.debug("getPassword(..)");
		String password = null;
		try {
			String usernamePasswordToken = StringUtils.substringAfter(authorizationHeader, " ").trim();

			String rawToken = this.decodeBase64Token(usernamePasswordToken);
			log.debug("rawToken: {}",rawToken);
			password  = StringUtils.substringAfter(rawToken, ":");
			log.debug("username: {}",password);
			return password;
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return password;
		
	}
	
	/**
	 * Parse for access token
	 * @param authorizationHeader
	 * @return String access token
	 */
	private String getAccessToken(String authorizationHeader) {
		log.debug("getAccessToken(..)");
		String bearerToken = null;
		try {
			bearerToken = StringUtils.substringAfter(authorizationHeader, " ").trim();
			log.info("bearerToken: {}",bearerToken);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bearerToken;
	}
	
	
	/**
	 * Decode authentication token
	 * @param usernamePasswordToken
	 * @return String
	 */
	private String decodeBase64Token(String usernamePasswordToken) {
		byte[] decodedBytes = Base64.getDecoder().decode(usernamePasswordToken);
		return new String(decodedBytes);
	}

}

Source code in Github




Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *