I’ve spent some time the last couple of days working with the new Azure B2C features and have had the chance to get some things working, as well as note a couple of things that you want to be aware of as you start playing with this yourself. The Azure B2C feature is the first really strong play towards obsoleting Microsoft ACS, or Access Control Services. Prior to B2C, the ACS service was the only Microsoft-hosted identity service that let you create identity provider relationships with social identity providers such as Facebook and Google. It’s an aging platform however, and one that Microsoft has publicly said is on the way out. Since they came out with that statement, folks have been between a bit of a rock and hard spot when wanting to use these social identity providers. You could write your own, use a paid identity hub service like Auth0, or spin “something” up on ACS, knowing full well that its end of life was coming. Even at that, on ACS the connectivity with Google to create new identity provider relationships broke last year so things were not looking good.
The Azure B2C feature now slides into public preview up on Azure. It provides hooks today to let you authenticate using Facebook, Google, Amazon and LinkedIn, as well as any local accounts you have in your new B2C Azure Active Directory. Support for Windows Live accounts ironically is not there yet, but the team has said that it is coming. Along those lines, here’s a couple of links that you should check out to really get started and dig your teeth into this:
- Blog post announcing new B2C and B2B features: http://blogs.technet.com/b/ad/archive/2015/09/16/azure-ad-b2c-and-b2b-are-now-in-public-preview.aspx
- Steps to create a new Azure AD B2C tenant (you can’t just “add” the feature to an existing Azure AD tenant – maybe that will change in the future): http://azure.microsoft.com/en-us/trial/get-started-active-directory-b2c/
- See and build some sample apps that are secured with Azure B2C: https://azure.microsoft.com/en-us/documentation/articles/active-directory-b2c-overview/
While there are some good links to get you started, I wanted to focus on some of the early rough edges so you can hopefully get up and running just a little bit quicker. I’ll preface this by saying the Azure team has really has their stuff together pretty well. There’s videos, sample apps, blog posts, and some good documentation. They also say that they are supporting it via forums on StackOverflow.Com, although so far my one post up there has been getting just a bit lonely. We’ll see. In the meantime, let’s move on to some things to keep in mind.
Sample Code Problems
You may work through the sample applications to build out your own site, which is the logical way to test it. In my case I built a standard VS 2015 ASP.NET MVC application so I followed along that sample. I actually only had to copy one set of files over from the Github sample that they use, which is a folder called PolicyAuthHandlers and the set of classes it contains. When I thought I had it all built out, I ran it and quite quickly got the dreaded yellow screen of death (i.e. an unhandled exception). I spent some time poking through this and realized that there is a problem in the Startup.Auth.cs file, in the OnRedirectToIdentityProvider method. Specifically, this line of code fires when you first authenticate as we try and figure out which Azure B2C policy to use (you can read more about policies in the links above):
OpenIdConnectConfiguration config = await gr.GetConfigurationByPolicyAsync(CancellationToken.None, notification.OwinContext.Authentication.AuthenticationResponseChallenge.Properties.Dictionary[Startup.PolicyKey]);
The problem is that the notification.OwinContext.Authentication.AuthenticationResponseChallenge property is null, so the whole thing blows up. For now, I’m working around it by replacing this parameter (which is just the name of the policy to use) with this other static string you’ll find in the sample code: SignUpPolicyId.
You Get a 404 Response When You Try and Authenticate
After you fix the sample code problem, then you will likely find that when your browser gets redirected to authenticate, it throws a 404 error (or more precisely, Azure throws the exception). After much digging around on that one, I finally realized that they had created a bad query string for me to login with. Specifically, it contained two question marks. In web land, that means it ignores all parameters after that second question mark. The second question mark needs to be an asterisk, and then everything moves right along. Here’s a screenshot of what the URL looks like:
I’ve highlighted the two question marks to make the easier to spot. The way to fix it? So far, each time I authenticate, I wait for the 404 error and then I manually go in and change it in the browser address bar. So I just change the second question mark to an ampersand, hit enter, and away I go.
UPDATE 9/23/15: Clarky888 was good enough to point out on StackOverflow.Com that this problem is fixed if you update your reference for Microsoft.IdentityModel.Protocol.Extensions to v18.104.22.168221351. I did this and found that everything works quite well now.
You Get a Login Error About the User Already Exists
One of the problems with my “fix” for the first problem I described in this post is that I set the policy that should be used to one that is only supposed to be fired when you are creating a new account. By “creating a new account”, I mean you are logging into the site for the first time. You can log in with whatever social identity provider you want, and then Azure B2C creates what for now I’ll call a “shadow account” in the Azure B2C AD tenant. For example, after I logged in with all of my different social and local accounts, here’s what my list of users looks like in my Azure B2C AD tenant:
So in the fix to the first problem, I described changing the second question mark to an ampersand. Well, the first query string parameter is the name of your B2C policy that’s going to be used. So in my case, I’m hard coding it in my Startup.Auth.cs file to use my sign “up” policy. However, I also have a different policy for accounts that already exist, called my sign “in” policy. In the address bar picture above you can see the name of my sign up policy is b2c_1_firstdemosignup. So for a user that has already signed up, when I get that 404 error I change the name of the policy as well as the second question mark. I just type over the last two characters so my policy name is b2c_1_firstdemosignin and then change the next character from a question mark to an ampersand, hit enter, and we’re working again. This brings up the “money” shot so to speak – here you can see all of my identity providers alive on my Azure B2C sign in page:
For this post I decided to log in with Amazon…mostly because I’ve never used Amazon as an identity provider before so I thought I would breathe deeply on all the oauth2 goodness. Here’s the login dialog from Amazon after I select it as my identity provider:
Once I sign in then I have a little code that just enumerates the set of claims I have and spits them all out on the page for me. Of course it’s big and ugly, which I think is exactly the kind of work you all have come to expect from me. 🙂
There you go – there’s your end to end login experience with Azure B2C. Pretty cool stuff.
Other Miscellaneous Issues
There are a couple of other little “things” that I noticed that might be worth remembering as well; here they are:
- It doesn’t recognize the username / password of my account that’s a global admin on my Azure AD B2C tenant. This is a bit of weird one, but I think I know why. To back up a little, as I mentioned earlier, you have to create a new Azure AD tenant and when you do, configure it as a B2C tenant. So you log into the Azure management portal and go through that exercise. When you do, it adds the account you are currently logged in with as the global admin of the new Azure AD B2C tenant. However, it doesn’t actually create an account (and corresponding password) for it in that tenant – it just notes that it’s from a different Azure AD tenant. That’s why I think it won’t let me log in with that account. Kind of sorta makes sense in a certain Microsoft “by design” kind of way.
- You can add custom claim types in your B2C tenant. So for example, I added “favoriteTeam” and “favoriteSport”. However the claim type that Azure sends to you precedes all of your custom attributes with “extension_”, so “favoriteTeam” becomes “extension_favoriteTeam”. I mostly add this so you are aware of it when making authorization decisions based on custom claim values. I don’t know if this will change for RTM or not, but I guess we’ll find out together.
- It doesn’t seem to pass along the access tokens (if provided) by these social identity providers. For example, with ACS if you logged in via Facebook it also passed along an access token from Facebook in your claims collection. That was really sweet because you could then extract out that access token and use it to make calls to the Facebook Graph API. That functionality is not in there today, not sure if it will be when it’s released. It was a very nice feature, so hopefully it will make a comeback.
That’s it – there’s my first look at Azure B2C. I’ll be working with it more and adding some other posts about it in the future. As always, you can reach out to me at firstname.lastname@example.org with your own observations, comments and questions…or just post ‘em here so everyone can see them. 😉