Spring boot how make a user role managing with jwt
Solution 1
You need to store user roles inside JWT token as additional claims, extract them after token validation and pass as 'authorities' for principal:
Collection<? extends GrantedAuthority> authorities
= Arrays.asList(claims.get(AUTHORITIES_KEY).toString().split(",")).stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
User principal = new User(claims.getSubject(), "",
authorities);
UsernamePasswordAuthenticationToken t
= new UsernamePasswordAuthenticationToken(principal, "", authorities);
Solution 2
First need to add the roles inside the JWT. For that you can add as Claim in the JWT Generator class.
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
Set<String> Userroles = new HashSet<>();
User user = userRepository.findByUsername(userDetails.getUsername());
for(Role role:user.getRoles()){
Userroles.add(role.getName());
}
claims.put("Roles",Userroles.toArray());
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
In the user model class need to include the roles in Set or any other data structure.
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "USER_ROLES", joinColumns = {
@JoinColumn(name = "USER_ID") }, inverseJoinColumns = {
@JoinColumn(name = "ROLE_ID") })
private Set<Role> roles;
In the Repository need to have a method like below.
User findByUsername(String username);
Please check this Github Repo(https://github.com/Senthuran100/SpringBoot_JWT) for your reference.
Solution 3
you should add role into Token and for example you can refer following link:- http://www.svlada.com/jwt-token-authentication-with-spring-boot/
Marco Ferraioli
Hi, I’m Marco Ferraioli A.K.A. ParanoiaSystem. I’m 23 years old. I’m a student at UNISA (University of Salerno) and study computer science.
Updated on July 05, 2022Comments
-
Marco Ferraioli almost 2 years
I'm writing a RESTful api with spring boot. I'm using spring boot, jersey, mongo db, swagger, spring boot security and jwt.
I have written the models, the repositories for the requests to the DB. Now I have integrated the Security and jwt token.
Now I need to discretize the role of the users, because a user cant call a route that need an admin priviledges.
I have a route for login, it's return a token. This is the code of my SecurityConfig
... @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired UserRepository userRepository; @Override public void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable().authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/api/swagger.json").permitAll() .antMatchers(HttpMethod.POST, "/login").permitAll() .antMatchers("/api/*").authenticated() .and() .addFilterBefore(new JWTLoginFilter("/login", authenticationManager(), userRepository), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); } }
I written the JWTLoginFilter that return me the token when user makes login
... @Override public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException { Credential creds = new ObjectMapper().readValue(req.getInputStream(), Credential.class); User user = userRepository.login(creds); if (user == null) throw new BadCredentialsException(""); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword() ); return token; } ...
I want insert this on my endpoint class on method
@PreAuthorize("hasRole('ROLE_ADMIN')")
this is a part of an endpoint
.... @Component @Path("story") @Api(value = "Story", produces = "application/json") public class StoryEndpoint { private static final Logger LOGGER = LoggerFactory.getLogger(StoryEndpoint.class); @Autowired StoryRepository storyRepository; @GET @Path("/") @Produces(MediaType.APPLICATION_JSON) @PreAuthorize("hasRole('ROLE_ADMIN')") <--- I want insert here @ApiOperation(value = "Get All Story", response = Story.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "hello resource found"), @ApiResponse(code = 404, message = "Given admin user not found") }) public Response getAllStory(){ Iterable<Story> stories = storyRepository.findAll(); LOGGER.info("getAllStory"); return (stories!=null) ? Response.ok(stories).build() : Response.ok(ResponseErrorGenerator.generate(Response.Status.NOT_FOUND)).status(Response.Status.NOT_FOUND).build(); } ....
How I can make a mechanism for assign to user the role and how i can pass the role in token and discretize on route the role of user?