Sunday, September 17, 2023

Role based Access control using Spring Security and MVC, Mapping LDAP Groups to Authorities for Authorization

Authentication and Authorization is an integral part of any Java enterprise or web application. Since most of the company uses LDAP Active directory for authentication, authorization, and Role-based access control (RBAC), it's good to know How to implement Role-based access control using Spring MVC and Spring Security. This is the second part of my articles on using Spring Security for authentication and authorization in Spring MVC based Java application. In the last part, we have learned about doing LDAP authentication against Windows active directory, and in this Spring Security tutorial, we will learn How to map LDAP groups to authorities for implementing Role-based access control or authorization.

If you are developing an application, whose access is controlled by adding a user to a particular LDAP group, then you need a mechanism to load those LDAP group after successful authentication. Spring Security uses GrantedAuthority class for holding all roles for a particular user. 

Based on these roles, a particular user can perform certain functionality in your application. For example, a read-only user can only see data, but a user with an ADMIN role can add or remove data from your application. 

After implementing Role-based access control, you are free of user management tasks, those will be taken care of by the respective team which manages LDAP groups and access, usually Windows support teams. 

In this article, we will all the steps required to map LDAP groups to granted authorities in Spring Security. If you love online courses, then you may want to checSpring Security Core: Beginner to Guru by John Tompson, a great course, which teaches all good features of Spring security including LDAP authentication and authorization in great detail. 

If you are developing a secure enterprise application in Java and considering spring-security, this is one of the best online course on Spring Security. 

And, if you are new to the Spring framework then I also suggest you join a comprehensive and up-to-date course to learn Spring in-depth like Spring Framework 6: Beginner to Guru, one of the comprehensive and hands-on courses to learn modern Spring from the same author. 


Steps to Map LDAP groups to Authorities for Role-based Access Control (RBAC)


1) Create an Application-specific Authority classes, usually an enum with values like APP_USER, APP_ADMIN

2) Create Authority Mapper which will Map LDAP groups to application-specific authority for example if the group in LDAP is "Application Access (Gn)" then mapping that to APP_USER.

3) If you are authenticating against the Active directory then provide your custom Authority mapper to ActiveDirectoryLdapAuthenticationProvider. After successful authentication, it will load all the groups for which authenticated user_id is a member, and map with application-specific authority.

4) Use application-specific authorities or roles as APP_USER or APP_ADMIN to secure your URL's by using

<intercept-url pattern="/secure/admin/**" access="hasRole('APP_ADMIN')"/>
 
<intercept-url pattern="/secure/user/**" access="hasRole('APP_USER')"/>
<intercept-url pattern="/secure/**" access="isAuthenticated()" />


If you want to learn more, I highly recommend you to check out Spring Security Core: Beginner to Guru course on Udemy by John Thompson on Spring security,  a great course even for experienced developers. It takes an application development approach to teach the basics of enterprise security, LDAP concepts, authentication, authorization, and several other spring security features with non-trivial examples.

Role based Access control using Spring Security and MVC, Mapping LDAP Groups to Authorities for Authorization




Java code for Mapping LDAP Groups to Authorities using Spring Security

Here is the Java code, required to map LDAP groups into granted authorities of Spring Security. We need one class, usually enum to create roles supported by our application, this must implement the GrantedAuthority interface, which is used to represent a role in Spring Security. Now we need a Mapper class to map LDAP groups into granted authorities, this class must implement the GrantedAuthoritiesMapper interface. 

We create an instance of this class using Spring and provide names of LDAP groups for mapping with a particular role. 

For example, if the application has two roles USER and ADMIN and LDAP group "Application User Access (Gn)" is for User and "Application Admin Access (Gn)" is for Admin, then this information is configured in Spring configuration file and this authority mapper is provided to LDAP authentication provider. 

Keeping the application role separate from LDAP groups allows you to cope up with any change in the LDAP group name, you just need to change your spring configuration file.



LDAPGrantedAuthoritiesMapper.java

import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
 
/**
 * LDAP Authorities mapper, Maps LDAP groups to APP_USER and APP_ADMIN
 */
public class LDAPGrantedAuthoritiesMapper implements GrantedAuthoritiesMapper {
    private final String APP_USER ="Ldap User Group";   //default user ldap group
    private final String APP_ADMIN ="Ldap Admin Group"; //default adming ldap group
 
    public ADGrantedAuthoritiesMapper(String userGroup, String adminGroup) {
        APP_USER = userGroup;
        APP_ADMIN = adminGroup;
 
    }
 
