SAML2 Multiple Service Providers - single-sign-on

We have single sign on implemented in our web product(app1) using SAML 2.0 - our product is the service provider. Now one of our clients is asking for a link in app1 which will take the user to their web app(app2) and they are expecting the user to single sign on into their application. I am assuming that their app(app2) will be using the same IDP as app1 is using.
Based on my understanding I think a link to their AssertionConsumer of app2 should do the work. When the link to the app2 is clicked app2's AssertionConsumer will be able to process the claims from app1. Will appreciate if someone will chime in and let me know if I am missing something.

You should not link to the Assertion consumer URL. You link to the relevant page in app2. App2 will detect that the user is not authenticated and send it to IDP for authentication. The IDP will detect that the user is already authenticated and return the user to the page it was originally sent to.

Does app2 do passive auth when users arrive? If so, you should just link to any page in app2 and let it take care of asking the IdP about the user's login status, rather than trying to tell it.
If app2 doesn't automatically check with the IdP, then you should probably link to a page in app2 that requires auth, so that it will.
In general, the whole point of the IdP is that it's the thing that the SPs trust to tell them whether (and how) a user is authenticated, so you shouldn't try to build an additional system of trust between the SPs. (It's fine if they hint to each other that the current user is logged in or even someone in particular, but they should check with the IdP before believing it.)

Related

Keycloak : update user email from external IDP after first login

I've successfully set up an external IDP in Keycloak with OIDC.
User is created if it doesn't exist in Keycloak realm, and is linked if it already exists. I've slightly altered the first broker login flow to implement this.
We've disabled email update feature in our app, as the trust source for this information is the external IDP. Now how can I force Keycloak to update the user email at login time if it has been changed in external IDP ? This informations is provided by the external IDP.
My knowledge of Keycloak login flows is not really good, so at least any hints / pointers on "how to to it" would be greatly appreciated. Thank you.

SAML SSO: keeping users logged in after validating the SAML Assertion

I am implementing front-channel SAML 2.0 SSO golang Service Provider, with Okta as my Identity Provider (this is just a POC and should eventually work with any IdP).
Implementing the sign on process was straightforward with saml2 package. I've created the login endpoint that redirects to the SAML application login URL at the intended IdP, as well as the POST callback endpoint which is properly receiving the SAML assertion and is able to validate it. After that a session with a random cookie is created with the same TTL as the Identity Provider session TTL. So far everything works well (I haven't implemented Single Sign-Out yet, but I'm planning to).
However, when some time passes and the session expires, I'd like to renew it only if the user is still logged in with the Idp and hasn't been removed from the SAML Application. I would like to avoid redirecting the user to perform SSO again with IdP, because it would mean that if they are still logged in, they would be redirected back to the home page of my application. I wasn't able to find great sources on my options to go about it online.
Questions:
1.1 One solution that comes to mind is storing the requested URL in the RelayState parameter, whenever the session has expired, then redirect the user to the IdP SSO URL. When the redirect returns to the SAML callback POST endpoint, check the RelayState parameter and if set, redirect back to that (original) URL. That means that for users that use the system continuously, I would have to request Assertions very often. Does that make sense?
1.2 A second solution that comes to mind is to implement a back-channel of communicating directly from my SP to the IdP. That would allow me to verify a user is still logged in 'behind the users back'. If that's a sound idea:
a. Do I need to have dedicated code for each IdP?
b. Do I need to load an API key to the IdP which would allow secure communication?
c. Do I need to upload a public certificate to the IdP that would be able to verify that my SP signed the requests?
Will using the Assertion to get an OAuth 2.0 Access Token help me in achieving this?
I've chosen SAML 2.0 for now, since the environment is an enterprise oriented one and I thought it fits well with it based on what I read. Would using OpenID Connect instead help achieve my goals easier and fit well with enterprise oriented products?

Is there a standard for two Relying Parties with a common Identity Provider to share information?

Here's a situation that I have been considering recently:
A client has their own Identity Provider (i.e. ADFS)
My company's web application (Application A) supports SAML and OpenID Conect
Another company's application (Application B) also supporting SAML and OpenID Connect
Both Application A and B are associated with the Identity Provider
It is possible to ask the authors of Application B to change it
Application A and B have links between each other. In order to get from Application A to B, the workflow looks like this:
User is logged in to Application A
User clicks on a link to Application B
User is now at the Application B sign-in screen
E-mail address is entered
User is bounced to ADFS or similar system
User is now logged in to Application B and can see the resource
We would like to streamline the user experience:
User is logged in to application A
User clicks on a link to Application B
Application B somehow detects that the user is using SSO and redirects them to the appropriate page
User is bounced to ADFS or similar system. Hopefully if the last login wasn't too long ago, the user should be automatically authenticated.
User is now logged into Application B and can see the resource.
Right now, we're thinking that we rewrite our outbound links to Application B like so: https://example.com/redirect?email=user#example.com&url=/the-resource
This would allow Application B to detect if SSO was required, and I guess we'll do this if there's no other option. I would however like it if there was an already established standard for doing this, so we could just ask other companies to implement the same standard.
I know that detection of the SSO system is left up to the Relying Party, so perhaps this is just something that we have to work out with the authors of Application B.
Is there a standard for RP to RP data interchange where both RPs have a common Identity Provider?
If by "share information" you mean "Provide a hint as to the user's IDP" there is a standard being developed, https://ra21.org/ . Before RA21 started, i had a similar thought that i shared at IIW 22 (https://www.internetidentityworkshop.com/proceedings.html). It was essentially what you are proposing: put an IDP hint in the URL. The response was positive, but few folks had a use case where they could use it.
I note that the proposal (see Tuesday 5G, p 45 of the proceedings) the hint we discussed for OpenIDConnect would be the issuer ...redirect?issuer=[issuer]... See the notes for the specification justification.
If you are sharing a SAML IDP, you could take a look at http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-ui/v1.0/cs01/sstc-saml-metadata-ui-v1.0-cs01.pdf ยง2.2 Discovery Hinting Information . If your SAML IDPs included the child element in their metadata, that would be a straightforward way for the IDP to establish how RPs could hint to each other, and the value in the URL could be ...redirect?DomainHint=[whatever].... It's been some years and i can't remember
As a final note, sending the email address in the URL would violate so many privacy expectations. Do not put PII in your URL!
I'm afraid there is no standard for SAML relying parties/service providers to exchange information. All protocol messages are between the claims provider/identity provider and relying party/service provider.
In lieu of a standard, what you're proposing looks reasonable.
Sounds like you need a 'WAYF-less' URL entry point for Application B. WAYF = Where Are You From? and was the old way of finding out which IdP a user was associated with. If the user is already authenticated at Application A, then Application A knows the entityID of the IdP for that user. The user's IdP will also have an authentication session for them as they have already logged in to Application A.
So you could have in Application B:
https://applicationb.com/sso?entityID=https://some.idp.com/shibboleth
Application B then loads the SAML metadata for the entityID and automatically redirects the browser to the SSO URL associated with the entityID and the IdP will redirect the user back to Application B's SAML consumer endpoint. The user will not see another login screen (unless their IdP session has expired) and Application B will get its own set of SAML attributes.
Sharing attributes in the URL isn't ideal as Application A might be entitled to see the user's email (as released by the IdP) but Application B might not. So it's best to follow protocol and let the IdP release the attributes to Application B, separate from anything Application A knows about the user.
The only thing A is sharing with B is the entityID of the user's IdP. That allows B to begin the SAML flow and get the attributes for itself.
I think you're on the right track. It's entirely up to the RP whether it thinks it should use the IDP or not so you just need to pass enough context when you navigate to app B so it can make that decision. So in this case the "standard" would be front channel navigation to a known endpoint with the information you require in the query string or hash.

How to implement "IdP first" scenario for WS-Federation

ADFS 2.0, WIF (WS-Federation): I want to implement SSO in the scenario when user goes to IdP web-site first to be authenticated. In this scenario our customers have intranet web-portals with links to our (service provider) web site, which actually lead them to IdP web site and redirect them to our web site as soon as user is authenticated. I could not find any info with technical details on how to implement it properly, can anybody?
What I did so far, I grabbed the redirection link to IdP using Fiddler to use as portal link and looks like it works, however I'm not sure if it's a proper way to do that. If you have similar experience please share.
UPDATE: More detailed use case: Our customer has its own intranet portal with link to our web site (service provider). The idea is to avoid additional initial http redirections and to have single entry point for different customers, so that our web site can count on security token coming from user to recognize identity of the customer, in other case we should have separate uri for any customer. User clicks the link, it leads him first to its own intranet IdP service (ADFS 2.0) that authenticates him with his windows account and adds security token and redirects him to our (relying party) web site where we can recognize him and his organization (customer) by the token, and he can consume our services. Let me know if something wrong or seems suspicious with the scenario.
Normal case is that the RP URL bound to ADFS via FedUtil is what ADFS return to. So if the portal is bound to ADFS (doesn't sound like it because you don't have to log in to get there?) then that's where you return when authenticated.
If your web site is what's bound to ADFS, then user goes to portal, clicks on link, gets authenticated, token with claims created and redirect to your web site.

WIF - optional authentication

I'm working on a proof of concept app. The basic functionality works, where I can log into one website, link to another site that shares the same STS, and the partner site picks up the credentials properly.
However, the partner site only requests the token if the page that we link to requires authentication (which kind of makes sense I guess).
Ideally, I'd like to link to a partner page that does not require you to be authenticated, BUT if the user IS already authenticated, I'd like to at least be able to recognize them on the partner site.
Currently, if my partner landing page does not require authentication, it doesn't appear that the user is logged in when they arrive. As soon as the user requests a page on the partner site that does require authentication, it then grabs the token without requiring the user to log in.
I've tried playing around with the SecurityTokenReceived and RedirectingToIdentityProvider events, but so far I'm stumped.
Any thoughts are appreciated.
So, the problem you are running up against is in dealing with the SessionAuthenticationModule hijacking the request. This module is responsible for detecting if the user has a valid session (based on a cookie that is written upon a successful redirect from the STS) and if not, to redirect the user to the STS to fetch a valid token. The WSFederationAuthenticationModule supplies the eventing necessary to hook into various stages of the redirection/authentication process.
Based on your description, it sounds like you want the following to happen:
User clicks on a link that redirects to the partner site
At the partner site, the request is intercepted and the system determines if the user is signed-in to the STS or anonymous
If the user has a valid session with the STS, then pull the claims for that user
The problem is, your RP cannot know that the user has a valid session without sending the user to the STS first (the RP's do not talk to each other or the STS. The user's brower is used as the means of communication between the RP's and the STS in the form of WS-Fed directives and SAML tokens passed in the url during redirects). If the user is sent to the STS, then they must authenticate, which could be a problem for anonymous users.
So, I do not think there is a "trick" that you can pull via configuration or interception of the request to determine if the user has a valid session with the STS. You might be able to pass a hint, however, from the referrer that is intercepted by the partner site. This hint could take the form of a parameter on the url that indicates to the partner site that the current user has a valid session and to go ahead and redirect to the STS (absence of this hint would indicate an anonymous user). You could also build a system to "hand-off" knowledge of the signed-in user using a resource that both sites have access to (i.e. database).
As you are sure to learn soon, more often than not, WIF offers pieces to the puzzle, but every situation is different and you have to supply the other pieces on your own.
Hope this helps!