In the previous post we turned our claims transformation code into OWIN middleware. We went through the process of creating a component – the ClaimsTransformationComponent – and registering it with OWIN in Startup.cs. We set the current claims principal in our component which is then available within the controllers.

In this post which finishes this series we’ll diverge a little from our main topic and take a look at how we can add dependencies to an OWIN component.

Like this:

In the previous post we built upon our MVC claims transformation demo. Specifically we saw how to take the incoming claims and add a couple of custom ones by pretending that we query some data store. We wired up all the demo code in the HomeController.

The goal of this closing post is to reorganise the claims-related code into OWIN middleware.

Like this:

In the previous post we laid the foundations for this short series. We went through a refresher of claims and OWIN and started building a simple ASP.NET MVC web project to investigate what’s available about the user of the current thread in a controller. We saw that by default the only claim available about a user might be their name, unless they are anonymous of course.

Like this:

Claims have become widespread in software projects to tighten the security aspects of an application. We looked at claims before on this blog – see the link in the next paragraph – but time goes by and new features have been added to this technology lately. This is especially true as far as OWIN is concerned. In this mini-series we’ll concentrate on a very narrow aspect of claims in .NET MVC: claims transformation in OWIN middleware.

Like this:

Claims in authorisation have received a lot of attention recently. Claims are simply key-value pairs where the key describes the type of claim, such as “first name” and the value provides the value of that claim, e.g. “Elvis”. Think of a passport which usually has a page with the photo and lots of claims: first name, last name, maiden name, expiry date etc. Those are all key-value pairs that describe the owner of the passport and provide reliable evidence that the person is really the one they are claiming to be.

I have a long series on claims on this blog. If you don’t anything about them then I recommend you at least go through the basics starting here. That series takes up claims in MVC 4. MVC 5 brings a couple of new features as far as claims are concerned.

Demo

We’ll be using the same demo application as before in this series so have it open in Visual Studio 2013.

As we said before authentication in MVC 5 is built using Katana components which are activated with extension methods on the incoming IAppBuilder object. These Katana components work independently of each other: e.g. you can turn on Google authentication at will as we saw in the previous part. At the same time you can even turn off the traditional cookie authentication, it won’t affect the call to app.UseGoogleAuthentication().

When we turned on Google authentication the consent screen stated that the application, i.e. the demo web app, will have access to the user’s email. That’s in fact a type of claim where the key is “email” or most probably some more complete namespace. Where’s that email? How can we read it?

Locate the method called ExternalLoginCallback in the AccountController. That method is fired when the user has successfully logged in using an external auth provider like Google or Facebook. The method will first need to extract the login information using…

This login information contains the tokens, expiry dates, claims etc. As the login is taken care of by OWIN, MVC will need to tap into the corresponding Katana component to read those values. This is an example of a piece of logic outside OWIN that needs to find out something from it. The AccountController will need this information to handle other scenarios such as signing out. The key object here is the AuthenticationManager.

The AuthenticationManager which is of type IAuthenticationManager is extracted using the following private property accessor in AccountController:

The interface lies in the Microsoft.Owin.Security namespace. The AuthenticationManager is retrieved from the current OWIN context. The GetOwinContext extension method provides a gateway into OWIN from ASP.NET. It allows you to retrieve the request environment dictionary we saw in the series on OWIN:

HttpContext.GetOwinContext().Request.Environment;

I encourage you to type ‘HttpContext.GetOwinContext().’ in the editor and look through the available choices with IntelliSense. The Authentication property exists so that ASP.NET can read authentication related information from the OWIN context as all that is now handled by Katana components.

If you look further down in the code you’ll see the SignInAsync method. The method body shows how to sign users in and out using an external cookie-based login:

Now that we know a little bit about the authentication manager we can return to the ExternalLoginCallback method. Let’s see what the GetExternalLoginInfoAsync method returns in terms of login information. Add a breakpoint within the method and start the application. Click the Log in link and sign in with Google. Code execution stops within the method. Inspect the contents of the “loginInfo” variable. It doesn’t contain too much information: the user name, the provider name – Google – and a provider key. So there’s nothing about any provider specific related claims such as the user’s email address.

