I have a use case in which I have to perform authorization part only. JWT token is getting generated by another service. My service will only consume that token which will have data in it's custom claim. In my spring boot application, I just want to verify that token if it's valid or not before allowing users to access any API. In all answers I can see one Authentication object is created from current Security context. Is there any way in spring in which I don't need to write so much unnecessary code in Custom Filter and just write the logic to parse JWT token and if it is valid, then allow user to API or else send unauthorized response?
Auth0 Java JWT provides few methods to verify JWT token. I want to validate and parse using code like below
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm).withIssuer(issuer).build();
DecodedJWT decoded = verifier.verify(token);
CodePudding user response:
If you want to work with spring security you have to work with those things (filters, authentication object, context, etc.). You have to set an Authentication to be able to access protected resources. It's not complicated at all, you don't have to write "useless" code but just tell spring security what you want to do.
In your case, you just have to provide a custom filter that matches your criterias.
We can imagine something like :
@Component
public class TokenAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) req;
// Here, I get the token from authorization header, change if you get it from anywhere else
String token = httpRequest.getHeader("Authorization");
// here i'm just doing a dummy check. if my token equals "mysupersecrettoken" the authentication is validated
// change this test by yours (using Auth0 etc.)
if ("mysupersecrettoken".equals(token)) {
// dummy authentication object. You can set a real username / credentials / role based on the claims of your token if you want to.
UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken("username", "credentials",
Arrays.asList(new SimpleGrantedAuthority("ROLE")));
SecurityContextHolder.getContext().setAuthentication(user);
}
// call next filters, if authentication is not valid, no authentication will be set so user will not be authenticated
chain.doFilter(req, res);
}
}
It's not the best way to work with spring security but it's a kind of "minimal" way to achieve your usecase. You'll probably need to set some security context too but it's not a big thing.
CodePudding user response:
Spring Security ships with out of the box support for JWT authentication, so you would not need to write any code aside from configuration. See OAuth 2.0 Resource Server JWT in the reference docs. You can enable it with the Spring Security DSL using:
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
Note that JWTs can be used outside of OAuth 2.0 with this support, though it may not be obvious at first that this is the case. You can check out the JWT Login sample to see how that is accomplished, but the main takeaway is that you need to provide an @Bean
of type JwtDecoder
that is created with a public key, such as:
@Bean
JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withPublicKey(this.key).build();
}
Also see this Tanzu Tuesday talk for a deep dive on this subject.