[14 July, 2016] There has been a few updates to this article related to the ISAM 9.0.1 release, adding some enhancements for OAuth. This includes enhancements to the session lifetime, and session logout, also some technical updates regarding the use of DSC.
ISAM has made it’s forth release of the year, with version 184.108.40.206 released at the end of June.
A list of new features has been assembled here in the knowledge center.
In this post, I want to talk more about this feature:
- OAuth authentication
WebSEAL can now create an authenticated session by using an OAuth token. See the documentation for the EAS here: Support for OAuth authorization decisions.
In particular about some of the capabilities this introduces to the WebSEAL environment for Native mobile applications.
Historical OAuth capabilities
In versions of ISAM prior to v220.127.116.11, OAuth passing through WebSEAL was validated via an EAS. This meant that all the authorization is handled by ISAM for Mobile (or TFIM in older deployments) and WebSEAL passed the request to the junctioned servers as an ‘unauthenticated’ but ‘authorized’ request. This created some interesting challenges around audit logging and didn’t allow for any authorization to be handled by WebSEAL based on ACLs or context based access using attributes that are related to the OAuth token set.
OAuth Authentication to WebSEAL
In 18.104.22.168, a new stanza has been introduced to the WebSEAL configuration file [oauth].
From version 9.0.1, the auto_config script will configure most of these settings (including OAuth-Auth Sessions, and session logout) by default
Note: If you have upgraded from an earlier version, you may not have all the options and descriptive text available so I’ve reproduced it below.
[oauth] # Enable authentication using Open Authorization (OAuth) mechanism. # One of <http, https, both, none> # # The OAuth authentication mechanism should be considered only as part of a # Mobile scenario, where a session can be established based on the Bearer # token in the Authorization Header. oauth-auth = https # The Provider ID of the default OAuth federation at TFIM. If a Provider ID # is not provided in the request using the fed-id-param option, this provider # ID will be used for OAuth requests. The Provider ID of a federation can be # found on the federation properties page. default-fed-id = http://localhost/sps/oauth/oauth20/ # The name of the request parameter that can be used to override the # default-fed-id option configured above. By deleting this configuration # option, you can enforce that the default fed id is always used. fed-id-param = FederationId # The name of the TFIM cluster which houses this OAuth service. There should # also be a corresponding [tfim-cluster:<cluster>] stanza which contains the # definition of the cluster. cluster-name = oauth-cluster # The name of the attribute within the RSTR response from TFIM whose value is # to be used as the user identity when creating the session credential. user-identity-attribute = username
There is also a new configuration option in the [oauth-eas] stanza, and this makes it easy to disable the old EAS when using the new OAuth authentication. This option means you can still use the ISAM configuration utility to enable WebSEAL for API protection, and then just switch to OAuth authentication and disable the EAS.
Note: It is not recommended to use both OAuth authentication AND the EAS at the same time. Only use one or the other.
# # The oauth-eas configuration stanza is used to configure the EAS which # communicates with TFIM to handle OAuth authorization. The EAS itself will # be invoked for a particular object if the effective POP for the object has # an attribute entitled "eas-trigger", with an associated value of # "trigger_oauth_eas". # [oauth-eas] # Should the EAS be enabled? eas-enabled = false
With these options configured, WebSEAL will now build a user credential for the user from the ‘username’ attribute (as defined by the ‘user-identity-attribute’) with the full user registry credential information. This will enable standard SSO to the backend junctions.
When simply presenting just the access token, WebSEAL will revalidate the access token on every access. There are two ways to avoid this:
- Use a client with a cookie jar, and catch the WebSEAL session cookie
- Configure OAuth-Auth Sessions using the steps below.
Here is a sample request showing the ISAM session cookie returned to the client:
$ curl -k -v -H "Authorization: bearer 1J0EA" https://webseal/resource.jsp * Trying 192.168.42.202... * Connected to webseal (192.168.42.202) port 443 (#0) * TLS 1.2 connection using TLS_RSA_WITH_AES_128_CBC_SHA * Server certificate: isam901 > GET /epac.jsp HTTP/1.1 > Host: webseal > User-Agent: curl/7.43.0 > Accept: */* > Authorization: bearer 1J0EA > < HTTP/1.1 200 OK < content-language: en-US < content-type: text/html; charset=UTF-8 < date: Thu, 14 Jul 2016 04:59:36 GMT < p3p: CP="NON CUR OTPi OUR NOR UNI" < transfer-encoding: chunked < x-global-transaction-id: 396435295 < cache-control: no-cache="set-cookie, set-cookie2" < expires: Thu, 01 Dec 1994 16:00:00 GMT < x-powered-by: Servlet/3.1 < session-timeout: 598 < x-backside-transport: OK OK < Set-Cookie: PD-S-SESSION-ID=1_2_1_mTk7l4ZSgDhLCE...tV0BdLxcgsuj; Path=/; Secure; HttpOnly <
Building an OAuth session from the token (Cookieless OAuth access)
For a cookieless client, a WebSEAL session can be keyed off the Access token to provide:
- Access token validation – just once in a session.
- Session activity keep alive.
If the access token is used in this way, the token lifetime may reduce its expiry time.
You can use the existing WebSEAL inactivity times for this, in combination with the session logout functionality. The session max lifetime is based on the expiry of the access token. Its possible to modify this max value dynamically in the OAuth Post Token mapping rule.
- WebSEAL Cookie Jar, Cookies can be withheld from the client using the managed cookie list.
- Session logout, killing the current access token and ending the session. [New in ISAM 9.0.1]
To enable this feature, there are two steps: first set “require-mpa” to no:
# Require Multiplexing Proxy Agent for HTTP Header Session Keys and # HTTP Header authentication tokens. # # The use of an HTTP header as a session identifier or as an authentication # token carries a measure of risk that the header can be spoofed or stolen. # It is strongly recommended that headers only be accepted when proxied # through an authenticated channel. A 'yes' setting means that HTTP headers # will not be valid session keys or authentication tokens unless received via # an MPA. Please see the WebSEAL Administration Guide for more details # regarding MPAs. require-mpa = no
And Define the key for the ISAM session to be the OAuth Authorization Handler:
[session-http-headers] #---------------------- # HTTPHEADER SESSION KEYS #---------------------- Authorization = https
OAuth Session Lifetime
The OAuth Session maximum lifetime is based on the access token’s response.
As per the ISAM 9.0.1 Whats New documentation:
OAuth Authentication session based on token lifetime
When OAuth Authentication is enabled, the WebSEAL configuration parameter session lifetime timeout, which is controlled by the timeout entry in the [session] stanza of the WebSEAL configuration file, is ignored. The session lifetime is set to the OAuth token expiry time.
This means that inactivity is important to consider, such that you may have an access token valid for 60 mins, but an inactivity of 10mins. If you would like to modify this dynamically, modify the OAuth response in the Post Token mapping rule to give the desired value.
(For example, you might set the token lifetime short in the API definition, but report a longer max lifetime value in the Post Token mapping rule to enable sessions that extend beyond life of a token based on activity.)
OAuth Session Logout
[New in ISAM 9.0.1] When the WebSEAL session expires due to inactivity, WebSEAL is configured to call the OAuth runtime and request that the access token is disabled from future validation. This is configured using the Backend server single sign off capability of WebSEAL:
#----------------------------- # BACK-END SERVER SINGLE SIGN-OFF #----------------------------- # When a user's session is terminated in WebSEAL, any sessions that may exist # on back-end application servers are not destroyed. When this item is # configured, WebSEAL will send a request to the configured URI's including # any configured headers and cookies for the junction point on which it resides # The backend application can use this information to terminate any sessions # for that user. # # Multiple URI's can be specified by including multiple single-signoff-uri # configuration entries. # # The configured URI must reside on a standard junction. For example: # single-signoff-uri = /app/logout.asp # # single-signoff-uri = single-signoff-uri = /mga/sps/oauth/oauth20/logout
This means an OAuth Session can also be effectively closed/ended by navigating to the standard WebSEAL /pkmslogout URL.
Distributed Session Cache
When using OAuth-Auth, it’s not currently possible to use the Distributed Session Cache. If your instance of WebSEAL DSC enabled the cookie returned in the request will override the Access token.
# Enable/disable use of the DSC. If this is set to yes the "dsess" stanza # must have information about how to communicate with the DSC. dsess-enabled = no
Adding OAuth attributes to the ISAM credential
Any attributes returned from the ISAM for Mobile OAuth mapping rule in the format of:
//Add a custom attribute to the ISAM users credential stsuu.addContextAttribute(new Attribute("custom_attribute", "urn:ibm:names:ITFIM:oauth:response:attribute", "some_value"));
will be added to the users credential.
Note: With the old EAS implementation, any attribute returned using the above format, would automatically be converted into a header and sent with the request down to the junction.
By default in the OAuth authentication process attributes are only sent down the junction in the encrypted ISAM credential (when configured to send iv-creds) to the junctioned server. In order to send them as a HTTP Header, see the steps detailed in the next two sections.
OK: Sending OAuth attributes as a header manually
In order to replicate the old behaviour of the EAS and send the OAuth response attributes from the mapping rule as headers in plain text, use a feature that has been in WebSEAL for a long time. HTTP Tag Values. HTTP Tag Values allow the user to access attributes from the credential and send the values as a HTTP Header.
Note: Take a special note of the requirement of the “tagvalue_” prefix in the linked Knowledge Center pages.
These are documented in the Knowledge Center here:
IBM Security Access Manager for Web > Configuring>Configuring Access Manager for Web > Configuring Web Reverse Proxy > Authentication > Credential processing > Extended attributes for credentials > Junction handling of extended credential attributes
Configuring a HTTP Tag Value can be done via pdadmin, or via the Web Portal Manager, this is configured on a per junction basis. For sending OAuth attributes with all requests, see the next section.
Better: Sending OAuth attributes as a header automatically
IBM Security Access Manager for Web 22.214.171.124 > Configuring > Configuring Access Manager for Web > Configuring Web Reverse Proxy > Authentication > Credential processing > Extended attributes for credentials > Junction handling of extended credential attributes > tagvalue_always extended attribute
//Add a custom attribute to the ISAM users credential stsuu.addContextAttribute(new Attribute("custom_attribute", "urn:ibm:names:ITFIM:oauth:response:attribute", "some_value")); stsuu.addContextAttribute(new Attribute("tagvalue_always", "urn:ibm:names:ITFIM:oauth:response:attribute", "custom_attribute"));
Using the WebSEAL tracing component pdweb.debug you can validate that the headers are supplied in the request:
----- trace.pdweb.debug:2 ----------------- PD ===> BackEnd GET /test/api/postpin/viewAccounts.jsp HTTP/1.1 connection: close host: host iv-user: testuser1 user-agent: Dalvik/1.6.0 (Linux; U; Android 4.2.2; sdk Build/JB_MR1.1) via: HTTP/1.1 isam:444 custom_attribute: some_value iv_server_name: wga-webseald-isam Cookie: PD_STATEFUL_5c7e53f6-b30b-11e3-8d6e-000c2931096b=%2Fmga ---------------------------------------------------
The EAS was configured to send the following attributes by default:
HEADER: username HEADERVALUE: testuser1 HEADER: access_token HEADERVALUE: xKOzCJaE9TWE96vAdcwb HEADER: oauth_token_client_id HEADERVALUE: ZtwIDmdJqlE3B7Ool9au HEADER: authorized HEADERVALUE: TRUE HEADER: scope HEADERVALUE: balance,phone HEADER: client_type HEADERVALUE: public HEADER: Expires HEADERVALUE: 2013-02-15T01:47:48Z
So the mapping rule configured to replicate this behavior would be the following:
stsuu.addContextAttribute(new Attribute("tagvalue_always", "urn:ibm:names:ITFIM:oauth:response:attribute", "username,access_token,oauth_token_client_id,authorized,scope,client_type,"+ "Expires"));
Such that the WebSEAL debug trace would appear as follows:
----- trace.pdweb.debug:2 ----------------- PD ===> BackEnd GET /test/api/postpin/viewAccounts.jsp HTTP/1.1 connection: close host: host iv-user: testuser1 user-agent: Dalvik/1.6.0 (Linux; U; Android 4.2.2; sdk Build/JB_MR1.1) via: HTTP/1.1 isam:444 username: testuser1 access_token: xKOzCJaE9TWE96vAdcwb oauth_token_client_id: ZtwIDmdJqlE3B7Ool9au authorized: TRUE scope: balance,phone client_type: public Expires: 2013-02-15T01:47:48Z iv_server_name: wga-webseald-isam Cookie: PD_STATEFUL_5c7e53f6-b30b-11e3-8d6e-000c2931096b=%2Fmga ---------------------------------------------------
This concludes the discussion on OAuth Authentication, to consider OAuth Authorization with WebSEAL, see my new article OAuth Authorization with ISAM.