ACS integration with Windows Live ID & Facebook Connect

I’ve received several requests regarding ACS and Windows Live ID integration for websites. This post describes what you can do with ACS and Windows Live ID today (with the new release of ACS). It takes a bit of code, but the integration is pretty straightforward.

Note that this code isn’t hardened and it relies heavily on server side code. I’m showing it as an architectural sample, and I’m showing it now based on the number of requests I’ve received for the sample. In the future, I’ll work on a better sample that’s easier to setup (and possibly one that uses javascript & cross domain iFrames).

I’ll be discussing WLID Web Authentication as an integration point. The same basic model can apply to other WLID capabilities and other web identity providers. The code sample also has Facebook connect integration, but I won’t go into any detail about how it works in this post (in the future I will).

The basic model is fairly simple. The swim lane and description is shown below.

clip_image002

1. A user browses to your website and clicks a login button.

2. This button redirects the user to the WLID Redirector. The code for this redirector is in this post. For now, you’ll need to write and host this code yourself.

3. The redirector redirects the browser to the WLID login page with correct WLID AppID. From there, the user logs into WLID using their credentials.

4. Upon a successful login, WLID returns the browser to the redirector. The response contains a unique pair-wise ID for that user.

5. Once the redirector receives the user ID, it packages that ID into an ACS token request (OAuth WRAP request for an Access Token)

6. ACS will issue a token for that user and return it to the redirector (the token is a SWT).

7. From there, the redirector will return the ACS token to the website

8. The website will validate the token. If validation passes, the website will write the token to a cookie.

9. (Not shown on the diagram) On subsequent requests to the website, the website will use the cookie to authenticate and authorize the user.

10. (Not shown on the diagram) If the user logs out, the website will clear the cookie and send the browser to the redirector. From there, the redirector will send the browser to WLID for logout. This will remove the WLID cookie for that website.

Setup Steps IdpRedirector project

1. First, you’ll need to have a domain name for the redirector. You can host the redirector in Azure, or your own server. The site needs to have a public address.

2. After you have the address, go to the Live ID developer portal at https://go.microsoft.com/fwlink/?LinkID=144070

3. Setup your WLID developer account. The steps are at https://msdn.microsoft.com/en-us/library/bb676626.aspx.

The only trick here is to be very careful about the return URL. For this sample, you’ll want to enter https://<yourdomainname>/wlidfederation-handler.aspx, where <yourdomainname> is the hostname + any subdomains for your redirector.

4. Copy the Application ID and Secret shown below

clip_image004

5. Open the VS solution in the zip at the bottom of this post.

6. In the WebRedirector project, open the web.config and edit the values below with your Application ID and secret.

 <add key="wll_appid" value="yourappid"/>

<add key="wll_secret" value="yoursecret"/>

7. Change the rploginpage and rplogoutpage to the URL for the RelyingPartyWebsite project. I used Cassini in this project, so your port number will likely change.

 <add key="rploginpage" value="https://localhost:32210/RelyingPartyWebsite/login.aspx"/>

<add key="rplogoutpage" value="https://localhost:32210/RelyingPartyWebsite/logout.aspx"/>

8. Update the ACS specific settings.

 <add key="serviceNamespace" value="updateToYourServiceNamespace"/>

<add key="clientIssuerKey" value="updateToYourIssuerKey"/>

<add key="clientIssuerName" value="updateToYourIssuerName"/>

<add key="tokenPolicyKey" value="updateToYourTokenPolicyKey"/>

<add key="acsHostName" value="accesscontrol.windows.net"/>

<add key="applies_to" value="updateToYourAppliesTo"/>

9. Upload the project to the domain specified in (3)

Setup Steps RelyingPartyWebsite project

10. Open the web.config of the RelyingPartyWebsite in VS. Update the appSettings below to the settings for your ACS Service Namespace & the domain of your IdPRedirector.

 <add key="idpRedirectHost" value="updateToYourRedirectorHost"/>

<add key="serviceNamespace" value="updateToYourServiceNamespace"/>

<add key="tokenPolicyKey" value="updateToYourTokenPolicyKey"/>

<add key="acsHostName" value="accesscontrol.windows.net"/>

<add key="applies_to" value="updateToYourScopeAppliesTo"/>
Running The Sample

11. Start the RelyingPartyWebsite and browse to the Default.aspx page. You should see something like the following:

clip_image006

12. If you click on the WLID icon, you’ll be redirected to the IdPRedirector, then to WLID. Enter your creds at WLID & you should be redirected back to the IdPRedirector, then to the login.aspx page in RelyingPartyWebsite. If all is well, you’ll see something like:

clip_image008

Here’s the code sample:

Comments

  • Anonymous
    January 31, 2010
    The comment has been removed

  • Anonymous
    February 03, 2010
    Do you have an example that works with Wrap v0.9? Wrap v0.8 is not supported anymore :( Thanks!

  • Anonymous
    February 12, 2010
    The sample needs the following updates to work with WRAPv0.9. Global:

  • Replace all instances of "applies_to" with "wrap_scope" IdPManager.cs:
  • Replace "WRAPv0.8" with "WRAPv0.9"
  • Replace "wrap_token" with  "wrap_access_token" TokenValidator.cs:
  • Remove "WRAPv0.8" from trustedTokenIssuer URL Note that TokenValidator.cs is in both IdPRedirector and RelyingPartyWebsite.
  • Anonymous
    February 16, 2010
    Thanks for your help, however I had already figure out the changes after looking at MS doc. It still doesn't work. When GetACSToken is called after I log in to Windows Live, I get a http error 400 Bad Request. More specifically it crashes when I call client.UploadValues("WRAPv0.9", "POST", values); I looked at all the values passed in that UploadValues method and it looks fine to me. Have you ever got that error? Do you have any hint about what it could be? Thanks

  • Anonymous
    February 16, 2010
    I'm curious what the error message is. Have you tried to look at the response body of the error? For info on how, check the bottom of this page: http://msdn.microsoft.com/en-us/library/ee706734.aspx

  • Anonymous
    February 18, 2010
    Haaaa! I didn't know you could get the info from the response... that's the first time I see information on that trick. I suggest you update your sample to include that little "catch" in the code. It'll be definitely easier to troubleshoot... I will try it and get back to you. Thanks for your help

  • Anonymous
    February 18, 2010
    ok my error is T1016:Detail:An output claim token cannot be issued because the issuer and claims in the request do not map to any output claims for this scope. Could it be because I created a rule? I shouldn't?

  • Anonymous
    February 20, 2010
    Got it working! It was because I hadn't created the rules correctly. This helped me a lot : http://blogs.msdn.com/justinjsmith/archive/2009/11/15/mgmt-config-sample-for-wlid-facebook-connect-sample.aspx I basically recreated my passthrough rules correctly. I suggest you include it in your sample. Thanks for your help!

  • Anonymous
    February 20, 2010
    Now do you guys know how I can get more than the wlid of the user? I would like to have minimally the email/username of the user. Can it be done? Does it have to be through the Contact API?

  • Anonymous
    May 10, 2010
    This is very helpful but I don't think that it can really be considered authentication. Unless I know the name of the person that authenticated I only know that they authenticated SOME Live ID, not the one that I care about. There may be some scenarios where that is interesting but I don't think that it is the most common case.

  • Anonymous
    October 05, 2010
    I have been trying it for a long time. I am using September release of ACS Labs.Everything works great but sign out. How do i implement sign out if i am using multiple identity providers. To keep the things simple i add a FederatedSigninStatus Control and I display it only when Page.User.Identity.IsAuthenticated is true. So when a user i logged in I click on Sign Out for FederatedSigninStatus it does reset the value of Page.User.Identity.IsAuthenticated to false. It means that user is signed out, but this is not the case. Because, if i again click on sign-in and delect the same IP as before is just logs me in without even asking for credentials. Even if i close the browser and open the site agian, same thing happens, it doesnt ask me for credentials. I have tried deleting all the Response cookies in the SigningOut event of FederatedSigninStatus Control and then calling Signout. But, this also doesn't work. However, if i am running my application from Visual Studio and then sign out it still doesn't work. But if is top debugging and run it again it runs fine. Seems like VS resets something. What is that i need to reset so that i can sign out completely?

  • Anonymous
    November 02, 2010
    freak, You are most likely not clearing your cookies. When you say that you removed them, do you mean you call the Remove method on the Response.Cookies collection? That won't remove the cookie in the browser. What you want to do is set its expiration to an earlier date.

  • Anonymous
    November 02, 2010
    I am setting expiration date to previous date only.

  • Anonymous
    May 31, 2011
    Thanks for the sample! I'm curious if you know of a way of programatically TEST a web app that uses ACS to integrate with Live ID? I want to write a test that simulates the browser and logs in to my app as a certain Live ID user. It gets redirected to Live ID, logs in there, then obtains claims from ACS and presents the token to the app. Browser does that easy, but I haven't been able to figure out how to make that work from code, so any pointers would be awesome.

  • Anonymous
    July 08, 2014
    Would you be able to show me the exact HTTP messages exchanged between the relying party, OpenID provider and Azure?  I'd like to know the query strings in the URLs as well as any JSON or other content sent with the message to better understand what is happening.