#Spring Security

24 messages · Page 1 of 1 (latest)

tawny hedge
#

I'm doing a small app using Spring Boot 2, Spring Security, and Vue 3. Currently I only have some endpoints for login, register new user, and get a list of tasks assigned to each user. I am using Postman to test my endspoints. I can perform login without a problem, it generates me a JWT. When I try to use that token to get the list of tasks for an user, I get 403 Forbidden. ``` @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/").permitAll() // Allow public access to authentication endpoints
// .antMatchers("/login").permitAll()
.antMatchers("/api/user-tasks/
").hasRole("ADMIN") // Restricted to admin role
.antMatchers("/api/tasks/**").hasAnyRole("BASIC_USER", "ADMIN") // Access for logged in users
.anyRequest().authenticated();

    // Add JWT filter
    httpSecurity.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}  ```  This is the configure method in my ``` @Configuration

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter``` class . I don't get any errors, I do not understand what is happening, I am very new to Java/Spring Boot but not to programming.

torpid crystalBOT
#

This post has been reserved for your question.

Hey @tawny hedge! Please use /close or the Close Post button above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

mystic token
#

Could you show us the JWT token?
(Or at least, the part that contains the roles)

Also, try settings the security logs to a lower level, so they might gives better hints.

in the application.yml

logging:
  level:
    org:
      springframework:
        security: debug

or if you're using the application.properties, it should be

logging.level.org.springframework.security=debug
tawny hedge
#

Here's a JWT token just generated by a login. eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJOZXdVc2VyMSIsImV4cCI6MTY5MjU0NzQ1MCwidXNlcklkIjoyLCJpYXQiOjE2OTI1NDM4NTAsInVzZXJuYW1lIjoiTmV3VXNlcjEifQ.ZGQDMdby6Dh62L0wk-UQ0uhDdgDBB_hzB9mMkITPOBA

mystic token
#

Mmm, there are no roles in your JWT token:

#

But here, you're telling spring, that to be able to call these endpoints, the caller must have the 'ADMIN' role:

.antMatchers("/api/user-tasks/**").hasRole("ADMIN") // Restricted to admin role

#

Am I missing something here?
Because a 403 forbidden, is exactly what I would expect 🙂

tawny hedge
#

okay makes sense. I'll try to first include the role in the jwt token

#

thank you

torpid crystalBOT
# tawny hedge thank you

If you are finished with your post, please close it.
If you are not, please ignore this message.
Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.

tawny hedge
#

I'll write back if it doesn't work

mystic token
#

You're welcome.

P.S.
I always get confused, but I'm pretty sure that for spring to correctly "understand" a Role, in the JWT you have to prepend the prefix ROLE_

For example, in your code, you said that .hasRole("ADMIN") is required.

This is fine, but probably only in the JWT you'll have to put ROLE_ADMIN instead of just ADMIN 👍

tawny hedge
#

THX!

mystic token
#

I guess it worked 😁

tawny hedge
#
        UserPrincipal userPrincipal = (UserPrincipal) userDetails;
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userPrincipal.getId()); // Add userId to claims
        claims.put("username", userDetails.getUsername()); // Add username to claims
        claims.put("role", userPrincipal.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toList()));
    
        return createToken(claims, userDetails.getUsername());
    }```   ``` public Set<String> getUserRolesFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(token)
                .getBody();
    
        return claims.get("role", List.class).stream()
                .map(Object::toString)
                .collect(Collectors.toSet());
    }``` the return claims.get("role", List.class).stream()
                .map(Object::toString)
                .collect(Collectors.toSet()); complains The method get(String, Class<List>) from the type Claims refers to the missing type List
#

I've changed it to this List<String> rolesClaim = claims.get("role", List.class);
return new HashSet<>(rolesClaim); and got rid of the error.

#

Now I get 401. Where should I prefix ROLE_?

mystic token
#

wait, 401 is not good. Something is failing during authentication now

#

I'm trying to understand the code, but I'm not that much familiar, since I rarely write my own JWT token.

Anyway, the first thing I would do, would be to revert to the code that gave you the 403, and go back from there

#
 claims.put("role", userPrincipal.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toList()));

This piece of code, is getting the authorities from the userPrincipal, to write them into the JWT token?
Does your userPrincipal has authorities?

And, when you decode the JWT token, can you read the roles inside of it?

tawny hedge
#

I think I lack a proper understanding of how to do this in spring security. I have now seen a github repo of a basic app, and the code seems very different from mine. I will come back, but for now I'll close the thread. Thank you very much, with your help I understood what I did wrong in the first place, missing the role in jwt

torpid crystalBOT
torpid crystalBOT