Note that the GetExternalLoginInfoAsync method only provides an object which includes properties common to all providers. The list is not too long as we’ve seen. However, the method cannot know in advance what the Google auth provider will provide in terms of claims. The list of available data will be different across providers. Some providers may provide a more generous list of claims than just an email: a URL to the user’s image, the user’s contacts, first and last names etc. Insert the following line of code above the call to GetExternalLoginInfoAsync:

Leave the breakpoint as it is and restart the application. Sign in with Google and inspect the authenticateResult variable. You’ll see that it provides a lot more information than the login info above. The claims are found
within the Identity property:

You can see that the claim types are identified in the standard URI way we saw in the series on claims. You can query the Claims collection to see if it includes the email claim. If your application explicitly requires the email address of the user then make sure to indicate it when you set it up with Google or any other auth provider.

You can save the email of the user in at least two ways:

Temporarily in the session using the ExternalLoginConfirmationViewModel object further down in the ExternalLoginCallback method. That view model doesn’t by default include any property for emails, you’ll need to extend it

In the database using the UserManager object we saw before in this series

Let’s see how we can achieve these. Locate the ExternalLoginConfirmationViewModel object in AccountViewModels.cs and extend it as follows:

This page redirects to a View called ExternalLoginConfirmation when the user first signs up in the “else” clause. Locate ExternalLoginConfirmation.cshtml in the Views/Account folder. You can use the incoming model to view the extracted email claim:

<p>
We've found the following email from the login provider: @Model.EmailFromProvider
</p>

I’ve deleted all rows in the AspNetUsers table so that I can view this extra information. Also, clear the cookies in your browser otherwise Google will remember you. You can also run the application from a brand new browser window. The email was successfully retrieved:

We can store the email claim in the database within ExternalLoginCallback as follows:

First we check the claims stored in the database using the UserManager.GetClaims method. Then we check if the email Claim is present. If not then we add it to the database. The identityResult helps you check the result of the operation through the Errors and Succeeded properties.

The claims by default end up in the AspNetUserClaims table:

You can of course use the AspNetUserClaims table to store any kind of claim you can think of: standard claims found in the ClaimTypes list or your own custom ones, such as http://mycompany.com/claims/customer-type.

Normally a web application is configured to use a single STS for authentication. Using the Identity and Access Tool also pushes you into that direction; there’s no option to set up 2 or more different federated STSs.

However, there may be cases where you would like to allow external users to access your application. Who are these external users? A typical example is the users of a business partner; those users will use a different STS to access their own web app. What if you wish to give those users access to your web app without them having to sign up with your app first? After all you don’t want to manage those accounts, right? They are not really your users, you don’t want to be responsible for their sensitive data in your database.

You could instead somehow configure your application to accept tokens from 2 STSs: your own and that of the partner company. You can designate the STS of the partner as a trusted identity provider. If the external user can come with a token from that other trusted STS then they will be allowed to view your application.

The recommended way to implement this is to follow a pattern called ‘Resource-STS’ or ‘Federation Gateway’.

The idea of this pattern is the following:

Your application should only trust one single token service. Always.

This “master” STS is called the Resource-STS

The Resource-STS can be configured to broker trust with other token services

The external users contact your STS and carry with them the token from their STS

Your STS will understand the external token because the Issuer figures on its trusted issuers’ list

Your STS will issue a new token that your application trusts and understands

This method simplifies the configuration of your web application because it still only needs to be concerned with your single trusted STS. The external relying parties will not need any reconfiguration either. The only application that will need to be adjusted is your STS because it must understand tokens that do not originate from your application.

The trust relationships are set up as follows:

Your web app trusts your STS

Your STS trusts the STS of the business partner

The application of the business partner trusts the external STS

So indirectly your web app will trust the external users.

The logical steps to log on to your web application “from the outside” will look like this:

An external user logs in to their own STS which lies within their domain

The external STS will issue a security token to that external user

The external token will be sent to your STS

Your STS will validate the external token

If necessary your STS will even transform the external claims into claims that your application needs

