Advanced authorization

IBM® WebSphere® sMash provides advanced authorization support based on security roles and URIs. This topic explores configuration for roles as well as URI-based authorization rules.

Authorizing URIs

For certain types of applications, you can group resources according to who owns them or global to any authenticated users. Application security in this way can be hard because you might not know user names and groups in advance and, even if you did, they might be too numerous to track manually. To simplify more common authorization scenarios, you can enable URI authorization using user names, group names, or all authenticated users.

Authorizing URIs for all authenticated users

You can create authorization rules to allow any authenticated user to access a protected resource. To enable this function, WebSphere sMash provides the a ALL_AUTHENTICATED_USERS group. For example, the following rule permits any authenticated user to access the resource that starts with /formauth/customers.

## enable security for the application
@include "security/enableSecurity.config"

@include "security/formAuthentication.config"{
   "conditions": "/request/path =~ /formauth/customers(/.*)?"
}
@include "security/authorization.config"{
   "conditions": "/request/path =~ /formauth/customers(/.*)?",
   "groups" : ["ALL_AUTHENTICATED_USERS"]
}

Authorizing URIs with user names

You can authorize URIs with user names. As an example, a file sharing service might give every user a URI like /resources/shares/{user}, where anything that comes after {user} is part of the user's file share. Securing such a service, so that only the user can modify his shared resources, can be handled in WebSphere sMash by creating a relationship between the URI pattern and the list of authorized users. WebSphere sMash has a special configuration variable, remoteUser, that can be added to URI patterns to indicate that only the authenticated user, whose name matches the URI token, can perform certain operations. For example, you can limit write operations on your file sharing service as shown in the following example:

@include "security/basicAuthentication.config"{
   "conditions": "(/request/path =~ /resources/shares/{remoteUser}) && (/request/method =~ (PUT|POST|DELETE))"
}

With this rule in place, PUT, POST, and DELETE operations are only allowed if the value of {remoteUser} is equal to the name of the person who is making the request. If the resource in question is /resources/shares/joe/file1.txt, then only code acting on behalf of user joe can perform PUT operations on it.

Rules that use the {remoteUser} variable can allow access to other users as well. For example, to allow a site administrator to delete any shared file, update the rule as shown in the following example:

## enable security for the application
@include "security/enableSecurity.config"

@include "security/basicAuthentication.config"{
   "conditions": "(/request/path == /resources/shares/{remoteUser}) && (/request/method =~ (PUT|POST))"
}

@include "security/authorization.config"{
   "conditions": "(/request/path == /resources/shares/{remoteUser} ) &&  (/request/method =~ (PUT|POST))"
}

@include "security/basicAuthentication.config"{
   "conditions": "(/request/path == /resources/shares/{remoteUser} ) &&  (/request/method == DELETE)"
}

@include "security/authorization.config"{
   "conditions": "(/request/path == /resources/shares/{remoteUser} ) &&  (/request/method == DELETE)",
   "users": ["admin"]
}


Authorizing URIs with group names

Just as you can incorporate user names into your URIs to ease the configuration of user-owned resources, you can also include a group name for group-owned resources. All of the semantics of the Authorizing URIs with user names section can be applied to groups. To do this, replace {remoteUser} with {remoteGroup}, and your authorization rule must contain a groups property that contains the list of authorized groups, as shown in the following example:

## enable security for the application
@include "security/enableSecurity.config"

@include "security/basicAuthentication.config"{
   "conditions": "/request/path == /resources/calendars/{remoteGroup}",
}  
 
@include "security/authorization.config"{
   "conditions": "/request/path == /resources/calendars/{remoteGroup}",
    "groups": ["newyork-team", "raleigh-team", "chicago-team"]
}

Using roles

Using roles is an advanced topic and this feature should not be required for most applications. By including role based authorization, WebSphere sMash provides a method for developers to specify which roles can access specific resources. For example, you can provide access only to users for which the users role consists of users from the groups developers, sysadmins, and testers.

Enabling role based authentication requires the specification of roles to users or groups or both. For example, for development purposes, you can include the following lines in the application configuration:

# developmentRoles.config
/config/security/roles/ADMIN/users=["testUser"]

When in production, you might want to enable the productionRoles.config as shown in the following example:

# productionRoles.config
/config/security/roles/ADMIN/groups=["ROOT"]

The following example shows how to leverage roles for authorization:

## enable security for the application
@include "security/enableSecurity.config"

@include "developmentRoles.config"

@include "security/formAuthentication.config"{
   "conditions": "/request/path =~formauth/adminRoleOnly(/.*)?"
}
#Authorization rules
@include "security/authorization.config"{
   "conditions": "/request/path =~formauth/adminRoleOnly(/.*)?",
   "roles" : ["ADMIN"]
}

After a user has successfully authenticated for the REST resource /formauth/adminRoleOnly(/.*)?, the global context is updated to reflect not only the remote user (remoteUser) and groups for the current subject, but also the set of roles of which this user is a member. The following examples filter users based on whether the user is part of a role:

The following example shows the users filtered by role in Java coding:

// java snippet
List<String> roles = 
   GlobalContext.zget(zero.core.context.GlobalContextURIs.Request.Subject.roles);
boolean isUserInAdminRole = roles.contains("ADMIN");

The following example shows the users filtered by role in Groovy coding:

// groovy snippet
boolean isUserInAdminRole = request.subject.roles[].contains("ADMIN");

The following example shows the users filtered by role in PHP coding:

<?php
// php snippet
$roles = zget("/request/subject/roles");
$isUserInAdminRole = in_array("ADMIN", $roles);
?>

Version 1.1.31300