The problem with Azure ACS and Live ID

One of the nice features of Azure is ACS. Basically, Microsoft has attempted to make it easy for developers to integrate third-party identification systems (Live ID, Yahoo!, Google, Facebook, etc.) into web applications. I say attempted, because like many Microsoft products figuring out how to use it is going to involve wading through a lot of confusing, incomplete, outdated, and/or downright inaccurate web tutorials and documentation. That said, once you've worked through it once or twice, it really is pretty easy to get your application up and running with a third-party identification service.

This is fantastic for web application developers; it saves us from having to deal with collecting and protecting yet another set of user passwords, something that we are all, on balance, terrible at.

ACS does a few othings really, really well. For one, it makes handling multiple identity providers a snap. And dropping a new provider into an existing application is pretty much painless. It's also very development environment friendly; it actually works with 'localhost' as relying-party, and doesn't force you to do any hosts file magic to get development and test setups working.

Unfortunately, there's one huge pain point in all this: Windows Live ID.

It seems like it should be simple: Microsoft controls both Azure ACS and Windows Live, so the integration between the two should be a snap. And it is ... sort of. Windows Live ID is one of the default providers (along with Google and Yahoo!) that you can set up in ACS with just a few clicks. Once you've figured out which tutorials to follow, you can get a project set up with a login using these three providers in no time.

Now, I can't speak to Yahoo! integration, because I immediately turned that off (does anyone have a Yahoo! account anymore?). But the first thing I did after getting Google and Live running on EZReader was to create a Users table in my database so I could associate people with their feeds. Then I went to the claims provided by each account so I could link them to a database user.

With Google's provider, this is obvious - just use the email. The Google provider gives you the email address of the account along with the person's name. Simple.

Live, on the other hand, just gives you a unique id string. Nothing else. I mean, literally nothing - no email address, no name, nothing. Now, technically, this is sufficient. It's the same id every time that account logs in, so you can track that in your application and you'll be fine. It means you don't have any info to use for personalization (no, "Welcome, Bob!" once the user is logged in), but that's not a big deal - after all, if you want to collect more information on a separate form and associate it with the id, you're free to do so. So personalization is a solvable problem.

As to why Live works this way when every other provider seems to give out (at least) the email address, well, it's a security issue. And technically, they're right. Here's a pretty good defense of the practice, and I agree in principal. In practice, however, there's a flaw to this logic that I didn't see until the other day when a friend signed up for EZReader with his Live account.

See, some people have multiople Live accounts. You have a live account if you're an MSDN subscriber, an Xbox Live user, a Windows Phone user, a Microsoft Certified Professional, and several other services that Microsoft provides. It's possible to have one Live ID for all of these services; I still use my original Passport.NET ID from my first MCP test (it's morphed into four different email adddresses and two or three marketing names from MS in the interim). But not only can it be difficult to use the same ID for all the services (it's not always clear that your Xbox Live account and your MCP account are the same thing, for example) - in some cases, you have legitimate business reasons to have separate IDs. My friend owns parts of multiple companies, and needs an MSDN subscriber ID for both of them. And that's where the problem arises - he was already sign in to Live when he logged in to EZReader for the first time, but he didn't know with which account. So an ID was created for him in the EZReader system, but with no way to identify which account he was using.

Seriously, there's no way to know. The ID generated by Live for an application is unique to that application. There's no trail back to the original Live ID, no way to correlate it unless you're Microsoft. And I had no way to display a name or email address for this user, so he had no clue which account it was.

In the end, the only solution was to add Live ID app integration (basically, the Live OAuth implementation) to my applications so that when a Live user signs up, I can ask for permission to get their email address. That way, I can display the email address in the "Logged In As" section of the page. This adds a whole lot of complexity to my signup process for Live users, but at least they'll know which account they're using.

There's one other bit of annoying weirdness to this process - scopes. The Live API provides for different access scopes for applications; basically, it's the set of things your application is asking to access when they sign up. Now, for my purposes I need the user's email address and nothing else. I don't want to access their Skydrive or their list of contacts or their birthday or anything else. But there is no scope for "just give me the email address". The closest thing available is "wl.basic", which gives me access to their email and their list of contacts. So when someone signs up for EZReader with a Live account, it tells them that the application needs access to their contact list, which seems pretty suspicious for a feed reader. But I don't have any other good scope option.

I originally included Live as a sign-in option for the service because ACS seemed to make it very simple; it seemed like a no-brainer to check the box and use it. In the end, it's taken far more development time than the Google provider, and the experience still isn't great. Unless you've already got a high demand for Live integration in your service, I'd recommend skipping it for now.