Home > Net >  How does Spring Security hasRole with PreAuthorize works under the hood?
How does Spring Security hasRole with PreAuthorize works under the hood?

Time:12-26

I am building a rest API and set sessionCreationPolicy of HttpSecurity object as STATELESS in my SecurityFilterChain method.

Since I could not find how does hasRole() method works internally, I wanted to try to see database access per requests which needs authorization.

After modifying database config. file, I can test and see manual queries logged but still can not get a query log from my application "check if this user has that role etc.".

Here is overwritten doFilterInternal() method of AuthTokenFilter class, which we extend from OncePerRequestFilter.

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
    try {
        String jwt = parseJwt(request);
        if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
            String username = jwtUtils.getUserNameFromJwtToken(jwt);

            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null,
                    userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (Exception e) {
        logger.error("Cannot set user authentication: {}", e);
    }

    filterChain.doFilter(request, response);
}

Is it possible something similar to session storage is used by spring security for authorization purpose, which seems impossible from the way we build HttpSecurity.

CodePudding user response:

how does hasRole() method works internally

If that's the whole point of the question

The first thing to point out is that hasRole() is a part authorization mechanism (reminder: authorization is about what access permissions a specific user has). Authorization relies on the authentication, i.e. establishing the identity of the user. To put it simple, what you can do depends on who you're.

So firstly, Filter responsible for authenticating the user creates an instance of Athentication and populates it with information including granted authorizes (in the form either roles or authorities) from the data storage (Database, LDAP data store, and we have an option for testing purposes to store users in memory). Suppose that authentication succeeds, a fully authenticated Athentication (which returns true for isAthernticated() call) gets placed into the SecurityContext.

Then we can check if the user can access the target resource based on the security roles and information contained in the Athentication instance associated with this request.

If you wonder how hasRole() is implemented, here is the source code:

public final boolean hasRole(String role) {
    return hasAnyRole(role);
}

@Override
public final boolean hasAnyRole(String... roles) {
    return hasAnyAuthorityName(this.defaultRolePrefix, roles);
}

private boolean hasAnyAuthorityName(String prefix, String... roles) {
    Set<String> roleSet = getAuthoritySet();
    for (String role : roles) {
        String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
        if (roleSet.contains(defaultedRole)) {
            return true;
        }
    }
    return false;
}

Internally it delegates to hasAnyRole() which in turn calls hasAnyAuthorityName() (in order to use the same logic for roles or authorities). Which would prefix the given string with "ROLE_" (which a default prefix for roles) and check if the prefixed string is present in the set of authorities extracted from the Athentication.

So if you're storing your users in the database, authorities are being pull out from the DB at the stage of Authentication, not during Authorization, when hasRole() gets executed.

  • Related