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
@include "security/rule.config"{
"conditions": "(/request/path =~ /customers(/.*)?) && (/request/method =~ (PUT|POST)) ",
"authType" : "Basic",
"users" : ["myUser1"],
"groups" : ["CUSTOMERS"]
}
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"
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"
}
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 and groovy:
// java snippet String remoteUser = GlobalContext.zget(Request.Subject.remoteUser); java.util.List groupNames = GlobalContext.zget(Request.Subject.groups);
// groovy snippet RemoteUser: <%=request.subject.remoteUser[] %> Groups: <%=request.subject.groups[] %>
Requiring SSL
To require HTTPS access to a resource, create arequireSSL=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
}
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
}
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"]
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
When in production, you might want to enable the
The following example shows how to leverage roles for authorization:
After a user has successfully authenticated for the REST resource
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"]
productionRoles.config as shown in the following example:
# productionRoles.config /config/security/roles/ADMIN/groups=["ROOT"]
@include "developmentRoles.config"
#Authorization rules
@include "security/rule.config"{
"conditions": "/request/path =~formauth/adminRoleOnly(/.*)?",
"authType" : "Form",
"roles" : ["ADMIN"]
}
/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 and groovy filters users based on whether the user is part of a role:
// java snippet
boolean isUserInAdminRole =
GlobalContext.zget(Request.Subject.roles).contains("ADMIN");
// groovy snippet
boolean isUserInAdminRole = request.subject.roles[].contains("ADMIN");
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 Document for more information.
Related articles
- User Service (File, LDAP, Custom)
- Leveraging Trust Association Interceptors (TAI)
- Obfuscating passwords with XOREncoder
- Escaping active content with XMLEncoder