The external user will be given a new token by your STS, a token which comes from your side of the authentication chain: it is signed by your STS

In the last step the external user sends the transformed token to your we app

From here onwards we have “business as usual”: the claim is inspected, transformed, saved in the auth session etc.

However, there seems to be something missing. The external user will need to navigate to your application first, right? They do not contact the STS login page first and somehow try to modify the URL, that would be impractical. It is your application that should redirect the user to your STS. The additional difficulty is the following: how does your application know where the visiting user is coming from? Which STS should it redirect the user to? The complexity increases if there are more than one external STSs. Even if we establish that the user is an “external” one, then which external STS is theirs?

The process of finding out who is trying to log in and where to redirect this user is called Home Realm Discovery. There’s of course no magic way to answer all those questions in the previous paragraph, we simply need to ask the visitor. Are you a partner? Which partner? Are you an “internal” user? There will be a special GUI within your application to ask these questions and redirect the user to the correct STS.

This GUI may actually not be necessary. There is another way to discover where the external user is coming from. If you have 5 partners then you will probably have links on their web sites that lead to your web application. You can build special landing pages for each of those partners. You can then see based on the opening URL where the user is coming from. Once you know that then you can add a special flag to the STS Url. The flag takes the form of ‘&whr=[id_of_external_identityprovider]’ where ‘hr’ means home realm. The URL may look like the following:

A pre-warning: this demo is far from complete as I don’t have access to a second STS.

Navigate to the Thinktecture Identity Server we installed before and log into the identity provider. Select the [administration] link and then choose the Identity Providers menu item:

Click “New” and you will be presented with the necessary fields to enter a trusted federation endpoint:

This is where you can add the details of an external STS. I don’t have any such STS unfortunately but the textboxes are pretty self-explanatory. Typical values might look like this:

The thumbprint is the certificate signature of the external STS which helps us decide whether the token is coming from a trusted source. The WS-Federation endpoint is the value of the login page of the external STS, like https://localhost/idsrv/issue/wsfed in the case of the demo project.

As we want to run the auth process through Home Realm Discovery we have to update the issuer from ‘wsfed’ to ‘hrd’:

Other commercially available STSs will also have similar URLs for home realm discovery. As we don’t have any other STSs there’s no point in testing the application really. However, using the hrd link we would land on an interim page where the user can select among the available STSs and pick the one that’s relevant to them. They will then be redirected to the login page of their STS. After a successful login the user will see the protected page of your web application.

In case you would like to go directly to an external STS after identifying where the external user is coming from you have two choices:

The homeRealm value will be the ‘Identifier’ field in the Identity Providers setup window we saw above. It adds the ‘&whr=BusinessPartner’ parameter to the STS query string. It tells our STS to go directly to the external STS called ‘BusinessPartner’ and do not show the interim page where the user can pick one of the available trusted STSs.

This is of course a very static way of specifying an external STS. Fortunately we can assign this value dynamically as well. You’ll need to override the following method in Global.asax:

In the previous post we left off with the shortcomings of the Logout function: we log out of the web application but the session is still alive on the STS. Would like to end all our sessions when we press Logoff on the main screen. Similarly if there are multiple web sites that share the same STS then we would prefer to log in once on the STS login page and then be able to use all those applications.

These techniques are called Single SignOn and Single SignOut.

We will build on the MVC4 application we have been working on in this series of blog posts.

Single SignOn

Single SignOn is really nothing else but an application of the widely used “Remember Me” function. Say you have two web applications, SiteA and SiteB that share the same STS. You start the day by logging in to SiteA and do some work there. You’ll of course use the STS login page. The STS will establish a login session with the client. The browser will send the FedAuth cookie with all subsequent requests.

Then at some point you need to use SiteB. SiteB also needs authentication and redirects the user to the same STS. However, the STS will recognise the user’s FedAuth cookie and will issue another token for SiteB without having to log in again.

Therefore we get Single SignOn accross all applications that use the same STS.

Single SignOut

