Showing posts with label Web Script. Show all posts
Showing posts with label Web Script. Show all posts

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.

Saturday, August 4, 2012

Beginner Thoughts on Alfresco Architecture

Originally posted on February 15th, 2011.

If you asked me three months ago if I enjoy developing to Alfresco’s repository and Share UI (specifically Enterprise 3.3.3), it would have been a frustrated “NO…” — Not frustration about WANTING to learn a new product, since that is always exciting and challenging, but frustration on not understanding the architecture, the BIG PICTURE, to know how to use the product.
I’m not going into any deep personal thoughts on Alfresco ECM architecture today; rather I am going to share my thoughts on working with the Alfresco repository and the Alfresco Share UI from a software developer’s standpoint that had (almost) no prior experience with Alfresco, or ECM platforms in general.
I am relatively new to Armedia, and went headfirst into learning Alfresco ECM. NOTE! It is generally a good idea to get a “crash-course” in a new product from a product expert before jumping headfirst into a new product, even if Alfresco has thorough documentation via their Wiki. My coworkers and I had the pleasure to have an “Alfresco Architecture Crash-Course” presentation shared with us from Dimy Jeannot who was working on another Armedia Alfresco project.
The high-level architecture is as seen below. Any numerous UI technology, frameworks, etc are represented by the presentation layer (Alfresco Share, jQuery, EXTJS, etc). The presentation layer can communicate with the Alfresco repository, or via Alfresco data web scripts (data layer).
High Level Alfresco Architecture


The more detailed Alfresco architecture is seen below; we use the Alfresco Share UI as our example here. Share, and any custom Share code you write, calls RESTful presentation and/or data web scripts. These web scripts, in turn, communicate directly with Java Core Services exposed by Alfresco (i.e. document, search, node), or any custom services you may need to add for your application, to communicate with the Alfresco Repository.

Never assume that Alfresco and Share are running on the same server host. For example, you should not hardcode localhost or any other hostname in your Share code. Instead, use Share’s proxy URL when invoking a data web script (i.e. from a Share ftl, use Alfresco.constants.PROXY_URI when invoking your data web script -> Alfresco.constants.PROXY_URI + “”).

Where should you store your web scripts? If you are concerned with data, store your web scripts in the data layer. When your data web scripts are deployed, they are stored at webapps\\WEB-INF\classes\alfresco\templates\webscripts, create custom packages for your application. Else you are concerned with presentation (such as from a Share dashlet), store your code in the presentation layer (it should then in turn call a data web script to get its data!). When your presentation web scripts are deployed, they are stored at webapps\\WEB-INF\classes\alfresco\site-webscripts, create custom packages for your application.

Detailed Alfresco Architecture

Looking back now and reading the Alfresco Wiki’s, the Alfresco architecture makes sense, I just needed guidance on putting the big picture together to start feeling comfortable with working with a new product. If you ask me do I enjoy developing with Alfresco now, I would say yes .