I have two microservices i.e Gateway service and User service. Gateway service redirects the calls of login to user service. User service will generate jwt token with info like roles and permissions etc and append it to response header.
Now clients can call user service for user create. In the request jwt token is passed and gateway service validates the token and forwards the call to user service. As I need to check whether the logged in user has write access or not (based on @PreAuthorize) I need to read the JWT token again in user service and extract the roles and permissions.
Gateway service WebSecurity class configure method
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.headers().frameOptions().disable();
http.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user/signup").permitAll()
.antMatchers(HttpMethod.POST, "/user/signin").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new AuthenticationFilter(authenticationManager(), environment));
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
AuthenticationFilter.Class
public class AuthenticationFilter extends BasicAuthenticationFilter{
private final Environment environment;
public AuthenticationFilter(AuthenticationManager authenticationManager, Environment environment) {
super(authenticationManager);
this.environment = environment;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String authHeader = request.getHeader(environment.getProperty("auth.token.header.name"));
if (authHeader == null || !authHeader.startsWith("Bearer")) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String authHeader = request.getHeader(environment.getProperty("auth.token.header.name"));
//validate jwt token code
}
In the application.properties enable this so that jwt token info in the header is passed to user service from gateway.
zuul.routes.user-service.sensitive-headers=Cookie,Set-Cookie
User Service WebSecurity class configure method
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/**").hasIpAddress(environment.getProperty("api.gateway.ip"))
.and()
.addFilter(getAuthenticationFilter());
http.headers().frameOptions().disable();
}
private AuthenticationFilter getAuthenticationFilter() throws Exception{
AuthenticationFilter filter = new AuthenticationFilter(usersService, environment, authenticationManager());
filter.setFilterProcessesUrl("/signin");
return filter;
}
UserService AuthenticationFilter class
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationService userService;
private final Environment environment;
@Autowired
public AuthenticationFilter(AuthenticationService userService, Environment environment, AuthenticationManager authManager) {
this.userService = userService;
this.environment = environment;
super.setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
LoginRequestModel creds = new ObjectMapper().readValue(request.getInputStream(), LoginRequestModel.class);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(creds.getEmail(), creds.getPasssword(), new ArrayList<>())
);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
//generate jwt token code
}
}
Now how can I read the values of jwt token sent by gateway service and set to security context authentication. Do I need to write one more filter. Where that filter would come. That filter should not be executed for sign up or login. Any help would be appreciated.