I am creating an API for an Angular 5 application. I would like to use JWT for authentication.
I would like to use the features that are provided by spring security so I
After a lot of searching and trying I think I have found the solution:
You need a bean of SecurityWebFilterChain that contains all configuration.
This is mine:
@Configuration
public class SecurityConfiguration {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private SecurityContextRepository securityContextRepository;
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
// Disable default security.
http.httpBasic().disable();
http.formLogin().disable();
http.csrf().disable();
http.logout().disable();
// Add custom security.
http.authenticationManager(this.authenticationManager);
http.securityContextRepository(this.securityContextRepository);
// Disable authentication for `/auth/**` routes.
http.authorizeExchange().pathMatchers("/auth/**").permitAll();
http.authorizeExchange().anyExchange().authenticated();
return http.build();
}
}
I've disabled httpBasic, formLogin, csrf and logout so I could make my custom authentication.
By setting the AuthenticationManager and SecurityContextRepository I overridden the default spring security configuration for checking if a user is authenticated/authorized for a request.
The authentication manager:
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager {
@Override
public Mono authenticate(Authentication authentication) {
// JwtAuthenticationToken is my custom token.
if (authentication instanceof JwtAuthenticationToken) {
authentication.setAuthenticated(true);
}
return Mono.just(authentication);
}
}
I am not fully sure where the authentication manager is for, but I think for doing the final authentication, so setting authentication.setAuthenticated(true); when everything is right.
SecurityContextRepository:
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
@Override
public Mono save(ServerWebExchange serverWebExchange, SecurityContext securityContext) {
// Don't know yet where this is for.
return null;
}
@Override
public Mono load(ServerWebExchange serverWebExchange) {
// JwtAuthenticationToken and GuestAuthenticationToken are custom Authentication tokens.
Authentication authentication = (/* check if authenticated based on headers in serverWebExchange */) ?
new JwtAuthenticationToken(...) :
new GuestAuthenticationToken();
return new SecurityContextImpl(authentication);
}
}
In the load I will check based on the headers in the serverWebExchange if the user is authenticated. I use https://github.com/jwtk/jjwt. I return a different kind of authentication token if the user is authenticated or not.