Extending security
IBM® WebSphere® sMash security leverages the flexible event-based system to make it easy to add your own security implementations. With this enhanced flexibility, you can implement your own request processing event handler for secure, authenticate and authorize events as well as registering preauthenticate handlers for security related tasks that do not fit neatly with the authenticate and authorize events.
For more information on the secure and authorize events, see the section on Request-processing events. The following sections of this article provide more information about how you can extend security:
Secure event processing
The following table summarizes the sub-events, in order, run by WebSphere sMash during security processing of the secure event:
| Event name | Description | Maximum number of handlers invoked | Precondition | Early termination criteria | Reaction to Exceptions |
|---|---|---|---|---|---|
| preauthenticate | Perform security related checks that should be fired prior to invoking the authenticate check, for instance requireSSL. | No limit | none | /request/status is set |
Return status code 500; skip to the log event |
| authenticate | This is a dual purpose event handler. The first purpose of this event handler is to process login credentials when necessary for authTypes such as Form and OpenID. The second purpose is to perform authentication check based on authType | 1 | /event/isAuthorized is not set to true in preauthenticate event |
/request/status is set |
Return status code 500; skip to the log event |
| authorize | Perform authorization checks | No limit | /event/isAuthorized is not set to true in preauthenticate event |
/event/isAuthorized is set to true |
Return status code 500; skip to the log event |
In the event where preauthenticate sets isAuthorized to false and there are no matching event handlers for the authenticate event, the security event processing considers the request to be unauthorized and sets the appropriate HTTP status code of 403. If isAuthorized is not set in the preauthenticate, the authorization event is fired as expected.
Defining a preauthentication handler
Complete the following steps to implement a handler for the preauthenticate event:- Implement a handler for the event name preauthenticate.
- Register the event name in the configuration file of your library or application as a handler for that event.
For example, you would implement a handler with the method onPreauthenticate and add the following stanza to the
configuration file:
/config/handlers += [{
"events" : "preauthenticate",
"handler" : "com.myimpl.RequireSSLHandler.class",
"conditions" : "/request/scheme != https"
}]
As the name implies, the example preauthenticate handler forbids http access to a resource based upon a set of conditions. The handler is registered with a condition based upon the request scheme. If the request scheme is considered forbidden, then the secure event will call this preauthenticate handler resulting in a HTTP Forbidden status code of 403 as shown in the following code example.
public void onPreauthenticate() {
GlobalContext.zput(Request.status, HttpURLConnection.HTTP_FORBIDDEN);
GlobalContext.zput(Request.view, "error");
ViewEngine.render();
}
For another variation of requiring SSL using the preauthenticate event handler please refer to the Requiring SSL section of the Developer's Guide.
Defining a custom authentication handler
Complete the following steps to implement authentication:- Implement a handler for the event name authenticate.
- Register the event name in the configuration file of your library or application as a handler for that event.
- Implement a handler for the event name retrieveCredentials.
- Register the event name in the configuration file of your library or application as a handler for that event.
For more information on how events are processed please refer to the Event processing section of the Developer's Guide.
For example, you would implement a handler with the method onAuthenticate and add the following stanza to the configuration file:
/config/handlers += [{
"events" : "authenticate",
"handler" : "com.myimpl.DigestSecurityHandler.class",
"conditions" : "/request/path =~ /(.*)?"
}]
Now that you have defined the authentication handler, the next step is define a handler that knows how to interpret digest authentication headers.
/config/handlers += [{
"events" : "retrieveCredentials",
"handler" : "com.myimpl.DigestUserInfoResolver.class",
"conditions" : "/request/path =~ /(.*)?",
}]
In the retrieveCredentials event, the handler is required to populate the event zone's userName and password values prior to exiting the event for later use by the security runtime as shown in the code snippet below.
GlobalContext.zput(Event.userName, user); GlobalContext.zput(Event.password, password);
The method by which users extend authentication was rewritten after WebSphere sMash 1.0 was released. If you were an early adopter for extending security, please refer to the Security migration section of the Developer's Guide. Currently, the previously documented way for extending authentication will continue to work but we suggest migrating to the latest method detailed above.
These events are fired by the global security handler after firing the preauthenticate event handlers. This allows you to use your handler with the standard security rules.
To make sure that CSRF credentials are added and to prevent certain attacks, consult the article Cross Site Request Forgery in the section regarding adding authentication mechanisms of the cross-site request forgery protection for some simple rules to follow.
Defining a custom authorization handler
To implement a custom authorization handler, create a handler with a method name of onAuthorize then define the appropriate application handler stanza. Note that whereas the authenticate event can only be associated with one handler, the authorization handler allows multiple handlers to be registered in addition to the default authorization handler that is provided as part of WebSphere sMash security. Depending on the rules that are matched for the request, one or more handlers could be run for the authorize event. Once a handler sets the value isAuthorized to true in the event zone, processing of additional handlers is terminated.
To guarantee security against cross-site request forgery attacks, it is crucial that you also follow some simple rules as outlined in the section on adding authorization mechanisms of the CSRF protection document
In the following example, the custom authorization handler checks to ensure that the custom event handler data myCustomSetOfRules matches ADMIN and is authorized to view this resource:
/config/handlers += [{
"events" : "authorize",
"handler" : "zero.core.security.auth.CustomAuthorizationHandler.class",
"conditions" : "/request/path =~ /formauth/subject(/.*)?",
"instanceData" : {
"myCustomSetOfRoles" : "ADMIN"
}
}]
Because there are no explicit definitions of user, group or role in the security constraint, the default authorization handler does not authorize this user.