I have an existing site A protected with CA SSO Web Agent with DirA using username attribute for user disambiguation and DirB for user authorization. DirA is mapped to DirB by UniversalId (cn).
Now I implemented Google OAuth 2.0 authentication. All social ids are stored in DirA ssoopenid multivalue attribute. Google sends customer's email in a claim. Policy Server can not disambiguate a user by email against DirA because DirA uses username to disambiguate not ssoopenid attribute. I need to createte DirC equal to DirA, but using ssoopenid attributefor disambiguation. Now, when browser is redirected from OAuth client to site A, a session created during OAuth authentication against DirC is not accepted by Site A, because CA SSO considers DirA != DirC.
How this is supposed to be resolved? Some OAuth AZ servers are not even returning email, but a random id, i.e. MobileConnect. The whole OAuth user disambiguation should be done over a custom disambiguation parameter, not a generic one from a user directory.
Email has always been a poor federation linking identifier unless it's fully guaranteed immutable at the IDP and still should be combined with Issuer for mapping; since the same email or other id could be used at multiple IDPs, Issuer combination is important to know which IDP can assert that identity auth info. Google sends their immutable Id as the sub claim to cover the immutable requirement without tying to email, which if combined with Issuer on mapping confirms that it is Google IDP that authenticated said identity and not some other one. Just general feedback to consider how you link external federated partners to ensure uniqueness across providers.
Hoping someone else has found a better way than what we had to do but below is the only way, short of customizing auth schemes to do all the disambiguation ourselves, we found to get the product to do what we needed out of the box under 12.52 (have not revisited with later 12.7+ versions but doubt it has changed much).
For social log in, due to the whole LDAP search being global at the User Directory level, is create yet another "Social Login" directory that uses the same actual physical directory but searches like (registeredSocialId=[idfromlogin]). Multi-values shouldn't matter as part of an LDAP search string since it either matches or doesn't match.
This essentially creates "Normal Dir" (username=[id-from-login]), "Social Dir" (registeredSocialId=[id-from-login]), "SomeOther Dir" (uid=[id-from-login]). They all link back via global identity mapping to "Normal Dir" via some shared attribute that matches or DN. At that point any common attribute can be used for the mapping so long as it exists wherever you are mapping from/to (username, name, email, whatever guaranteed unique)...But you've got to have that mapping identifier present. This results in "Normal Dir" being used for all the authorizations/attributes being sent to apps but the other directories used to disambiguate the users based on specific requirements; "Normal Dir" is also the only directory that has to be assigned to applications so that the only people who have to mess with the other ones are our centralized credential collectors.
Downside is having to manage those fake directories just to adjust the search base. It'd be easy to manage if we could simply customize disambiguation on the inbound partnership with a fully modifiable search parameter, but never found a way to do that.
Anyhoo, it's what works for us but can get messy since you end up with directories simply to be able to adjust search bases based on different requirements but has functioned; really depends on how many inbound trusts you'd have whether it'd be manageable or not. Slowly cleaning it all out by replacing all the CA SSO log in flows with the CA API Gateway on the front-end instead - makes things a lot nice and cleaner since it does a better job doing real logic compared to out of the box CA SSO .
Have you tried to perform Identity Mapping on Dir C to Dir A on ssoopenid and then use the Virtual attribute (from result of IdMapping call) which will be uid in Dir A to perform the disambiguation in partnership ?
We are at 12.7. Myself and my coworker have been trying hard to reproduce your scenario. Identity mapping is ignored, looks like it's not working for partnerships. Are you sure there is no any hacks you use to make it work? I'm reading communities posts now regarding Identity mapping and partnerships, your name is popping up :-). Something about modifying hidden objects.
If regular domains are used, Identity mapping works.
We use Option Pack, BTW. The other difference , you have User Accounts to APIxx mapping. The rest of setup is reproduced to no success.
You will need to add DirC to the SiteA User Directories list and also add it to the Domain Policy so that the users that have session cookies generated against DirC can be Authorized to use SiteA
That's a great answer and close to what I thought while trying OAuth authentication. Do you mind to confirm on a couple things please?
-What do you mean by "Issuer on mapping"? Is it like writing to LDAP not just a social id but issuer as well, so that registeredSocialId attribute will have "google:id" combination, and then "Social Dir" disambiguation will be (registeredSocialId=google:[id-from-login]). This will require "Social Dir per Vendor", right?
-Identity mapping to "Normal Dir". You mean an identity mapping where Source: "Normal Dir" and Target: "Social Dir", another mapping Source: "Normal Dir" and Target: "SomeOther"? I made this work, but it looks counterintuitive to me. If my application has "Normal Dir" and a user accesses it after OAuth authentication with "Social Dir" a logical mapping would be from "Social Dir" to "Normal Dir".
Shoot possibly, we had to do so much jank stuff to get things working lol. If I get some free time to look I'll give another once over, might be missing some key thing we check boxed or something.
Don't have a good TEST environment right now to work with unfortunately. We're in the middle of ripping all this stuff out so we don't have to deal with all this crazy mapping, directory searches etc any more; my test area is kind of in a between state since we're deep in the CA API Gateway transition to move all the core authentication there and away from CA SSO on the front-end.
This opens a door for a user to use alternative login names, lock not intended accounts , login with a wrong account (i.e. the same person can have multiple accounts with different services and use his google email as a login name on one account and as a social login on another). Probably another fringe cases.
I wonder why OAuth authentication is not using the same approach as SAML, where attribute from assertion can be mapped to any attribute in dir, even expressions available, and there is no reliance on dir disambiguation.
What do you mean by "Issuer on mapping"? Is it like writing to LDAP not just a social id but issuer as well, so that registeredSocialId attribute will have "google:id" combination, and then "Social Dir" disambiguation will be (registeredSocialId=google:[id-from-login]). This will require "Social Dir per Vendor", right?
- CB: Yes, something like that. In our scenario we actually have separate attributes - since they already existed in the enterprise directory, indexed, and managed so was easy to piggy back on them - so like googleId=[id-from-login], facebookId=[id-from-login]. For certificate authentication then we piggy back on Microsoft's altSecurityIdentity (ASI) concept which is like "X509:<I>[issuer from cert]<S>[subject from cert]" and can be multi-valued this way it ensures guaranteed uniqueness across the dozens of external CAs we trust and Issuer A cannot impersonate Issuer B users by having the same subject.
Using a scoped attribute at registration time, such as you mention (registeredSocialId=google:[id-from-login]), would do similar; that was our long-term goal but for now using multiple attributes. This way if the user came from say a compromised WeakIDP but used the same email then the search should fail because you'd end up with a search like (registeredSocialId=WeakIDP:[id-from-login]) and not find the user. If the legit user came in from Google then it'd pass because now the search would be for the proper (registeredSocialId=google:[id-from-login]).
With that type of setup you'r helping to ensure uniqueness to a specific IDP versus a generic attribute like email address (which can be re-used and also changed). There may be cases where email is still used - due to guaranteed unique from IDP - but should still always be combined with Issuer in some fashion.
The OIDC specs has some input regarding this as well with statements such as:
5.7: "The sub (subject) and iss (issuer) Claims, used together, are the only Claims that an RP can rely upon as a stable identifier for the End-User, since the sub Claim MUST be locally unique and never reassigned within the Issuer for a particular End-User, as described in Section 2. Therefore, the only guaranteed unique identifier for a given End-User is the combination of the iss Claim and the sub Claim"
16.15: ""OpenID Connect treats the path component of any Issuer URI as being part of the Issuer Identifier. For instance, the subject "1234" with an Issuer Identifier of "https://example.com" is not equivalent to the subject "1234" with an Issuer Identifier of "https://example.com/sales"."
One other benefit with tracking and leveraging trusted Issuer overall is also getting into more attribute based access control. For example, if I have a rule set that says anyone from WidgetCorp that is a Developer and logged in via MFA should have access to DevResources, then by closely tracking and leveraging the Issuer at linking and session, I can now assert and trust that UserMike is from WidgetCorp, used a strong cred and they asserted he is a Developer therefore allow access. So now, by having that trust with WidgetCorp, anyone that is a developer gets instant access to DevResources by simply authenticating through them into the asset and coming in with appropriate claims. Without closely tracking and monitoring the Issuer and who actually asserted the identity, I can't know for certain that the user is in fact associated with that organization and would always be reliant on some other mechanism to track access (internal role based, SCIM, etc). Social Login doesn't fall much into that realm, but something to consider for other higher level trusts where knowing that kind of information is vital.
Mapping this way:
"Social Dir" -- target -> "Normal Dir" .
"SomeOther" -- target -> "Normal Dir".
Basically just a big loopback and using the "virtual directories" (if you consider them that way) to adjust the LDAP search strings as needed (objectClass, ldap base, so on).
Then the only application that needs to assign the "Social Dir" and "SomeOther" would be the centralized credential collector since it has to authenticate to that directory first. THEN the mapping kicks in and attaches user to the "Normal Dir" for subsequent app access.
The first part is totally clear. The second I'm missing something.
I have App1 protected with CA SSO against "Normal Dir". User can authenticate with a regular U/P. I added a link to the login page to start OAuth with Google. OAuth Federation uses "Social Dir" and redirects to App1 URL after authentication is done.
App1 doesn't like user identity by default and asks to authenticate again. I'm adding Identity mapping from "Normal Dir" to "Social Dir" as target and this works. But if instead I add mapping from "Social Dir" to "Normal Dir" as target, it stops working.
Are you certain it's binding the original log in event to "Social Dir"? It's not clear to me how it works the direction you have it.
If App1 = Normal Dir then mapping Normal Dir -> Social Dir should be denied, right? Because the app doesn't know Social Dir...
Visual person so trying to picture your setup, but not doing a good job as to the full setup .
Here's a snippet of the setup I've got:
Assigned "APIxxx" directory only (no others)
Source: User Accounts, Target: APIxxx
Source: Google, Target: APIxxx
- User goes to an application and selects to log in with Google + RelayState (/affwebservices/public/oauthtokenconsumer?AuthzServerID=Google&RelayState=Something)
- User logs in with Google and maps to "Google" directory
- User identity mapped to "APIxxx" based on Universal ID (same physical directory)
- User redirected to RelayState URL
- User successfully logged in
Partnership OAuth with Google
After successful log into test app with mapping, the directory is the APIxxx mapped one, not Google.
I am using Domains not Application objects, this must be a difference. Behaviour you describe makes more sence than what I observe. In my system HTTP_SM_AUTHDIRNAME is not changed after mapping.
BTW, do you use Authorization or Validation mapping?
Ooooh doh should have asked that first lol. We use Application Objects and a global Authentication-Validation Identity Mapping (Directory -> Identity Mappings -> Authentication-Validation). Then under Policies -> Global -> Select Global Validation Directory select the one that contains all the mappings.
Even worse with Application. I need to add both NormalDir and SocialDir to Application directories to make it work. Global Validation Identity Mapping didn't help. I may need to contact support.
Couldn't hurt to ask them I suppose. It seems to work fine with the global mapping for the apps I have using the setup above. What version are you on? Right now I'm on 12.7 and about to be 12.8.
It is resolved. Apparently, when directories are mapped by universalId or common attribute PS adds extra criteria to LDAP query, like (objectClass=orgPerson). It was required to modify the registry to make the query to work with our custom objectClass.
Ah ok, glad you got it working!