Security considerations

IBM® WebSphere® sMash implements system-level authentication and authorization. Applications can take advantage of WebSphere sMash security by defining security rules that determine which resources are protected, and how they are protected.

Types of authentication

WebSphere sMash provides implementations of the following types of authentication:

Basic authentication
Basic authentication is defined in RFC 2617.
Form-based authentication
The full-page form login that leverages external redirect.
Single sign-on authentication
The URL based login that leverages HTTP request attributes that include support for Security tokens such as LTPA.
OpenID authentication
OpenID consumer based authentication for third party authentication with an OpenID provider.
Programmatic login authentication
Provides an API-based authentication model.

Security rules

WebSphere sMash security leverages the user service that defines the users and groups referenced in the security rules. Security rules define protected resources. Resources that are not covered by any security rule are not protected. If multiple rules match a given resource, only the first rule defined determines how that resource is protected.

Each rule contains the following information:

conditions
Any supported conditions clause supported by the event handling subsystem. Common patterns will be based upon /request/path and /request/method values demonstrated later in this article.
authType
The type of authentication: Basic, Form or SSO.
users
An optional list of users, separated by commas, that are allowed to access these resources.
groups
An optional list of groups, separated by commas, that are allowed to access these resources.
roles
An optional list of roles, separated by commas, that are allowed to access these resources. Advanced
csrfProtect
An optional parameter to specify whether this protected resource can be exempted from CSRF protection. Advanced

The following example shows basic authentication configuration:

@include "security/rule.config"{
   "conditions": "(/request/path =~ /customers(/.*)?)  && (/request/method =~ (PUT|POST)) ",
   "authType" : "Basic",
   "users" : ["myUser1"],
   "groups" : ["CUSTOMERS"]
}

This rule protects all resources that match the URI pattern /customers(/.*)? and are accessed with the HTTP method of PUT or POST with basic authentication. In this example, users must be either the user named myUser1 or be a member of the CUSTOMERS group.

You can configure an optional realm to be used by basic authentication as shown in the following example:

/config/security/realm="Secure Area"

If no realm is set, the default realm is Secure Area.

Best practices for configuring security rules

The recommended URI pattern is /<prefix>(/.*)?. For example, a pattern of /foo(/.*)? would match requests for /foo, /foo/ and /foo/bar/index.html. Using this pattern that is based on prefixes, prevents clients from circumventing security rules by adding pathInfo to the end of a request. Also, because of the default file serving behavior when a directory is accessed, if you want the default files protected, you need to be sure to protect the directory. For example, if you don't want /foo/index.html served, you should be sure to protect /foo/. This is accomplished using the prefix-based rules.

Authorizing URIs

For certain types of applications, you can group resources according to who owns them or global to any authenticated users. Securing such applications 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. WebSphere sMash enables authorizing URIs with user names or 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 a Group named 'ALL_AUTHENTICATED_USERS'. For example, the following rule will permit any authenticated user to access the resource that starts with /formauth/customers.

@include "security/rule.config"{
   "conditions": "/request/path =~ /formauth/customers(/.*)?",
   "authType" : "Form",
   "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, we can limit write operations on our file sharing service as shown in the following example:

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

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, if we want our site administrator to be able to delete any shared file, we can update the rule as shown in the following example:

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

@include "security/rule.config"{
   "conditions": "(/request/path == /resources/shares/{remoteUser} ) &&  (/request/method == DELETE)",
   "authType" : "Basic",
   "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:

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

Retrieving user information

After WebSphere sMash has verified the credentials, they are available in the request context as Map at /request/subject. The Map contains the remote_user and groups keys as shown in the following examples in java, groovy and PHP:

// java snippet
String remoteUser = GlobalContext.zget(zero.core.context.GlobalContextURIs.Request.Subject.remoteUser);
java.util.List groupNames = GlobalContext.zget(Request.Subject.groups);
// groovy snippet
RemoteUser: <%=request.subject.remoteUser[] %>
Groups:  <%=request.subject.groups[] %>
<?php
// php snippet
$remoteUser = zget("/request/subject/remoteUser");
$groups = zget("/request/subject/groups");
?>

This information is only available when accessing protected resources. If you want to be able to use this information when accessing non-protected resources you can store it in the user's session.

Requiring SSL

To require HTTPS access to a resource, create a requireSSL=true rule. For example, the following rule protects the resource with basic authentication while also requiring the connection to be SSL:

@include "security/rule.config"{
   "conditions": "/request/path =~ /employees(/.*)?",
   "authType" : "Basic",
   "requireSSL" : true
}

The SSL requirement can be combined with requirements for authentication, authorization or both by adding the requireSSL=true line to any stanza. It can also be used where there are no other security requirements. For example, the same resource in the previous example can be designated as requiring SSL but not be protected as shown in the following example:

@include "security/requireSSL.config"{
   "conditions" : "/request/path =~/employees(/.*)?",
   "requireSSL": true
}

If a resource that requires SSL access is accessed without it, a 403 (Access Forbidden) status code is returned to the client.

Caching of secured resources

In an effort to limit the caching of secured resources on the client, WebSphere sMash security sets the Cache-Control header for all secured resources and their associated login forms (OpenID, Form-based Login, Single Sign-On) that are provided as part of the WebSphere sMash security model.

The default Cache-Control header value is "must-revalidate","max-age=0","private". To override this default setting, the following zero configuration is provided with the example demonstrating the default Cache-Control value.

# max-age/must-revalidate can be dropped if there are only 1.1 
# caches as it would improve cacheability
/config/security/cacheControl = ["must-revalidate","max-age=0","private"]

Custom security handlers that override the secure event or provide a custom security implementation for obtaining a user's credentials will need to handle the Cache-Control header themselves. To add this Cache-Control header programmatically, the following API is provided.

zero.core.security.TokenService.setCacheControlHeader();

Using roles

Use of roles is an advanced topic and 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 could provide access only to users where the users role consists of users from the groups developers, sysadmins, and testers.

To enable role based authentication requires the specification of roles to users or groups or both. For example, for development purposes, you could 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:

@include "developmentRoles.config"

#Authorization rules
@include "security/rule.config"{
   "conditions": "/request/path =~formauth/adminRoleOnly(/.*)?",
   "authType" : "Form",
   "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 in java, groovy and PHP filters users based on whether the user is part of a role:

// java snippet
List<String> roles = 
   GlobalContext.zget(zero.core.context.GlobalContextURIs.Request.Subject.roles);
boolean isUserInAdminRole = roles.contains("ADMIN");
// groovy snippet
boolean isUserInAdminRole = request.subject.roles[].contains("ADMIN");
<?php
// php snippet
$roles = zget("/request/subject/roles");
$isUserInAdminRole = in_array("ADMIN", $roles);
?>

Fine-granular control of Cross-Site Request Forgery protection

WebSphere sMash allows you to protect you against Cross-site request forgery, a powerful attack. Specification of csrfProtect gives you additional control over how the protection is handled. This is an advanced topic and should not be required for many applications. In most cases, it is sufficient (but necessary) to include the zero.acf package as a dependency to be protected against CSRF. See the CSRF Protection for more information.

Related articles

Version 1.0.0.3.25591