Category Archives: ASP.NET

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 7

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 7: Logging in with Windows Live

If you want to enable users to login to your application with Windows Live, you to register an App like you have to with Facebook, LinkedIn, or Twitter. This means you first need a Windows Live account (which you get with Outlook.com among others). Follow the steps below to get your application running:

  1. Go to https://account.live.com/developers/applications/index and login if needed.
  2. If you have not created any Apps, you’re automatically redirect to the page to create an App.
  3. Give your application a name, as shown in the figure below.
    Application name dialog
  4. Click I accept. This brings up the API Settings, as shown below.
    API settings
  5. Enter the URL of the application in the Redirect domain textbox, and click Save.
  6. Open Visual Studio (if you don’t have already).
  7. Open the project created in Part 1 (or quickly create a project in the same manner).
  8. Find the App_Start folder and open AuthConfig.cs.
  9. Register the identity provider:
    1. In MVC go to the RegisterAuth method and add the following line of code:
      OAuthWebSecurity.RegisterMicrosoftClient("0000000048104C52", "Jm45Zcvj.........");
    2. In WebForms go to the RegisterOpenAuth method and add the following line of code:
      OpenAuth.AuthenticationClients.AddMicrosoft("0000000048104C52", "Jm45Zcvj.........");
  10. Save the file.
  11. Run the project.
  12. Click the Log in link. You will notice Microsoft has automatically been added next to the other providers you added under Use another service to log in.
  13. Clicking the Microsoft button will send you to Microsoft to log in.
  14. After you login, you are asked whether you want to allow the App access (see image below), and what the App may be able to see from your profile. In this case we aren’t doing anything with that information, but the App will receive a key that would allow it to get this information.

    Consent form

  15. When you click Yes, you are automatically sent back to the web application, where you will be asked to register the account as you learned in previous parts.

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 6

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 6: Logging in with Yahoo

If you want to enable users to login to your application with Yahoo, you don’t have to register an App like you have to with Facebook, LinkedIn, or Twitter. All you have to do is enable Yahoo as a provider. Assuming you already have a project setup, you do this as follows:

  1. Open Visual Studio (if you don’t have already).
  2. Open the project created in Part 1 (or quickly create a project in the same manner).
  3. Find the App_Start folder and open AuthConfig.cs.
  4. Register the identity provider:
    1. In MVC go to the RegisterAuth method and add the following line of code:
      OAuthWebSecurity.RegisterYahooClient("Yahoo!");
    2. In WebForms go to the RegisterOpenAuth method and add the following line of code:
      OpenAuth.AuthenticationClients.Add("Yahoo!", () => new DotNetOpenAuth.AspNet.Clients.YahooOpenIdClient());

    Note that is both cases you have to specify a display name. This is what’s shown in the page where the user selects the identity provider.

  5. Save the file.
  6. Run the project.
  7. Click the Log in link. You will notice Yahoo has automatically been added next to the other providers you added under Use another service to log in.
  8. Clicking the Yahoo! button will send you to Yahoo to log in.
  9. Login with a Yahoo account on the page shown below.

    Yahoo! Login screen

  10. When you sign in you are asked whether you want to sign in to the application with your account. The name of the application is shown in the text (red highlight).

    Yahoo! Consent page

  11. When you agree, you are automatically sent back to the web application, where you will be asked to register the account as you learned in previous parts.

Automatically generate Federation Metadata for your ASP.NET application

After having to generate Federation Metadata for the umpteenst time I decided it was time to deal with it once and for all. A tool like Thinktecture’s WS-Federation Generation Wizard is nice, but even that gets old after a while. Especially if you need to sign the metadata and the certificate is only on the hosting server. Fortunately, creating Federation Metadata for a passive endpoint is fairly easy, as the code below demonstrates. The code reads the current configuration from the system.identityModel section in web.config, so all you need to do is ensure it reflects your host configuration for a particular deployment (dev, test, acceptance, production). Of course you can manage that in Visual Studio with build management and config transforms.

private const string Saml10TokenTypeIdentifier = “urn:oasis:names:tc:SAML:1.0:assertion”;
private const string WsFederation12ProtocolIdentifier = “http://docs.oasis-open.org/wsfed/federation/200706″;

public string GenerateMetadata()
{
    return CreateMetadataString(CreateEntityDescriptor());
}

