Last active
February 9, 2019 17:59
-
-
Save OmarElgabry/ac5b03adfbe2fac41c0d4c44dbbe5e0f to your computer and use it in GitHub Desktop.
JWT UsernameAndPassword Authentication Filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.eureka.auth.security; | |
| import java.io.IOException; | |
| import java.sql.Date; | |
| import java.util.Collections; | |
| import java.util.stream.Collectors; | |
| 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.core.GrantedAuthority; | |
| import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |
| import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |
| import com.eureka.auth.security.JwtConfig; | |
| import com.fasterxml.jackson.databind.ObjectMapper; | |
| import io.jsonwebtoken.Jwts; | |
| import io.jsonwebtoken.SignatureAlgorithm; | |
| public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { | |
| // We use auth manager to validate the user credentials | |
| private AuthenticationManager authManager; | |
| private final JwtConfig jwtConfig; | |
| public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager, JwtConfig jwtConfig) { | |
| this.authManager = authManager; | |
| this.jwtConfig = jwtConfig; | |
| // By default, UsernamePasswordAuthenticationFilter listens to "/login" path. | |
| // In our case, we use "/auth". So, we need to override the defaults. | |
| this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(jwtConfig.getUri(), "POST")); | |
| } | |
| @Override | |
| public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) | |
| throws AuthenticationException { | |
| try { | |
| // 1. Get credentials from request | |
| UserCredentials creds = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class); | |
| // 2. Create auth object (contains credentials) which will be used by auth manager | |
| UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( | |
| creds.getUsername(), creds.getPassword(), Collections.emptyList()); | |
| // 3. Authentication manager authenticate the user, and use UserDetialsServiceImpl::loadUserByUsername() method to load the user. | |
| return authManager.authenticate(authToken); | |
| } catch (IOException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| // Upon successful authentication, generate a token. | |
| // The 'auth' passed to successfulAuthentication() is the current authenticated user. | |
| @Override | |
| protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, | |
| Authentication auth) throws IOException, ServletException { | |
| Long now = System.currentTimeMillis(); | |
| String token = Jwts.builder() | |
| .setSubject(auth.getName()) | |
| // Convert to list of strings. | |
| // This is important because it affects the way we get them back in the Gateway. | |
| .claim("authorities", auth.getAuthorities().stream() | |
| .map(GrantedAuthority::getAuthority).collect(Collectors.toList())) | |
| .setIssuedAt(new Date(now)) | |
| .setExpiration(new Date(now + jwtConfig.getExpiration() * 1000)) // in milliseconds | |
| .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret().getBytes()) | |
| .compact(); | |
| // Add token to header | |
| response.addHeader(jwtConfig.getHeader(), jwtConfig.getPrefix() + token); | |
| } | |
| // A (temporary) class just to represent the user credentials | |
| private static class UserCredentials { | |
| private String username, password; | |
| // getters and setters ... | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment