Sunday, December 23, 2012

Active Directory Role Based Access within an Alfresco Web Script


The Alfresco project I work on uses LDAP for authentication against Active Directory (AD), users and groups are synched from AD, with Kerberos protocol for Single Sign On (SSO); Alfresco runs on Apache Tomcat.  I won’t go into detail on how to configure this, my focus today is retrieving a SSO logged-in user’s AD groups to determine role based access within an Alfresco Web Script in order to access the web script’s functionality.

First, you’ll need to determine which AD Groups and Users will by synched with Alfresco.  This will be configured via Alfresco’s Authentication Subsystem.

Second, determine which AD groups will have access to this functionality, i.e. “AllBloggersGroup and SomeGroup”.  Make sure the user that you want access to this web script belongs to this group, i.e. “cherryshoe” belongs to group “AllBloggersGroup”.

Third, inject Alfresco’s Authentication Service Spring Bean into the service, and define the allowed roles.
<bean id="com.blogspot.cherryshoe.ExampleService"
class="com.blogspot.cherryshoe.ExampleService"
parent="webscript">
    <property name="authenticationService" ref="AuthenticationService"/>        
    <property name="allowedRoles" value="AllBloggersGroup,SomeGroup"/>
</bean>

Fourth, you’ll need to run authorityService.getAuthoritiesForUser as an admin user, since calling it requires admin credentials.  This article helped me solve the problem of insufficient permissions (running your code as a different user with alfresco blog).

private AuthenticationService authenticationService;
    
// holds the allowed roles
private String allowedRoles;
private List<String> allowedRoleList;

public void setAuthenticationService(AuthenticationService authenticationService) {
    this.authenticationService = authenticationService;
}

public void setAllowedRoles(String allowedRoles) {
    this.allowedRoles = allowedRoles;

    // set up value of allowedRoleList, get rid of any whitespace
    allowedRoleList = Arrays.asList(allowedRoles.split("\\s*,\\s*"));
}

public boolean isUserAuthorized(final String userName) {
    // someFunctionStart
    Set<String> authorizedAuthRoleSet = org.alfresco.repo.security.authentication.AuthenticationUtil
            .runAs(new org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork<Set<String>>() {
                @Override
                public Set<String> doWork() throws Exception {
                    // executes the following lines as admin user
                    Set<String> auths = authorityService
                            .getAuthoritiesForUser(userName);
                    return auths;
                }
            }, "admin");

    boolean isUserRoleAuthorized = false;

    for (String currAuthRole : authorizedAuthRoleSet) {
        for (String currRole : allowedRoleList) {
            if (currAuthRole.contains(currRole)) {
                isUserRoleAuthorized = true;
                break;
            }
        }
        if (isUserRoleAuthorized)
            break;
    }

    return isUserRoleAuthorized;
    // someFunctionEnd
}

NOTE:  Make sure that the LDAP synchronization occurs without any errors, or the call to getAuthoritiesForUser won’t work.  My current theory for this is because all users / groups synched cannot have any errors, or the call won’t work for any specific user.

Lastly, invoke the web service using an already authenticated user using Internet Explorer 9 web client using Kerberos for Single Sign On (adding Alfresco as trusted domain).  The web script is invoked without passing alf_ticket (since authentication is automatically passed for you using SSO) and using  /alfresco/wcservice in the base web URL (versus /alfresco/service).
i.e.  If user “cherryshoe” is already logged into Alfresco with IE 9 web client, then invoke URL http://127.0.0.1:8080/alfresco/wcservice/com/blogspot/cherryshoe/exampleService to use cherryshoe’s user credentials.

No comments:

Post a Comment

I appreciate your time in leaving a comment!