In a previous post, I talked about candidate architectures for federated identity systems. My current favorite includes a single IP-STS that issues identity-only claims that are globally unique across all security realms. Because most applications will require more than just identity claims to make an access control decision, the architecture includes an RP-STS per realm. These token services translate globally unique user attributes into ones that are specific to him/her in each of these fiefdoms. The additional claims allow the applications in these realms to determine if the subject should be allowed access to their resources. A diagram of this arrangement doesn't have many boxes or arrows (as you can see in the first figure); however, it gets more complicated when you think about what it would require to solve some fairly common use cases. For instance, how does a Web application in one realm call a Web service in another? This need may arise when one BU owns the Web front-end and another owns the back-end service. Each application in these two BUs (i.e., security realms) would trust different RP-STSs. So, how (on paper) can this use case be solved with the previously described candidate architecture?
In order for this to work, the Web front-end RP 1 needs to trust RP-STS 1; RP-STS 1 must trust the IP-STS. Also, the Web service RP 2 trusts RP-STS 2. The RP-STSs must trust each other. These relationships can be seen in the second figure.
That's a few more lines, and we still haven't shown the information flows ;-)
Given these trusts, the chain of events that result is as follows: When an unauthenticated user accesses RP 1, he is redirected to RP-STS 1 (via WS-Federation). From there, he is redirected again to the IP-STS (also on the front-channel). The user authenticates, and the IP-STS issues him a security token ST0 containing identity-only claims. It redirects him back to RP-STS 1. That STS accepts ST0 as proof of the callers identification (because it trusts the IP-STS), and issues him a new token ST1 which contains application-specific claims that RP 1 will need authorize his access. It is very important to note that at this point ST0 is gone. RP-STS 1 may have copied the identity claims into ST1, but for all practical purposes ST0 with its signature, claims, and whatnot is completely gone. ST1 is returned to the user, and relayed to RP 1.
Now, our Web front-end RP 1 wants to call the back-end Web service RP 2 to get some additional resource. To do so, RP 1 needs a token for the user that is specific to RP 2. This RP only trusts RP-STS 2, so RP 1 must request an ActAs token from RP-STS 2 (using WS-Trust). To get this, RP 1 must be able to authenticate (e.g., using an X.509 cert) and send it ST1 that it got from an issuer that RP-STS 2 trusts, namely, RP-STS 1. RP-STS 2 does some verification of the token and authorization to ensure that RP 1 and ST1 can be used to get an ActAs token for RP 2. If so, RP-STS 2 transforms ST1 into an ActAs token ST2 that contains application-specific claims for the user accessing RP 2 (via RP 1). ST2 is returned to RP 1 who includes it with the request sent to RP 2. RP 2 trusts the issuer, so it accepts the claims in it and uses them to determine if the user is allowed access.
This sequence of events is shown in the final figure:
I know what you're thinking: This is maddening. Anyone that does this is psycho. You're right that this is complicated stuff. (Anyone who tells you differently is trying to sell you something.) If you're dealing with financial data, healthcare records, government secrets, or other sensitive information, however, what alternatives do you have? Let me know if you can think of a better way.
Great post!
One little detail: the trust arrows suggest bi-directional trust relationships, when in reality trust is generally one way: the RP trusts the RP-STS. The RP-STS trusts the IP-STS.
Thanks, Eugenio, for the comment! I'm a little confused by it though. The RP-STS takes the RP's public key. Doesn't that establish a trust in the same sense that the RP taking the RP-STS's key does? Ditto for the IP-STS and its acceptance of the RP-STS's key. If so, the trusts are bidirectional not one way. I suppose the IP-STS and RP-STS need not encrypt the tokens for the RP-STS and RP receptively which would alleviate their need to trust their public keys. Besides this case, am I missing something else that would make these trusts one way?
Hi Travis,
It was a nice article. But, I have few queries. Is the above architecture supported in the Passive federation scenario. If yes, then can you give me the link for showing exact configuration to form a trust between an ASP.NET application (i.e., RP) and RP-STS, And then a trust between RP-STS and IP-STS if possible.
Thanks
Prashant
In the example, interaction w/ the Web front-end will be done using the passive profile; however, the communication w/ the back-end services will be done using the active version. To see how to configure this, check out the ActAs sample that comes w/ the Windows Identity Foundation (WIF) SDK. If you have more questions or are still unclear, let me know.