WIF and MVC – How it works
I got a few questions from people on how the “Federation with Multiple Partners” sample of the guide works, so I figured I would just write it down in one place for eternity.
The guide explains all sequence in quite some detail (see pages 88 to 97), but sometimes a diagram is more helpful, so here’s a sequence diagram that describes all interactions:
- An un-authenticated user browses a protected resource, say the “Shipping” page (which translates into a method in a Controller).
- The Controller is decorated with the AuthenticateAndAuthorizeAttribute which implements MVC’s IAuthorizationFilter interface. Because the user is not authenticated yet, it will issue a SignInRequest to the configured issuer (this results in a redirection to the issuer). Among other tings it passes the user original URL in the context (wctx) of the request (in this example is the “Shipping” page).
- The Issuer authenticates the user with whatever means and if successful, it issues a token for the user for that application.
- The Token and the the context information is passed back to the app to a specific destination (indicated in the realm). In the MVC application, this is just another controller (“Home” in our sample, method “FederationResult”). This controller is not decorated by the AuthenticateAndAuthorizeAttribute.
- The request however, does go through the WIF Module (the “FAM” in the diagram above). WIF will validate the token and create a ClaimsPrincipal that is eventually passed on to the controller.
- The Home Controller inspects the context parameter, extracts the original URL (remember the context is preserved throughout all hops) and then redirects the user there.
- The redirect will go again through the filter, but this time the user is authenticated.
- Any authorization rules are performed (in our example, we checked for specific Roles) and if all checks pass…
- The specific controller is finally called (e.g. Shipping).
A couple notes:
Everything within the green box above happens only when there’s no session established or when the session expires. Once there’s a session, the requests only go through the filter.
In our sample, there’re actually two Issuers. This is because the sample deals with “Multiple Partners” each one with its own Identity Provider, a scenario that makes convenient to have another intermediate Issuer (a.k.a. “Federation Provider”). I didn’t add it in the diagram above just to keep things simple and focus on the specifics of MVC and WIF.
Because the protocol uses redirections, interactions in the diagram above are “logical”. Whenever you see an arrow with “redirection” label, what actually happens is that the response is sent to the browser and then the browser initiates the interaction with whatever you are redirected to:
In our sample we chose to use “roles” as a way of providing access:
But it should be clear that you could use anything. Repeat: “roles are claims, but not every claim is a role” :-)
Also, this declarative model might not always work. You might have to make decisions on the parameters of the call, and since you have access to the claims collection (through the principal), you can programmatically use them for more advanced behavior. Using roles is just convenient for an examples.
Comments
Anonymous
April 12, 2010
The comment has been removedAnonymous
April 14, 2010
Thanks Russ, Why do you want to keep user/pwd screen in the application? The whole point of federation is to get rid of any authentication in the app. But, you can have your own STS with the login screen that you can customize as you wish. Makes sense? Eugenio BTW, I don't think FederatedPassiveSignin gives you user/pwd controls.Anonymous
May 31, 2010
My thinking behind keeping the actual login screen within the application is for look and feel. For example, say I am a large business that owns a number of brands (within the same market). Ideally, I like possibly to have to implement only one STS for authenticating users to sites associated with my different brands. How could this be handled by delegating the login screen to an STS? Could I have multiple login URLs for an STS, with each URL being associated with a different brand and styled according to that brand?Anonymous
May 31, 2010
Russ, You would only implement your own STS if the customer using your applciation doesn't have an identity provider. If you sell your service to a big company (like Microsoft), then you would have your application trust such company's STS not yours. Otherwise you'd be defeating the purpose of externalising Authentication. (its employees would have 2 distinct username/passwords: one for MSFT and one for your system). Makes sense? For campnies with NO STS of their own, then you would roll out your STS (with your custom look and feel) and have your app rely on that for authentication. From an app perspective, it's completely decoupled and independent. re: "Could I have multiple login URLs for an STS, with each URL being associated with a different brand and styled according to that brand?" The answer is yes. Happy to follow-up on e-mail. Contact me through the blog if you are interested.Anonymous
May 31, 2010
Thanks Eugenio. I have a few more questions, so I'll fire over an email with them. Really appreciate your time in resolving my questions :)Anonymous
July 15, 2010
Well, if I understand it right Russ wants to have a "login/passwd" form at his site (sites) index page(s) just for user convenience. User may want to login right here and right now on a particular page while reading something and suddenly desired to leave some comments. This is what I'm interested too in context of using WIF with ASP.NET MVC. Is it clearly possible to support such a transparent scenario?:
- you have a login form right on the every page of your site
- you want to allow user to login whenever he wants
- you want it without any user redirection (visually), user had to just put login/passwd in a form on a page which just refreshes and conceals all the movings behind itself (like STS working somewhere on background user would never see but it is used by RP-app itself)
- the desire is not to have the same look and feel of STS but to have a form on your page (along with other elements) and to let zero-friction login for user. P.S. Hope I described the problem right :)
- Anonymous
December 15, 2010
The comment has been removed - Anonymous
January 19, 2011
Hi, At my company we're using MVC 2 webapps as RPs and ADFS 2.0 for authentication. We have passiveRedirectEnable=True and our Custom IAuthorize Attribute simply throws an HttpUnauthorizedException when the user isn't authenticated and it's working fine. I've seen several posts/articles that state that you need to set passiveRedirectEnable=False and handle the redirecting in a custom IAuthorize attribute. Why? We're not doing that and it's working fine. Where is this information coming from? Thanks, Pete