ISAM Advanced Access Control has a mechanism that allows a developer to convert an authenticated/valid OAuth Access token, into an authenticated ISAM session, that is using a cookie.
There are two useful scenarios that this endpoint comes in handy:
- Hybrid Apps
Where an OAuth authenticated native application wants to open a WebView, that is authenticated using cookies. - Native App to Browser SSO
Where an app that has an authentication context with ISAM, wants to open the native browser on a mobile device, using a one time use Access Token.
Enable the ISAM Session Endpoint
There are three steps that are required to use the OAuth Session Endpoint.
- Enable the Advanced configuration parameter:
Find the parameter “oauth20.sessionEndpointEnabled” and set it to “true“.Enable the OAuth Session Endpoint - Add an EAI Trigger URL for the OAuth Session endpoint:
Set a trigger URL of: “/mga/sps/oauth/oauth20/session“.Enable the Session EAI Trigger URL - Allow Unauthenticated access to that URL to enable clients to login:
Using either the UI Policy Administration or the pdadmin command line.Attach an unauth ACL to the session URL.
Test the functionality using CURL
Using an OAuth implicit flow, I will login using a simple EAI to login. (It is an implementation of the JSP sample I have on: ISAM for Web without a User Registry)
curl -v -k -c cookiefile.txt https://192.168.42.200/EAIwar/eaiapp.jsp
Catch the authenticated cookie into our cookie file, and send it to our authorize endpoint for an access token.
curl -v -k -b cookiefile.txt "https://192.168.42.200/mga/sps/oauth/oauth20/authorize?client_id=browser&response_type=token&redirect_uri=https://www.ibm.com"
The response returns the access token in a 302 request.
> GET /mga/sps/oauth/oauth20/authorize?client_id=browser&response_type=token&redirect_uri=https://www.ibm.com HTTP/1.1
> Host: 192.168.42.200
> User-Agent: curl/7.43.0
> Accept: */*
> Cookie: JSESSIONID=0000KDihoJ-Bj49_Aqq1JNy2jOx:99f6131a-37b6-4ac9-bb90-4eb1539afdf1; PD-S-SESSION-ID=1_2_1_3Uxte-gMueIqDEZuEM5w6lm9DC-It0pUvLYXHWwnoRNLxfQt
>
< HTTP/1.1 302 Found
< content-language: en-US
< date: Mon, 13 Jun 2016 12:34:46 GMT
< location: https://www.ibm.com#access_token=wFoZluYrHwstCFWKAqWd&expires_in=3599&token_type=bearer&scope=
< p3p: CP="NON CUR OTPi OUR NOR UNI"
< transfer-encoding: chunked
< cache-control: no-store
< pragma: no-cache
If we extract that access token out of the request, we can now use it by POSTing it to the session endpoint.
curl -v -k --data "access_token=wFoZluYrHwstCFWKAqWd" https://192.168.42.200/mga/sps/oauth/oauth20/session > POST /mga/sps/oauth/oauth20/session HTTP/1.1 > Host: 192.168.42.200 > User-Agent: curl/7.43.0 > Accept: */* > Content-Length: 33 > Content-Type: application/x-www-form-urlencoded
All going to plan, we should get the HTML page for “Your login was successful” and a Set Cookie request for the ISAM Reverse Proxy session cookie.
< HTTP/1.1 200 OK
< content-type: text/html
< date: Mon, 13 Jun 2016 12:37:28 GMT
< p3p: CP="NON CUR OTPi OUR NOR UNI"
< server: WebSEAL/9.0.1.0
< x-old-content-length: 8015
< transfer-encoding: chunked
< cache-control: no-cache
< pragma: no-cache
< Set-Cookie: JSESSIONID=0000JkxVDM6vWi_WyLSIMLUDBSH:99f6131a-37b6-4ac9-bb90-4eb1539afdf1; Path=/mga/; HttpOnly
< Set-Cookie: PD_STATEFUL_02954abc-3161-11e6-a142-000c29e29751=%2Fmga; Path=/
< Set-Cookie: PD-S-SESSION-ID=1_2_1_9ICev86euCnnl7TfdvWgda58dA1zj9El9YYSZOpvcRPjsZT6; Path=/; Secure; HttpOnly
We now have an authenticated session from our OAuth access token.
Enrich the credential in the OAuth generated Session
Since our OAuth session may have been generated from a scoped OAuth token, its possible for us to add additional attributes into our ISAM session credential using our OAuth mapping rules.
The first thing you need to know, is we have a special “Request Type” of “session” when going through the mapping rule.
This is also identified by turning up the OAuth tracing, I could find the useful debug statements:
commands.GetFlowGrantInfoCmd > execute ENTRY commands.GetFlowGrantInfoCmd > getRequestTypeFromSTSUU ENTRY commands.GetFlowGrantInfoCmd < getRequestTypeFromSTSUU RETURN session commands.GetFlowGrantInfoCmd > getGrantTypeFromSTSUU ENTRY commands.GetFlowGrantInfoCmd < getGrantTypeFromSTSUU RETURN null commands.GetFlowGrantInfoCmd > getResponseTypeFromSTSUU ENTRY commands.GetFlowGrantInfoCmd < getResponseTypeFromSTSUU RETURN null commands.GetFlowGrantInfoCmd 3 execute OAUTH20 Flow: Request Type=session Grant Type=null ResponseType=null
If we want to return an additional credential attribute (or override the defaults), we can identify the flow in the mapping rule, and add some STSUU attributes in the response.
Here is a simple OAuth Post Token Mapping Rule.
importPackage(Packages.com.tivoli.am.fim.trustserver.sts); importPackage(Packages.com.tivoli.am.fim.trustserver.sts.uuser); //Simple Session Endpoint Credential enrichment importClass(Packages.com.tivoli.am.fim.trustserver.sts.uuser.Attribute); var request_type = null; var temp_attr = null; // The request type - if none available assume 'resource' temp_attr = stsuu.getContextAttributes() .getAttributeValuesByNameAndType("request_type", "urn:ibm:names:ITFIM:oauth:request"); if (temp_attr != null && temp_attr.length > 0) { request_type = temp_attr[0]; } else { request_type = "resource"; } if (request_type == "session") { var stsuuAttrs = stsuu.getAttributeContainer(); /* Add attribute "authenticatedBy" * with value "OAuth Session Endpoint" * to the current user credential. */ stsuuAttrs.setAttribute(new Attribute("authenticatedBy", null, "OAuth Session Endpoint")); /* Note: This is an example of setting the authentication level * for the established session. This is a different attribute * attribute than that which is used to do the same with * OAuth-Auth as a resource request. * When setting an Auth level, make sure you've configured * WebSEAL to be aware of the existence of the level. */ stsuuAttrs.setAttribute(new Attribute("AUTHENTICATION_LEVEL", "urn:ibm:names:ITFIM:5.1:accessmanager", "2")); /* To set the EAI Redirect Header use the following: * To ensure it takes priority, set the Webseal Flag: * eai-redir-url-priority=yes */ var redir = new Attribute("itfim_override_targeturl_attr", "urn:ibm:names:ITFIM:5.1:accessmanager", "/somepage.jsp"); stsuu.addAttribute(redir); }
This will return the extended attribute “authenticatedBy” with the value “OAuth Session Endpoint”, overrides the Authentication level – setting it to 2 instead of the default 1, and it will redirect the browser to the page “somepage.jsp” after login.
For a more complete version of the Post Token Mapping rule, with many more plug points documented, see: ISAM OAuth Token Mapping Rules – Beginners Guide
If you disable the EAI trigger URL, you can check that your values are being returned with the same CURL commands as above.
< HTTP/1.1 200 OK < content-language: en-US < content-type: text/html < date: Mon, 13 Jun 2016 12:53:53 GMT < p3p: CP="NON CUR OTPi OUR NOR UNI" < server: IBM Security Access Manager < transfer-encoding: chunked < am-eai-ext-user-id: emily < am-eai-redir-url: /somepage.jsp < cache-control: no-cache, no-store < expires: Thu, 01 Dec 1994 16:00:00 GMT < authenticatedby: OAuth Session Endpoint < am-eai-xattrs: authenticatedBy,AUTHENTICATION_LEVEL < authentication_level: 2 < pragma: no-cache
Notes:
- Be sure to re-enable the trigger URL when you’re confident the extended attributes are being set in the session endpoint response.
- If you are changing the authentication level, be sure to declare the authentication level available in the Reverse Proxy configuration.
- The headers above may not show extended attributes if you have configured your Point of Contact mechanism to return a Credential
Point of Contact Configuration - The Access Token used to perform the session creation can be configured to be single use only.
The easiest way to do this, is to use a custom API definition, and select the “Enforce single-use authorization grant” checkbox.Single Use Grant - Since this endpoint requires the HTTP operation to be POST, it might be difficult to use this in a Browser SSO flow. Since its only possible to use a Browser Intent to perform a GET request, we can get creative with an ISAM HTTP Transformation Rule, and modify the request midstream. I hope to share an example of this in another post. Stay Tuned.
Exactly answers what I’ve been searching for, for quite some time now. Thanks for sharing!
LikeLike