Monday, January 11, 2016

ADFS : SAML redirect to application via relayState and loginToRp

This post follows on from:

IDP Initiated Sign-on to SAML SP using SAML IDP

Prior reading:


The question is around having a SAML IDP (Salesforce), ADFS as the RP-STS and multiple SAML RP.

Users may authenticate with either AD (via ADFS) or via Salesforce.

The easy way is to use RP Initiated but that wasn't an option.

In the link above, there is a useful tool to generate the relayState.

There are three text boxes:

IDP
RP-STS
Application

The article is somewhat confusing because the third text box refers both to a string to be passed to the application and the ADFS identifier of the application.

However, the use case we want i.e.

Identity provider security token server (STS) -> relying party STS (configured as a SAML-P endpoint) -> SAML relying party App

is supported.

I tried this with two ADFS - both v3.0.

So ADFS IDP = adfs-idp
ADFS RP-STS = adfs-rp-sts
Application ID = appid

which leads to:

https://adfs-idp/adfs/ls/idpinitiatedsignon.aspx
https://adfs-rp-sts/adfs/ls/
appid

and the URL is:

https://adfs-idp/adfs/ls/idpinitiatedsignon.aspx?RelayState=RPID%3Dhttps%253A%252F%252Fadfs-rp-sts%252Fadfs%252Fls%252F%26RelayState%3Dappid

So the user should authenticate on adfs-idp, be redirected to adfs-rp-sts, be already authenticated and then be redirected to the application.

However, I could not get this to work. I kept getting:

MSIS7001: The passive protocol context was not found or not valid. If the context was stored in cookies, the cookies that were presented by the client were not valid. Ensure that the client browser is configured to accept cookies from this website and retry this request.

If I left the third text box empty and removed the empty "RelayState=", I get:

https://adfs-idp/adfs/ls/idpinitiatedsignon.aspx?RelayState=RPID%3Dhttps%253A%252F%252Fadfs-rp-sts%252Fadfs%252Fls%252F

So the user should authenticate on adfs-idp, be redirected to adfs-rp-sts, be already authenticated and then select the application from the dropdown, This works.

For AD authentication, we can use the form at the top of the article i.e. using the loginToRp parameter.

This gives:

https://adfs-rp-sts/adfs/ls/idpinitiatedsignon.aspx?loginToRp=appid

So the user should authenticate on adfs-rp-sts and be redirected to the application, This works.

Or we can take a completely different approach (albeit with ADFS 3.0) as per:

ADFS 3.0: Playing with Authentication

where you can use:

Set-AdfsRelyingPartyTrust

where you can configure any of your relying parties to use specific claims provider(s).

Note:

Just to call out @RobM's summary from the forum question above:

"If you have a SAML IDP and a WS-Federation SP, you can use a URL constructed in the following manner to sign in:

https://corporate.adfs.com/adfs/ls/?wa=wsignin1.0&whr=https://identity.provider.com/&wtrealm=https://service.provider.com

If you have a SAML IDP and a SAML SP, the URL looks like so:

https://identity.provider.com/idploginpath/login?RelayState=RPID%3Dhttps%253A%252F%252Fidentity.provider.com

Note that with WS-federation, the flow is ADFS --> IDP --> ADFS --> RP

With SAML only, the flow is IDP --> ADFS --> RP"

Enjoy!

11 comments:

Unknown said...

Hi,

Thanks for nice article.

Could you please advice if there is a way to skip IDPInitiatedsignon page on ADFS RP-STS?

So we the following scenario.
On Client's IDP user opens IDPInitiatedsignon page, selects required Relying Party (which is our ADFS RP-STS), enters login/pass and press sign in.

After successful authentication user being redirected to ADFS RP-STS (ie. https:///adfs/ls/) and right after that he/she automatically goes https:///adfs/ls/idpinitiatedsignon

Note: ADFS RP-STS makes transformation of incoming claims and adds a couple of new claims.

As our application (RP) supports only WS-Fed on that page user sees only message "You are signed in" and Sing Out button.

But even we can get our app talk SAML user will have to select RP (our application) in the list on https:///adfs/ls/idpinitiatedsignon page. which is not acceptable for us.

So Question: is any way we can skip idpinitiatedsignon page on adfs-rp-sts and go directly to RP (Application) ?

Thanks!

nzpcmad said...

If you changed to SAML, could you not use relayState?

Unknown said...

Hi,

Lets clarify a bit.

Do you mean change application to support SAML protocol and enable SAML endpoint on adfs-rp-sts ?

The issue is that we don't control client's ADFS ( adfs-idp in your terminology )
Of course we can ask them to enable RelayState but base on their requirements user goes to
https://adfs-idp/adfs/ls/idpinitiatedsignon and select required Relying Party (they have several in the list).

So it is not an option to provide them link so they could insert it on their portal.
https://adfs-idp/adfs/ls/idpinitiatedsignon.aspx?RelayState=RPID%3Dhttps%253A%252F%252Fadfs-rp-sts%252Fadfs%252Fls%252F


If they could put a link somewhere on their portal then it would be easy to put link directly to application and then we would get RP initiated flow which perfectly works right now.

But even base on your note in article (if i understand correct) user be authenticated on asfs-idp automatically goes to adfs-rp-sts where he/she should select application from the drop down.

So question: is that possible to avoid this step with selecting RP(in case when SAML endpoint enabled) on adfs-rp-sts if user already authenticated on adfs-idp.

For now i see only one option
We change app to support SAML protocol and get rid of adfs-rp-sts from this chain.
then ask client to send us Claims in appropriate format (as i mentioned above we make transformation of incoming claims on adfs-rp-sts side)


Thanks!

nzpcmad said...

The way it's supposed to work is:

https://adfs-idp/adfs/ls/idpinitiatedsignon.aspx?RelayState=RPID%3Dhttps%253A%252F%252Fadfs-rp-sts%252Fadfs%252Fls%252F%26RelayState%3Dappid

idpinitiatedsignon - the ADFS-idp
RPID - the ADFS-rp
RelayState to the application

If you remove ADFS-rp, then you have to point the app to ADFS-idp.

Unknown said...

Hi,

Looks like the only option for us is to remove ADFS-rp and point app to ADFS-idp.

Thanks!.

Unknown said...

I got it working by using this

https://RP-adfs/adfs/ls/idpinitiatedsignon.aspx?LoginToRP="identifier"&RedirectToIdentityProvider=http%3a%2f%2fidp-adfs%2fadfs%2fservices%2ftrust

Thanks

Unknown said...

Finally, I got it's working. Using this

https://RP-ADFS/adfs/ls/idpinitiatedsignon.aspx?LoginToRP="Identifer"&RedirectToIdentityProvider=http%3a%2f%2fIDP-ADFS%2fadfs%2fservices%2ftrust

Anonymous said...

Hi nzpcmad,

May i know is it possible to pass parameters to saml idp?
My scenarios is like below :
SAML-RP -> ADFS -> SAML IDP

the SAML IDP expecting us to pass something like https://identity.provider.com/?Target=https://service.provider.com&Name=SpApp

nzpcmad said...

Have a look at loginToRP:

https://techontip.wordpress.com/2013/01/11/logintorp-auto-select-relaying-party/

Anonymous said...

Thanks for sharing the link to me, i just noticed the actual issue with my setup.

Do you have any idea how to get the adfs generated MSISContext cookie {guid} value and pass it to SAML idp as one of the querystring?

nzpcmad said...

No sorry.

Be aware that whatever you do needs to conform to the SAML protocol.