    public Collection  mapAuthorities(
            final Collection authorities) {
 
        Set roles = EnumSet.noneOf(LDAPAuthority.class); //empty EnumSet
 
        for (GrantedAuthority authority : authorities) {
            if (APP_USER.equals(authority.getAuthority())) {
                roles.add(LDAPAuthority.APP_USER);
            } else if (APP_ADMIN.equals(authority.getAuthority())) {
                roles.add(LDAPAuthority.APP_ADMIN);
            }
        }
        return roles;
    }
}

LDAPAuthority.java

import org.springframework.security.core.GrantedAuthority;
 
/**
 * Maps LDAP Group application roles
 */
public enum LDAPAuthority implements GrantedAuthority{
    APP_USER, APP_ADMIN; //roles used in application
   
    public String getAuthority() {
        return name();
    }
   
}

Spring Security Configuration for Role-based Access and Mapping LDAP groups

Mapping LDAP authorities into role based access Java spring security exampleAs stated above, the first configuration is creating an instance of LDAPGrantedAuthoritiesMapper and mapping LDAP groups to application roles, so that when a user is successfully authenticated and comes with all LDAP groups, he is member of, those groups are read and converted into corresponding roles. 

The second configuration is to provide this mapper to ActiveDirectoryLdapAuthenticationProvider, this is similar to our last example of LDAP authentication, except <beans:property name="authoritiesMapper" ref="ldapAuthoritiesMapper"/>, which is requite to map LDAP groups to granted authorities for role-based access control.



<beans:bean id="ldapAuthoritiesMapper" 
    class="com.abc.web.security.LDAPGrantedAuthoritiesMapper">
        <beans:constructor-arg value="Ldap User Group" />
        <beans:constructor-arg value="Ldap Admin Group" />
</beans:bean>   
 
<beans:bean id="LdapAuthProvider"  
class="org.springframework.security.ldap.authentication.ad.
                                  ActiveDirectoryLdapAuthenticationProvider">
        <beans:constructor-arg ref="domain" />
        <beans:constructor-arg ref="url" />
        <beans:property name="convertSubErrorCodesToExceptions" value="true"/>
        //LDAP authority mapper
        <beans:property name="authoritiesMapper" ref="ldapAuthoritiesMapper"/>   
        
        <beans:property name="useAuthenticationRequestCredentials" value="true"/>
</beans:bean
 
That's all you need to implement Role-based access control on your Spring MVC, Spring Security based Java web application. Like other features, LDAP authorization doesn't come out of the box from Spring Security and you need to follow the above steps to map LDAP groups to granted authorities.

Further Reading
Spring Security Core: Beginner to Guru
Spring Security Fundamentals by Bryan Hassen
Spring Framework 5: Beginner to Guru



Other Spring tutorials from Javarevisited Blog
  • Top 5 Courses to learn Spring in depth (courses)
  • Top 5 Spring Boot Features Java developer should know (features)
  • 15 Spring Boot Interview Questions with Answers (questions)
  • 10 Free Courses to learn Spring Boot for Beginners (free courses)
  • 21+ Spring MVC Interview Questions for Java developers (Questions)
  • Top 5 Courses to learn Microservices in Java (courses)
  • 5 Best Resources for Spring Certification (resources)
  • How to Crack Spring Certification for Java developers (certification)
  • 10 Advanced Spring Boot Courses for Java developers (courses)
  • How to get a ServletContext object in the Spring controller? (example)
  • Top 5 Courses to learn Spring Boot in-depth (courses)
  • How to change the port of tomcat in Spring boot (tutorial)
  • Top 5 Books to learn Spring Boot and Spring Cloud (books)
  • What is the default bean scope in the Spring MVC framework? (answer)
  • Top 5 Courses to learn Spring Cloud for Java developers (courses)

P.S. - If you are an experienced Java/JEE Program and want to learn Spring Security end-to-end, I recommend the Learn Spring Security course by Eugen Paraschiv, The definitive guide to secure your Java application. It's useful for both junior and experienced Java Web developers.

And, Lastly one question for you, what was the last Spring Framework or Spring Boot question which was asked to you your last interview? 

4 comments :

Unknown said...

The name of this article should be changed to 'Using Roles for Access Control in Spring' rather than what it is currently called. Role-Based Access Control refers to ANSI RBAC INCITS 359 which uses roles in concert with permissions - and sessions. Binding roles directly to pages as you have done here is actually an anti-pattern for policy enforcement. The policy enforcement point should use always bind to permissions and let the access control mechanism determine what roles are needed.

Manoj Panke said...

I am also beginer
i have one problem i e i want to give access to different user by folderwise
so how i can do this

Unknown said...

Understood how the roles are mapped to group names and how the authorities identified , now how these are roles linked security layer so that roles can be accessed to validate resources

Anuj Somvanshi said...

Have idea about USER PROVISINING in Spring SAML application ?

Post a Comment