This requires some more steps. It is necessary to clean the local session cookie but it’s not enough. We need to inform the STS that we want to sign out, so please dear STS, end the auth session at your side too. The STS will need to clear its own session cookie so that the Single SignOn session is terminated. Optionally it can also tell the other relying parties that the user wants to sign out, but this is not mandatory. If you only clear the local session cookie of SiteA and the session at the STS, then when you go over to SiteB the STS will not recognise you any more as you killed the auth session. So you will need to sign in again.

If you want to end the auth sessions in all relying parties you have accessed before you click the Logoff button then the STS will need to keep track of all apps you have used since your first log in. Then when you log out of SiteA then the STS will ‘contact’ SiteB to end the auth session there too.

You’ll recall from our discussion of the URL format for logging that it had the section ‘?wa=wsignin1.0’. There is a similar URL format for signing out: ‘?wa=wsignout1.0’. The client will send a GET request to the STS with this URL. The STS in turn will look up in its records which relying parties the user has logged in to since they first logged on. The STS will respond the client with a HTML that may look like this:

The client browser will contact all the relying parties in the message and send them a signoutcleanup message.

To recap:

The client clear his/her local auth cookie

The client contacts the STS

The STS clears its own session cookie

STSs replies with a page similar to the above markup

The client uses that message to inform the other relying parties about the logoff event

The relying parties clear their own auth cookies

Demo

Open the MVC4 appluication we’ve been working on in this series. Run the application and press F12 to open the Developer Tools just as we did before in the Claims series. Select Start capturing on the Network tab. On the home page of the MVC4 application select the About link to trigger a sign in. This time check the Remember Me checkbox:

The STS will set two cookies: idsrvauth and wsfedsignout:

The idsrvauth cookie is the logon session with the STS itself. The wsfedsignout cookie is a tool for the STS to keep track of the relying parties the user has logged into.

The STS will issue a cookie to establish a logon session with the client. You can see the FedAuth cookie issued by the STS in Developer Tools:

Close the browser running the MVC4 app on localhost and re-run the application. We do this in order to simulate two things:

The user wants to re-enter the same web app after closing it first

The user is trying to enter another relying party which uses the same STS for authentication

Click the About link to trigger the authentication. You should see the following:

You are redirected to the STS login page

The login page never actually loads

You are redirected to the About page automatically

This is the effect of the Remember Me checkbox. The STS recognises the previously established logon session with the user and does not require the login name and password again. The STS simply issues a new auth token.

This is the essence of Single SignOn and this is the solution for multiple relying parties on different web servers.

We now have to implement Single SignOut. Locate the LogOff action within AccountController.cs. Currently it may look similar to the following:

This will only end the auth session in the MVC4 web app but not at the STS. Test it for yourself: run the application, click on ‘About’ and after logging in click the Log off link in the top right hand corner. You have successfully logged out of the MVC4 app. However, click About again. You will be redirected to the MVC4 without having to log in. This may be a good thing in some cases, but a Log off should mean LOG OFF, right?

We first get a reference to the WS Federation authentication module. Then we clear the local cookie using the SignOut method. Then we construct a signout request message. The constructor requires the Issuer Uri and the Realm which will be read from the web.config. The WriteQueryString() method will form a valid ‘wsignout’ URL which will be understood by the STS. It will ‘know’ that the user wants to log out. You can set a breakpoint at ‘String queryString = signOutRequestMessage.WriteQueryString();’ to see what the signout request looks like.

Run the application and click the About link as usual. Click the Log off link and code execution should stop at the breakpoint within the LogOff action. You can now inspect the queryString variable and see what a signout URI looks like. We are redirected to the STS and we’re greeted with the following message:

You’ll see the ‘wsignout’ command and the ‘wreply’ which provides a way to return to the calling application.

Inspect the HTML source of the SignOut page of the STS. You’ll find the wssignoutcleanup command embedded in an iframe:

Click ‘Return to the application” and the select the About link. You will see that you have to provide your username and password again on the STS homepage meaning that we successfully killed off the auth session at the STS as well. The session was ended at all relying parties in the STS records as well.

This finishes up this blog post. The next one which will be the last post in this series about Claims in .NET4.5 will discuss the following more advanced topics: