Sunday, July 2, 2017

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 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 to read books, then you may want to check Spring Security 3.1 By Robert Winch, Peter Mularien, a great book, 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 and must-read book on Spring Security.

By the way, if you are new to Spring framework then I also suggest you join a comprehensive and up-to-date course to learn Spring in depth. If you need recommendations, I highly suggest you take a look at Spring Framework 5: Beginner to Guru, one of the comprehensive and hands-on course to learn modern Spring. It' also most up-to-date and covers Spring 5. It's also very affordable and you can buy in just $10 on Udemy sales which happen every now and then. 



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

Mapping LDAP authorities into role based access Java spring security example1) 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)" than mapping that to APP_USER.

3) If you are authenticating against Active directory than provide your custom Authority mapper to ActiveDirectoryLdapAuthenticationProvider. After successful authentication, it will load all the groups for which authenticated user_id is a member of, 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()" />


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 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 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

As 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. 

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 box from Spring Security and you need to follow the above steps to map LDAP groups to granted authorities.

Further Reading
Spring Framework 5: Beginner to Guru
Spring Master Class - Beginner to Expert
Spring Security Fundamentals by Bryan Hassen
Learn Spring Security 4 Basic hands-on

Recommended Book:
Spring Security 3.1 By Robert Winch, Peter Mularien is one of the best and must-read book on Spring security, 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.


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.

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