Some details:
Credits to Peter Volckaert and https://philipnye.com . Most of what I did was copy pasting things together.
Disclaimer:This was done as part of a PoC and is not running in production. Several improvements might be possible, such as encryption of the password in idmappingextcache. Note that the GSO service provides obfuscation out of the box, but therefore you'd need to use both PUT and GET of that service. In this implementation, we are manually putting the password in idmappingextcache, since this has the advantage of being able to control its lifetime.
Also note that perhaps some steps are not required. It's just a summary of what we did.
Please reply to this thread in case you make improvements.
It's possible that I'm not always using the right terminology. Feel free to correct me.
Overview:
- Prep
- Create custom U/P service to store the U/P in the idmappingextcache upon logging in
- Configure that U/P policy by default (optional)
- Create GSO webservice which will respond to GSO get queries and take the information out of the idmappingextcache
- Configure the FSSO mechanism to use that GSO service
- Set permissions
Prep
- sps.httpRequrestClaims.enabled must be set to true
- sps.httpRequestClaims.filterSpec must be set to cookies=*: headers=*: parameters=*
- I'll be using the runtime configuration for the custom U/P mechanism (https://philipnye.com/2017/06/14/isam-infomap-any-alias-authentication/) so make sure you have admin credentials configured in the bind-credentials stanza in ldap.conf
- sps.authService.policyKickoffMethod is set to 'path'
- upgrade to 9.0.6, this relaxes the requirement to have application/json headers present. Otherwise you'll have to inject an accept header yourself. (https://www-01.ibm.com/support/docview.wss?uid=ibm10734111&aid=1)
Custom U/P serviceThe mapping rule is of course the most important part, since we'll be adding the username-password to the idmappingextcache.
importClass(Packages.com.ibm.security.access.user.UserLookupHelper);
importClass(Packages.com.tivoli.am.fim.trustserver.sts.utilities.IDMappingExtUtils);
var username = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:parameter", "username");
var password = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:parameter", "password");
validateCredentials();
function validateCredentials() {
if(username == null || password == null) {
success.setValue(false);
} else {
var userLookupHelper = new UserLookupHelper();
userLookupHelper.init(false);
if(userLookupHelper.isReady()) {
var user = userLookupHelper.getUser(username);
if(user != null) {
isAuthenticated = user.authenticate(password);
if (isAuthenticated) {
IDMappingExtUtils.getIDMappingExtCache().put(username, username, 600);
IDMappingExtUtils.getIDMappingExtCache().put(username + "-pass", password, 600);
context.set(Scope.SESSION, "urn:ibm:security:asf:response:token:attributes", "username", username);
success.setValue(true);
} else {
macros.put("@ERROR_MESSAGE2@","Invalid credentials");
success.setValue(false);
}
} else {
macros.put("@ERROR_MESSAGE3@","User null");
success.setValue(false);
}
}else {
macros.put("@ERROR_MESSAGE4@","Lookup Helper not ready");
success.setValue(false);
}
}
}
Then, create a mechanism linking this mapping rule to a template (you can use the default login.html).
Finally, create a policy with this mechanism as a workflow step.
Configure that U/P policy by default (optional)Follow
https://philipnye.com/2015/12/22/isam-selective-use-of-local-response-redirect/ to configure this new U/P policy by default.
Create GSO webservice which will respond to GSO get queries and take the information out of the idmappingextcacheThe most important part is again the mapping rule:
importClass(Packages.com.tivoli.am.fim.trustserver.sts.utilities.IDMappingExtUtils);
importClass(Packages.com.tivoli.am.fim.trustserver.sts.utilities.IDMappingExtCacheDMAPImpl);
var gsousername = "";
var gsopassword = "";
var username = context.get(Scope.REQUEST, "urn:ibm:security:asf:request:parameter", "username");
usernamenoslash = username.substr(1)
if (usernamenoslash != null) {
gsousername = "some-domain\\\\" + IDMappingExtUtils.getIDMappingExtCache().get(usernamenoslash);
gsopassword= IDMappingExtUtils.getIDMappingExtCache().get(usernamenoslash + "-pass");
}
success.setValue(false);
page.setValue("/authsvc/authenticator/gsoresponder/gso.html");
macros.put("@GSO_USERNAME@", (gsousername!= null ? gsousername : ""));
macros.put("@GSO_PASSWORD@", (gsopassword!= null ? gsopassword : ""));
Create the mechanism, make sure to add a gso.json file (we'll not be using the html version). Our json looks as follows:
{ "gso-username": "@GSO_USERNAME@", "gso-password": "@GSO_PASSWORD@" , "error": "@ERROR_MESSAGE@" }
And again, create a policy with the GSO mechanism as a workflow step.
Configure the FSSO mechanism to use that GSO service
[forms-sso-login-pages]
login-page-stanza = login-page-one
[login-page-one]
login-page = /RDWeb/Pages/en-US/login.aspx*
login-form-action = *
login-success-pattern = +302
gso-resource = [url]****redacted****:443,mga/sps/apiauthsvc/policy/gsoservice?username=
argument-stanza = args-for-login-page-one
[args-for-login-page-one]
DomainUserName = gso:username
UserPass = gso:password
Set permissions on the gso serviceI'll leave that one up to the reader. We created a PoP blocking access to the GSOService for any network (and therefore implicitly only allowing access to the service from ISAM).
------------------------------
Michael
------------------------------
Original Message:
Sent: 12-19-2018 11:41 AM
From: Michael Boey*****
Subject: Forms based SSO - credential pass-through
Hi Jon,
I'm certainly willing to share code snippets. I have them available but need to take some time to present them more nicely here. I should have some time by the latest next week. Please ping me in case I forgot!
Kr,
Michael
------------------------------
Michael
Original Message:
Sent: 12-18-2018 02:03 PM
From: Jon Harry
Subject: Forms based SSO - credential pass-through
Hi Michael,
I am certainly interested in the detail. This would make a great subject for a blog post if you're willing to share the code snippets. I'm sure you are not the only one who has be looking into this but you are the first I know of to set up a GSO service in the Authentication Service!
Nice work.
Jon.
------------------------------
Jon Harry
Consulting IT Security Specialist
IBM
Original Message:
Sent: 12-18-2018 12:58 PM
From: Michael Boey*****
Subject: Forms based SSO - credential pass-through
Update:
I implemented the Store password in GSO at login time (v2) option.
Since this was my first real encounter with ISAM it took me some time, but actually it is pretty easy (and I had some help of Peter).
Basically the steps were the following:
- Create a custom U/P mechanism-mapping where the UP is stored in idmappingextcache for a limited amount of time
- Use that U/P mechanism by default (or for RDS only)
- Create a mapping which will respond to GSO get requests and retrieve gso-password and gso-username from the idmappingextcache
- Configure FSSO for using the GSO service
gso-resource = [url]*****.com:443,mga/sps/apiauthsvc/policy/gsoservice?username=
If anyone wants more details, please ask.
Thanks for all the help!
------------------------------
Michael
Original Message:
Sent: 11-24-2018 08:24 AM
From: Michael Boey*****
Subject: Forms based SSO - credential pass-through
Hi Jon,
Thank you very much for your efforts! I have to sync with another team for making changes to RDS, but given the limited impact I assume that will not be an issue.
Concerning the move to Kerberos, that's probably the better move to make. However I wanted to use RDS as a quick proof of concept regarding the forms based so capabilities and limitations. I guess they are clear now ;).
Original Message------
One thing that just occurred to me...
Given that this is a Windows application sitting behind IIS, would it not be easier to enable your WebSEAL for delegated Kerberos authentication rather than relying on form-filling?
Jon.
------------------------------
Jon Harry
Consulting IT Security Specialist
IBM
------------------------------