private EntityDescriptor CreateEntityDescriptor()
{
    var entityDescriptor = new EntityDescriptor();
    var applicationServiceDescriptor = new ApplicationServiceDescriptor();
    var config = FederatedAuthentication.FederationConfiguration;
    entityDescriptor.EntityId = new EntityId(config.WsFederationConfiguration.Realm);
    if (config.ServiceCertificate != null)
    {
        entityDescriptor.SigningCredentials = new X509SigningCredentials(config.ServiceCertificate);
        applicationServiceDescriptor.Keys.Add(GetSingingKey(config.ServiceCertificate));
    }
    applicationServiceDescriptor.ProtocolsSupported.Add(new Uri(WsFederation12ProtocolIdentifier));
    applicationServiceDescriptor.PassiveRequestorEndpoints.Add(new EndpointReference(config.WsFederationConfiguration.Realm));
    applicationServiceDescriptor.TargetScopes.Add(new EndpointReference(config.WsFederationConfiguration.Realm));
    entityDescriptor.RoleDescriptors.Add(applicationServiceDescriptor);
    return entityDescriptor;
}

private static string CreateMetadataString(EntityDescriptor entityDescriptor)
{
    var serializer = new MetadataSerializer();
    var stream = new MemoryStream();
    serializer.WriteMetadata(stream, entityDescriptor);
    stream.Seek(0L, SeekOrigin.Begin);
    return Encoding.UTF8.GetString(stream.ToArray());
}

private KeyDescriptor GetSingingKey(X509Certificate2 certificate)
{
    var x509Token = new X509SecurityToken(certificate);
    var x509RawDataKeyIdentifierClause = x509Token.CreateKeyIdentifierClause();
    var securityKeyIdentifierClause = new SecurityKeyIdentifierClause[]
                                            {
                                                x509RawDataKeyIdentifierClause
                                            };
    return new KeyDescriptor(new SecurityKeyIdentifier(securityKeyIdentifierClause))
    {
        Use = KeyType.Signing
    };
}

Fix: ClaimsAuthorizationManager.CheckAccess throws HttpException

While preparing a demo about Claims Based Authorization in .NET 4.5, I ran into an exception that initially had me dumbstruck. I created an ASP.NET MVC 4 application from the Internet template. Then I used the Identity and Access Tools for Visual Studio (downloadable from http://bit.ly/IDATVS2012) so users login through an external Identity Provider (for the demo LocalSTS). So far so good. Next I created a custom ClaimsAuthorizationManager class with a custom CheckAccess method to demonstrate how you can invoke this from code, essentially separating security checks from business logic. After hooking it up in web.config I run the code and after a wait I got an HttpException with the message Unable to connect to SQL Server database on a call to Principal.IsInRole, as you can see in the image below.

This had me puzzled to say the least. Why would a simple role check go to a database, especially because these are already in the Claims collection? First I tried commenting it out and just do a direct claim check… no dice. Why? The claims collection is empty. Huh? I have a page that lists the claims and they look fine. A closer look at the principal in the AuthorizationContext revealed it was actually of type System.Web.Security.RolePrincipal. That still inherits from ClaimsPrincipal, but it isn’t a normal ClaimsPrincipal, explaining the behavior. But now the big question: where did it come from? This took me a while to figure out with the help of a forum post (this one), ILSpy, and this blogpost by Phil Haack. As it turns out, the ASP.NET MVC 4 Internet template includes the WebMatrix.WebData DLL. This DLL, among other things contains classes used with the SimpleMembership API introduced by WebMatrix. SimpleMembership, which uses a database, is automatically enabled because the DLL uses PreApplicationStart method to initialize itself (as explained in Phil Haack’s blogpost). As soon as you place the WebMatrix.WebData DLL in your bin folder, it automatically registers itself. The result is that Thread.CurrentPrincipal yields a System.Web.Security.RolePrincipal instead of the ClaimsPrincipal associated with the user.

You could obviously remove the WebMatrix.WebData DLL, but there might be other functionality in there you want to use. A better option is to add the following key in web.config appSettings:

<addkey="enableSimpleMembership"value="false" />

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 5

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 5: Logging in with Twitter

As is the case with Facebook and LinkedIn discussed in previous posts, you need to register with Twitter. This means you have to get a Twitter account. With that account you have to register your application.

  1. Go to https://dev.twitter.com/apps and login with your Twitter account.
  2. Click the Create new application button.
  3. Fill out the form below. To avoid problems later, it makes sense to provide a Callback URL, even though it is not required.

  4. Accept the terms of use (Developer Rules of the Road), enter the Captcha and click the Create your Twitter application button. This will show the Details page shown below.

  5. In the page above notice that Sign in with Twitter has the value No. If you would now try to login users into your application, your server would get a 401 Unauthorized exception. To change this, go to the Settings tab and scroll down to the Application Type section. There you can check the highlighted checkbox in the image below.

  6. Click the Update this Twitter application’s settings button.
  7. Open Visual Studio (if you don’t have already).
  8. Open the project created in Part 1 (or quickly create a project in the same manner).
  9. Find the App_Start folder and open AuthConfig.cs.
  10. Register the identity provider:
    1. In MVC go to the RegisterAuth method and uncomment the following line of code:
      OAuthWebSecurity.RegisterTwitterClient( consumerKey: "", consumerSecret: "");
    2. In WebForms go to the RegisterOpenAuth method and uncomment the following line of code:
      OpenAuth.AuthenticationClients.AddTwitter(
          consumerKey: "your Twitter consumer key",
          consumerSecret: "your Twitter consumer secret");
  11. Replace the place holder text with the Consumer key and Consumer secret shown on the Details page of your application in Twitter (see image under step 4).
  12. Save the file.
  13. Run the project.
  14. Click the Log in link. You will notice Twitter has automatically been added next to the other providers you added under Use another service to log in.
  15. Clicking the Twitter button will send you to Twitter to log in.
  16. Login with a Twitter account on the page shown below. Notice that it is telling the user which application wants you to log in with your Twitter account, and what the application can do once you logged in. Twitter recognizes the application from the Consumer key, and provides the user with the information you entered earlier.

  17. When you sign in you are automatically redirected to the application.

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 4

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 4: Logging in with LinkedIn

Like with Facebook as covered in Part 3, you will need to register your application with LinkedIn before users can log in using their LinkedIn account.

  1. Go to http://developer.linkedin.com.
  2. In the menu select Support->API Keys, login when prompted.
  3. Click Add New Application.
  4. Next you need to fill out a form with quite some information in it. Fortunately most is straight forward. The image below shows the Company Info and the Application Info. Most important is the Application Name (in my case Michiel’s Security Demo), the Website URL (in my case http://michiel-security-demo.localtest.me), and Live Status. The latter indicating whether this is a development application or a live (production) application.

  5. Next up is contact information, which I’ll skip here, followed by the OAuth User Agreement. This is where you add information on what the user sees when logging in through linked in and where the user should be sent (in your application) when the user logs in (or cancels). In this case I’ll use the root URL of the application, because ASP.NET handles all that for me. Also notice I’ve set the Agreement Language to English.

  6. Agree to the terms of service and click Add Application.
  7. Next you’ll see a screen like the one below. You need the information shown to configure ASP.NET. You can get back to this information later by repeating steps 1 and 2, and then selecting the application you created. You will need the API Key and the Secret Key. The other two are only useful if your application uses the LinkedIn API (not covered here).

  8. Open Visual Studio (if you don’t have already).
  9. Open the project created in Part 1 (or quickly create a project in the same manner).

Now comes the tricky part. For starters, ASP.NET WebForms doesn’t have a neat method AddLinkedIn. There’s a fairly easy way around that using the generic Add method, but you’ll then find out what MVC users have already when they used RegisterLinkInClient: it doesn’t work! After logging in with LinkedIn your application will show one of the following messages:

  • MVC: Login Failure. Unsuccessful login with service.
  • WebForms: External login LinkedIn failed.

The problem is that the internal LinkedInClient class used by both MVC and WebForms isn’t quite correct, as Mr. Roa explains in this blogpost. Now, Mr. Roa’s solution works fine of you’re using ASP.NET MVC, but if you’re using WebForms, you’ll run into a new exception. For some reason verification of the authentication response sent by LinkedIn can’t be processed correctly. I’ve already spent quite some time digging through the underlying mechanics, but so far I haven’t been able to track down the problem. So if you’re using WebForm you’re out of luck. For MVC users just follow the steps Mr. Roa discusses and you’ll be fine.

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 3

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 3: Logging in with Facebook

  1. Login to Facebook.
  2. Go to https://developers.facebook.com/apps.
  3. Click the Create New App button.
  4. Go through the Captcha (if shown).
  5. In the dialog enter the App Name, in my case Michiel’s Security Demo, and a unique namespace. Then click Next (Doorgaan in Dutch).
  6. Next you need to fill out some information about your application. If all is well the Display Name, Namespace, and Contact Email are already prefilled. The only other thing really needed is a Site URL, which appears when you click the top check-icon.
  7. Save the settings to finish up on Facebook.
  8. Open Visual Studio (if you don’t have already).
  9. Open the project created in Part 1 (or quickly create a project in the same manner).
  10. Find the App_Start folder and open AuthConfig.cs.
  11. Register the identity provider:
    1. In MVC go to the bottom of the RegisterAuth method and uncomment the following line of code:
      OAuthWebSecurity.RegisterFacebookClient(
        appId: "",
        appSecret: "");
    2. In WebForms go to the bottom of the RegisterOpenAuth method and uncomment the following line of code:
      OpenAuth.AuthenticationClients.AddFacebook(
        appId: "your Facebook app id",
        appSecret: "your Facebook app secret");
  12. Set the appId and appSecret values in the code with the App ID and App Secret shown on the settings page of your application in Facebook (see image under step 6).
  13. Save the file.
  14. Run the project.
  15. Click the Log in link. You will notice Facebook has automatically been added next to Google (from Part 2) under Use another service to log in.
  16. Clicking the Facebook button will send you to Facebook to log in.
  17. Login with a Facebook account. You will then see a page like the one below. Notice that it is telling the user which application wants you to log in with your Facebook account. Facebook recognizes this from the App ID, and provides the user with the information you entered earlier.
  18. If you click Go To App (Naar app gaan) you’re sent to your website again. This also registers the App with the user, so he/she will not see the second screen again. The App will show up in the user’s account under My Apps, where the user can remove the App if he/she no longer wants to allow logging in through Facebook. This has to do with the fact that by accepting the App, the user also accepts that the App can read some information.
  19. If this is the first login with Facebook, you can create a registration for the Facebook account. Note: if you’re already logged in through the local database or another identity provider, you will be asked to add the Facebook account to your existing account.

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 2

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 2: Logging in with Google

Enabling your site for users to login with Google is extremely easy. It just requires you to uncomment a single line of code. There is no need for registration with Google or setting up some share secret, as is the case with the other identity providers.

  1. Open Visual Studio (if you don’t have already).
  2. Open the project created in Part 1 (or quickly create a project in the same manner).
  3. Find the App_Start folder and open AuthConfig.cs.
  4. Register the identity provider:
    1. In MVC go to the bottom of the RegisterAuth method and uncomment the following line of code:
      OAuthWebSecurity.RegisterGoogleClient();
    2. In WebForms go to the bottom of the RegisterOpenAuth method and uncomment the following line of code:
      OpenAuth.AuthenticationClients.AddGoogle();
  5. Save the file.
  6. Run the project.
  7. Click the Log in link. You will notice Google has automatically been added under Use another service to log in.
  8. Clicking the Google button will send you to Google to log in, which will show a page like the one below. Notice that it is telling the user which application (gained from URL) wants you to log in with your Google account.
  9. On the next page the user gets to see which information the application will get, in this case only the email address (and in Dutch in my case). The user can also indicate if this permission should be remembered next time.
  10. After clicking the approval button, you’re sent back to the application, where you can create a registration for the Google account. Note: if you’re already logged in through the local database or another identity provider, you will be asked to add the Google account to your existing account.

ASP.NET OpenID/OAuth Login With ASP.NET 4.5 – Part 1

With ASP.NET 4.5 it is very easy to enable users to login to your site with their accounts from Facebook, Google, LinkedIn, Twitter, Yahoo, and Windows Live. In this 7 part series I’ll show you how for each of the identity providers.

Note: Out-of-the-box this only works with WebForms and MVC4. MVC3 is not supported by default.

Part 1: Setting up your development environment

Create a website project in Visual Studio

You’re going to need a website project for any of this to work, and you may have to configure some of it later. So first, let’s create a project.

  1. Fire up Visual Studio (Express will work just fine).
  2. From the menu select FILE > New Project…
  3. Select one of the Web Application projects. In this example I’ll use ASP.NET MVC 4 Web Application.
  4. Click OK.
  5. Select Internet Application. This is the only template that includes the OpenID/OAuth stuff by default.
  6. Click OK.
  7. The project is ready. You may want to run it once just to make sure everything works. Be sure to click Register and then register for an account to see if the database is working.

Setting up your development environment

In most cases you need to register you website with the identity provider to be able to authenticate users with that identity provider. The provider will ask for several pieces of information, most notably a URL. The problem is that this can’t be an IP-address, and can’t be localhost. Most identity providers also don’t allow a port number, so you will have to ensure that your development website can be reached at port 80 (or port 443) and on a valid URL.

Getting a valid URL

Getting a valid URL is mainly about using a domain that an identity provider will recognize as valid and public. You can get one setup for your application in three ways:

  1. Modify your hosts-file to contain the desired URL.
  2. Open notepad as Administrator.
  3. Click File > Open and navigate to the C:\Windows\System32\drivers\etc folder.
  4. Select All Files (*.*) as filter so the files with no extension show up, as shown below.
  5. Open the hosts file.
  6. Add a line for IP-address 127.0.0.1 with the domain you want to use with your application, as highlighted below.
  7. Save the file.
  8. Use a public domain of your own and modify add a DNS entry for your application. How this works depends on your hosting provider, so I won’t elaborate in this.
  9. Use the localtest.me domain. This is a very neat trick by some clever guys. They’ve setup a DNS that will route any localtest.me request to 127.0.0.1, your local computer. That includes the root domain itself, but any subdomain or sub-sub domain (or sub-sub-sub domain… you get the idea), will work. The only domain that doesn’t work is http://readme.localtest.me, because that’s where you can find the documentation and background. The great thing is that this works without registering or anything. For my demo’s I will use http://michiel-security-demo.localtest.me.

Setting up IIS

Besides having a public domain, your application needs to run on port 80. Although this is possible with IIS Express, it is much easier using IIS (if you want to tinker with IIS Express, check Scott Hanselman’s post Working with SSL at Development Time is easier with IISExpress). The one proviso is that IIS can’t work with LocalDB, so you will have to use SQL Server (Express) instead. For the description below I will assume you have SQL Server Express installed. The best way to go about this is creating a new Web Site in IIS with a custom host header. The steps are easy:

  1. Start the IIS Manager.
  2. In the Connections pane navigate the tree to the Sites folder.
  3. Right click Sites and select Add Website…
  4. Set the Site name and under Physical path browse for the application folder created by Visual Studio.
  5. Under Host name set the host header, in my case michiel-security-demo.localtest.me.
  6. Click OK.

Now you need to point Visual Studio to use IIS, instead of IIS Express when you debug.

  1. Open your project in Visual Studio (if not already open).
  2. Right click the project and select Properties.
  3. Select the Web tab, and scroll down to where it says Use Local IIS Web server.
  4. Uncheck Use IIS Express.
  5. You will be warned that you can’t use LocalDB with IIS with the dialog below. Click Yes.
  6. Enter the Project Url, in my case http://michiel-security-demo.localtest.me/. The settings now should look like the image below.
  7. Click Save.
  8. Start the project in debug mode to verify that everything is working under the specified URL.

Although IIS points to the right folder, it needs permissions to read the folder. If that is not the case, you will get a HTTP 500.19 error when you run the application. You can solve this as follows:

  1. Open Windows Explorer.
  2. Navigate to the application folder.
  3. Right click on the application folder and select Properties.
  4. Go to the Security tab and ensure IIS_IUSRS has read permissions. If so, skip the next steps.
  5. Click Edit…
  6. Click Add…
  7. Enter IIS_IUSRS and click OK.
  8. Click OK twice.

Dealing with Token Timeout in Windows Identity Foundation

When a Security Token Service (STS) creates a token, that token has an absolute expiration. Usually this is about 60 minutes, after which the Relying Party (RP) has to send the user back to the STS to acquire a new token. When using Windows Identity Foundation (WIF) in ASP.NET (so for passive federation), this is the default behavior, because the SessionAuthenticationModule stores the token in the FedAuth cookie and checks that token on each request.

What’s the problem?

I hear you thinking “Cool, WIF takes care of all that for me”, and that is cool. But there’s also a nasty side effect, one which all web developers have encountered in a different context: sessions. If a user logs in, starts filling out some form, and then gets interrupted by a phone call, chances are that the session expires. This can lead to problems when the user submits the form, because the user has to log in again. The original posted data gets lost in the process, much to the frustration of the user. Because sessions use sliding expiration the problem is minor. But with absolute expiration, expiration can wreak havoc even if the user posts a form just a minute after the form was presented to the user.

Solving the problem

There are several ways to solve the problem outlined above:

  1. Don’t use the SessionAuthenticationModule.
  2. Modify the stored token to implement sliding expiration.
  3. Force reacquiring a token in the background, so you can control when this happens.

Ditching the SessionAuthenticationModule

Not using the SessionAuthenticationModule appears to be simple. Just remove it from web.config and you’re done. However, if you remove it, you have to ensure a user stays logged in after receiving the token, and you need to keep track of the received claims. This means you need to use a cookie or session data to keep track of the user. Basically you would be recreating what the SessionAuthenticationModule does for you for free.

Making token expiration sliding

This is actually easier than ditching the SessionAuthenticationModule. All you have to do is handle the SessionSecurityTokenReceived event and modify the ValidTo property of the token, as shown in this MSDN Forums post.
Tip: You can hookup the event in the Application_Start event in global.asx using FederatedAuthentication.SessionAuthenticationModule to point to the module.

Force reacquiring a token

The above methods work fine, but have some drawbacks. One of these is the fact that Single Sign-On (SSO) no longer works properly if a user spends too long in a single application. This is because the login session with the Identity Provider will expire at some point. Another issue arises if you want to use delegation or impersonation when you call a web service. WS-Trust 1.4 supports delegation (ActAs) and impersonation (OnBehalfOf). Even though WIF officially implements WS-Trust 1.3, WIF does support these constructs. When calling web services from a web application, using delegation is a recommended practice, because it greatly improves the security. The reason is that in order for the web application to make the web service call on your behalf, it needs to acquire a token from the STS, based on the original token. This means a malicious user would need that token in order to make the web service call. Breaking into the web application is not enough.

So, how can you ensure you get a new token once in a while? Although the implementation is somewhat more difficult, the principle is simple: logout of the RP. That triggers the RP to re-authenticate the user by redirecting to the STS. As long as the user is still known in the STS, a new token is transparently given out. You can do this in roughly two ways: in an invisible iframe that does this process under the covers or in the main request stream. The latter is more visible to the user and requires you to bring the user back to where he was before the logout was forced, which is slightly more complicated than a simple redirect. The iframe solution is more elegant, because it does not interrupt the main working process. Basically all you have to do is point the iframe to a handler that logs the user out if necessary, triggering the re-authentication process when necessary and coming back to the handler to produce an empty HTML page. The handler to do this is shown in the code below.

using System;
using System.Configuration;
using System.Globalization;
using System.IdentityModel.Tokens;
using System.Threading;
using System.Web;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Web;
namespace WebApp
{
    /// 
    /// HTTP Handler triggering token renewal when this is necessary.
    /// 
    public class TokenRenewalHandler : IHttpHandler
    {
        /// 
        /// The default number of minutes before the token expires when renewal should be triggerd.
        /// 
        private const int DefaultTokenRenewalWindow = 20;

        /// 
        /// Value container for the TokenRenewalWindow
        /// 
        private int m_TokenRenewalWindow = 0;

        /// 
        /// Number of minutes before the token expires when renewal should be triggerd.
        /// 
        /// Should be less or equal to the session timeout.
        protected int TokenRenewalWindow
        {
            get
            {
                if (m_TokenRenewalWindow == 0)
                {
                    int securityTokenRenewalWindow;
                    if (!int.TryParse(
                           ConfigurationManager.AppSettings["SecurityTokenRenewalWindow"],
                           NumberStyles.Integer, CultureInfo.InvariantCulture,
                           out securityTokenRenewalWindow))
                    {
                        securityTokenRenewalWindow = DefaultTokenRenewalWindow;
                    }
                    m_TokenRenewalWindow = securityTokenRenewalWindow;
                }
                return m_TokenRenewalWindow;
            }
        }

        /// 
        /// Handles the HTTP reqyest and forces a signout to renew the token if necessary.
        /// 
        public void ProcessRequest(HttpContext context)
        {
            SecurityToken token = null;
            IClaimsPrincipal principal = Thread.CurrentPrincipal as IClaimsPrincipal;
            if (principal != null && principal.Identities.Count > 0)
            {
                token = principal.Identities[0].BootstrapToken;
                if (token != null)
                {
                    DateTime tokenExpirationTime = DateTime.Now.ToUniversalTime().AddMinutes(TokenRenewalWindow);
                    if (token.ValidTo.ToUniversalTime().CompareTo(tokenExpirationTime) < 0)
                    {
                        if (FederatedAuthentication.WSFederationAuthenticationModule != null)
                        {
                            // Force sign-out.
                            FederatedAuthentication.WSFederationAuthenticationModule.SignOut(false);
                        }
                        // Redirect to this handler to force a new sign-in request to the STS
                        context.Response.Redirect(context.Request.RawUrl, true);
                    }
                }
            }
            // Return an empty HTML page
            context.Response.ContentType = “text/html”;
            context.Response.Write(“”);
        }

        public bool IsReusable
        {
            get { return false; } }
    }
}