Category: Authentication

App Service Easy Auth with Auth0 (or any Open ID Connect provider)

So I’m going to prefix this with a warning – I doubt this is officially supported but at a basic level it does seem to work. I would use at your peril and I’m writing this in the hope that it makes for a useful starting point discussion with the App Service team.

I was looking at Easy Auth this week and found myself curious as to if it would work with a generic Open ID Connect identity provider. My first choice provider is Auth0 but that’s not one of the listed providers on the Easy Auth configuration page which, on the face of it, is quite limited:

Azure AD is (as well as many other things) an Open ID Connect Provider so I had a look at its settings in the advanced tab and its asking for two pretty common pieces of information in the identity world: a client ID and an issuer URL. I had an app in Auth0 that I use for general testing so I pasted in its well known configuration endpoint and the ID for my client:

I hit save and it seemed to accept everything. My web app is sat on the URL https://jdreasyauth0.azurewebsites.net/ so on the Auth0 side I added a callback URL to the Easy Auth callback endpoint:

Easy Auth forwards on the contents of common claims in headers such as X-MS-CLIENT-PRINCIPAL-ID (the subject) and X-MS-CLIENT-PRINCIPAL-NAME (the name) so to see if this was working I uploaded a simple ASP.Net Core app that would output the contents of the request headers to a web page. Then I paid it a visit in my browser:

Oh. So that’s hurdle one passed. It does redirect successfully to a none-Azure AD identity provider. What about logging in?

Great. Yes. This works too. And the headers are correct based on the identity I used to login with.

How does this compare to the headers from an Azure AD backed Easy Auth:

Basically the Auth0 login is missing the refresh token (I did later set a client secret and tweak configuration in Auth0) – so there might be some work needed there. But I don’t think that’s essential.

It would be incredibly useful to be able to use Easy Auth in a supported manner with other identity providers – particularly for Azure Functions where dealing with token level authorization is a bit more “low level” than in a fully fledged framework like ASP .Net Core (though my Function Monkey library can help with this) and is only dealt with after a function invocation.

My Number One Tip for Working With IdentityServer3

It’s a real simple one but honestly a real time saver:

Turn on logging

IdentityServer3 is a great piece of software with excellent documentation but the identity space is inherently complex and gets quite fiddly quite quickly. Fortunately if you turn on the logging the output is rich and incredibly useful.

I was working on standing up another STS this morning based on it and was just cracking through it thinking “yeah I know this” and hadn’t bothered to turn on logging. Pride, of course, always comes before a fall and so of course I hit a weird and inscrutable problem: the STS let me log in with Google but then never redirected back to my application. Spent a little while thrashing around then remembered my own number one tip, turned on logging, and there in the trace window was the source of my problem (in my case I hadn’t run the new client properly through my custom user service and wasn’t marking users as active in a particular work flow).

Turning it on is really simple. All you need to do is add a NuGet package for one of the supported loggers and configure it. In my case I use Serilog and the code for configuring it is as on the IdentityServer3 website:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Trace()
    .CreateLogger();

Authenticating AngularJS against OAuth 2.0 / OpenID Connect

I’ve recently found myself doing quite a bit of work putting in place an STS (Security Token Service) based around the excellent Thinktecture IdentityServer 3. I have a variety of different client types that need to authenticate including JavaScript Single Page Applications using the AngularJS framework.

IdentityServer 3 implements the Open ID Connect protocol for clients to authenticate against, Open ID Connect being an extension to OAuth 2.0.

There’s an existing open source plugin for authenticating with OAuth 2.0 called oauth-ng that utilises the implicit authentication flow that I wanted to use however I wanted some different behaviour and was interested in implementing my own plugin as a learning exercise with the protocol itself and with AngularJS. Massive credit to the author of that plug-in for inspiration and readable code, this is the first non-trivial AngularJS directive I’ve developed and so it was incredibly useful to be able to look at oauth-ng and riff off it’s design. As another reference the Adal-Angular project was also really useful.

The main features of the plugin I’ve developed are:

  • Sign in / sign out button
  • Specify which routes require a token for access to protected resources and automatically handle sign in if required when they are accessed
  • Storage of the token in the browsers session storage via the ngStorage module
  • Automatic insertion of a bearer token into HTTP requests once a user has authenticated

The plug-in can be found on GitHub here. It works and I’ve tested it against both Thinktecture IdentityServer3 and Google’s OAuth2 endpoint but is still quite early code in terms of testing and so if you encounter any issues please do log them on the GitHub issues page or submit a pull request with a fix.

All the code samples given below are from the sample app which is basically the Yeoman generated scaffold and that you can find on GitHub here and which I’ve configured to authenticate directly against Google. You will need to obtain your own client ID and configure Google as per the instructions here.

Getting Started

You can either grab the scripts from GitHub or, more easily, install the plugin as a bower package which you can install as follows:

bower install angularjs-oauth2 --save

First you’ll need to add the module to your applications list of dependencies in app.js and you need to make sure that ngStorage is also included:

angular
  .module('angularJsApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngStorage',
    'ngSanitize',
    'ngTouch',
    'afOAuth2'
  ])

The default template that is supplied for the sign in / out button expects to be placed inside a bootstrap navbar.

Typically in the above example you would select a scope appropriate to the resource you wished to access (if that terminology is confusing then I have a series of blog posts on the way as an intro to Open ID Connect and OAuth 2.0) – I’ve just picked one that we’ll have access to without additional configuration.

Now let’s modify the app.js file so that clicking the About link will require the user to be signed in:

.config(function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl',
        requireToken: true
      })
      .otherwise({
        redirectTo: '/'
      });
  });

Note the addition of requireToken:true to the route for about.

Now run the app (if you’re using the yeoman builder like myself then type grunt serve). You should see something much like the following appear in your browser:

indexScreen

The only difference from the standard Yeoman template (at least at the time I wrote this) is the Sign In button at the top right. If you click that, or the about link, then you should be redirected to the Google sign in page that looks like this:

signonSuccess

If you’ve not got things wired up “just so” in the Google console then you’ll see an error. Generally they are reasonably informative and normally, in my experience, the redirect URI in the console doesn’t quite match the redirect URI in the app (they’re sensitive over things like the / on the end or not).

After signing in the token will be added as an Authorization header to all http calls using the ‘Bearer my token’ format and so any calls you make to a remote resource that require authorisation will be supplied the token they need to verify the user.

Options

The oauth2 tag has a number of attributes that can be specified as follows.

authorisation-url: The URL to request the token from.
client-id: The client ID to supply to the token provider.
redirect-url: The URL the token provider should redirect to on a successful sign in.
response-type: Optional. The required token type. Defaults to token.
scope: The resources that access is requested to.
state: A magic number to send to the token provider to protect against CSRF attacks.
template: Optional. URL of a Angular template to use for the sign in / out button in place of the built in template.
buttonClass: Optional. Defaults to “btn btn-primary”. The class to apply to the button in the standard template.
signInText: Optional. Defaults to Sign In.
signOutText: Optional. Defaults to Sign Out.
signOutUrl: Optional. The URL to call to ask the token provider to perform a sign out. See notes on sign out below.
signOutAppendToken: Optional. Defaults to “false”. If set to “true” then the access token will be appended to the signOutUrl.
signOutRedirectUrl: Optional. The URL that the token provider, if it supports redirects, should redirect to following a sign out.

Signing Out

Signing out in the OAuth world can be… complicated. When the user presses the sign out button presented by this plug in the token that is stored in session storage is cleared and as we’re using session storage as soon as the session ends (window or tab closed) then they’ll be logged out.

However they may still be logged in with the token provider depending on how the token provider behaves and the options the user has selected their.

This plugin does allow a URL to be supplied to initiate a logout at the token provider where the token provider allows for that but if the token provider is using a persistent cookie and the user shuts the window without clicking sign out then they could remain logged in.

It’s worth thinking about if / when you choose to use OAuth.

ASP.Net Identity Provider 2.0 and Table Storage

I’ve started to implement the new storage interfaces in AccidentalFish.AspNet.Identity.Azure so you should be able to use the new features of Identity Provider 2.0 with table storage.

I’ve added an MVC5 project that shows how to configure the provider.

It’s not fully tested yet but if you come across any bugs please log them on GitHub and I’ll get right on it. Once complete I’ll publish the new version on NuGet.

How To: Using Facebook to Authenticate with Web API 2 in a Native Mobile Application

If you’re developing mobile applications and you’re a .Net developer there’s a fair chance you’re using Web API to present access to server side resources. I’ve already covered how to authenticate using organisational accounts with MVC 5 which is a good choice for many applications, particularly business apps, but if you’re working in the consumer space you may want to allow your users to login using social media identities such as Facebook or Twitter.

There’s a really good tutorial on the ASP.Net web site covering how to do this if you’re working in a browser but it doesn’t, directly at least, cover how to do this from a native mobile application. In this post I’m going to take you through the steps required to do this from an iOS application written using the Xamarin tools (if you’re a C# developer working on mobile they are very much worth checking out). I’m going to focus on Facebook but the same approach works for the other providers supported by Web API 2: Facebook, Twitter, Microsoft Accounts and Google Accounts are all supported straight out of the box.

The below walks through the process of configuring Azure, Facebook, a Web API project and a Xamarin mobile application, you can walk through it for the most part (there is the odd missing step – instance variable declarations for the most part) but really it’s intended as a guide to go along with the source code that is on GitHub here.

We’re going to host our Web API on Azure so begin by going to the Azure management portal and create yourself a free website. Take a note of the URL as you’ll need it later. Also create an empty SQL Database either on a new or existing server and take a note of the credentials, you’ll need this later.

Configuring Facebook

Firstly you need to create a Facebook application in the Facebook developer portal (http://developer.facebook.com). From the developer portal homepage select Apps -> Create a New App and enter the Display Name for your app and the Category applicable to your app and click Create App. At the time of writing there is a bug in the portal and after it finishes whirring away the dialog box stays on the screen, but your app has been created. Refresh the browser and select the Apps menu again and click the name of your app (that you should now see there). You should see a screen like this:

external1

Take a note of the App ID and the App Secret as you’ll need them later (click the show button to see the App Secret) and then click the Settings option on the left to show the settings screen for your app:

external2

Now click the Add Platform button and choose Website. In the Site URL text box enter the URL you noted earlier from Azure and click Save Changes:

external3

That’s Facebook configured to allow your application to logon so now we’ll go and create our Web API project and wire it up to Facebook.

Web API / Visual Studio

In Visual Studio 2013 create a New Solution and select a project type of ASP.Net Web Application for .Net 4.5.1. On the configuration dialog that appears select Web API and then click the Change Authentication button. Select an authentication type of Individual User Accounts. Your project configuration should now look like this:

external4

Click OK and your solution will be created with the familiar MVC structure. Open the App_Start folder and open the Startup.Auth.cs file for editing:

external5

It’s the code in this class and file that configures how Web API will authenticate. By default it’s setup for local accounts – accounts and passwords that are stored in a SQL database that goes along with your app. To add an external identity provider you need to scroll to the bottom of the file and uncomment the appropriate lines for the provider you want.

In this case as we’re authenticating with Facebook we’re going to uncomment those lines and add the App ID and App Secret that we obtained earlier from the Facebook portal:

external6

We’ve got one last step to perform – point the web site at the SQL Database we created earlier by updating the web.config file as shown below:

external8

Believe it or not in terms of code changes that’s it – we’re done. Build and publish the project to the Azure website we created earlier.

Mobile Application

This isn’t really intended as an iOS or Xamarin tutorial so I’m largely going to gloss over the steps that aren’t specifically about the authentication process – if you get stuck post a comment and I’ll reply when I get a chance. Not everybody has the Visual Studio plugin so I’m going to use Xamarin Studio to do this.

To authenticate from the mobile device we need to go through the following high level flow:

  1. Request a list of external providers and authentication end points from the server.
  2. Send a get request, from a web browser, to the end point for the provider the user wants to log in with.
  3. At the end of the process extract the access token from the URL of the page that is showing in the browser.
  4. Establish if the user is already registered with the server and if not create a user mapped to the external login and then call the authentication end point again.

In practice it’s simpler than it sounds. The key thing is that the authentication process must take place through a web browser, you can’t do this using a native approach. Although you can use something like the Facebook SDK to log in locally against Facebook and then use Facebook that doesn’t result in authentication against your server and web services.

Begin by creating a new iPhone Storyboard project with an application type of Single View Application. Then open the storyboard in the created project and add a second view controller that hosts a UIWebView control. You don’t have anything to create the Segue from as we’re going to drop buttons on programattically and trigger the segue in code so we need to create an segue from the view controller and give it a name – this trips a lot of people up! Basically control click the icon I have highlighted below and drag it to the second view controller. Then click the segue and give it an identifier.

external7

To communicate with the Web API you’re going to need access to some of the models that go with the AccountController – specifcally ExternalLoginViewModel and RegisterExternalBindingModel. In a real application my preference is to extract these models from the Web API project and place them in a portable class library, that way your mobile code and your web code can all use the same models with no code duplication. For the sake of this example copy and paste these classes to your Xamarin project.

We’re going to want to process some JSON so using the Xamarin Component Store add the Json.NET component to your project.

Now we’ve done all that we’re going to add a class called AuthenticationServices within which we’re going to wrap the calls we need to make to Web API directly. To begin with we need a method to let us get the external providers registered with Web API:

external10

We now need to edit our root view controller so that when the view loads we retrieve the external providers and when one of the buttons is tapped we run the segue to load our second view controller and display the browser, I’ve done this in a slightly hokey way as it just leads to a simpler example than a table view or collection view:

external9

At this point we have a tremendously exciting app that is displaying a Facebook button which when tapped launches the web browser but not much more happens:

external11

To complete the login process we need to do work on the view controller that is hosting the web browser. When the view is loaded we’ll get the URL that has been returned from the server and load it in the browser:

external12

This will present the Facebook login page as shown below:

external13

If you enter valid credentials then you’ll find that eventually you end up back at your web sites home page:

external14

If you look at the URL (which will have been output to Xamarin Studio’s Application Output window) you’ll see it includes the access_token as a parameter. This is the bearer token that I’ve discussed in a previous post and which you need to pass as a header to Web API for future authenticated requests.

Having got this far we now need to check and see if the Facebook user has a registered account with our web services and if not create one. There are two ways you can find this out – you can either ask Web API the question on the endpoint /api/Account/UserInfo or take a shortcut and look at the cookies that have been set. In this example we’re going to do the latter.

In external identity provider scenarios ASP.Net makes use of two cookies, one is called .AspNet.ExternalCookie and the other is called .AspNet.Cookies. When a user has logged in with an external identity provider but doesn’t yet have an account with our web service then the .AspNet.Cookies cookie will not be set. So to find out if this is the case we’re going to have a look in the applications cookie store:

external15

We also need to add some code to actually call Web API’s external account registration method into our AuthenticationServices class, in the example below I’m supplying a hard coded username but in reality you would collect this from the user:

external16

And finally we need to look for the access token in the URLs that appear in the web browser as the authentication process takes place and react to them appropriately (gather the access token, look for an account, register if necessary, then move on):

external17

In production code it’s definitely worth also verifying that the access token is on a URL that maps to your domain.

If you run the app at this point the full authentication chain will work but we’re not actually doing anything to prove that. So finally lets add a step to call the default get handler on the sample ValuesController that Visual Studio included in our Web API project and call it on a successful login / registration:

external18

At this point we’re done – we’ve secured our web services with a Facebook login and you can easily extend this to Twitter, Microsoft Accounts or Google by uncommenting the other lines of code in Startup.Auth.cs. Behind the scenes if you look into the SQL database that the ASP.Net authentication system will have created you’ll see a user in the users table and a login for the Facebook provider in the logins table.

If you’d rather use table storage for your user data you can use my alternative ASP.Net user store provider that I outlined here.

The account controller contains other methods to support logout and get information about users but it’s all pretty straightforward once you understand the workflow to login and register.

Hope that’s useful, if you spot any problems let me know in the comments.

Full source code can be found on GitHub here.

Follow up: Use Azure Table Storage as an OAuth Identity Store with Web API 2

My original blog post and NuGet package have generated a lot of interest (great!) and a couple of bugs (not so great!) in the slightly naive code I dropped out of a early development project I was working on.

I’ve since had the opportunity to test the code at reasonable scale (> 1 million users, 1000s of concurrent logons) and made a few changes to the table structures as a result of learning more about the ASP.Net provider workflow.

There’s also a fix on the way for the “Google” issue – invalid (from an Azure table storage perspective) characters being placed in partition and row keys.

Finally apologies in the delay for replying to everybody’s comments – I took a solid 2 weeks off over the Christmas break and since rejoining the fray have been absolutely snowed under. I hope normal service is now resumed and as well as these bug fixes I’ve got some blog posts on the way covering topics such as cross-table concurrent table storage patterns, alerting around an Azure system and using Shared Access Signatures to reduce server rental fees.

Azure AD, Groups, Roles and the Authorize Attribute

Configuring a new MVC 5 website to authenticate against an Azure Active Directory is really simple – all you need to do is configure using the ASP.Net 4.5 Web Application creation wizard when you create a new project as described here.

If you complete that successfully and add an Authorize attribute to one of your controllers or actions then you’ll find everything works as you’d expect.

However if you try and use roles with AD groups (obvious thing to try right – particularly now groups are exposed in the management portal) you’ll find you get UnauthorizedException’s being thrown. This is because, out of the box, the current implementation doesn’t translate group memberships into role claims.

Fortunately this is fairly straightforward to resolve by supplying a specialization of the System.Security.Claims.ClaimsAuthenticationManager class to ASP.Net and using the Azure AD Graph API to retrieve the memberships of the authenticated user.

The good news is I’ve done the grunt work for you and extended the NuGet package I blogged about recently to include an implementation of a claims authentication manager that does just this. You can take a look at the code involved here. It makes use of the Windows AD Graph API Helper Library posted on MSDN which takes care of some of the required service wrapping.

As before the source for the whole library is in GitHub and covered by the MIT license and a NuGet package is available.

In order for you to use AD groups as roles then your application is going to need to be able to read data from your Azure AD and to allow that you’ll need to do some additional configuration of your application inside the Azure Management Portal. The New Project wizard will have added your website to your Active Directory which you can see in the Management Portal on the Applications page. You can see mine listed below:

adstep1

Select your application and you’ll be taken to the application configuration page which should look something like the below:

adstep2

To configure your app you need to tap the Manage Access button down the bottom. Do that and then select Change the directory access for this app. Then on the next page select Single sign on, read directory data.

Azure will whirr away for a short while changing settings on your AD and when it’s done you need to go to the Configure tab (click configure at the top of the page as shown in the image above). In here you need to create a key that your application can use to authenticate with the Graph API and read AD data.

To do this scroll down to the Keys section and click the drop down and choose whether you want a 1 year or 2 year key. In the screenshot below I’ve picked 1 year.

adstep3

After you’ve done this click save in the toolbar at the bottom and you’ll see your key.

We’ve just about done in the Azure Management Portal all you need to do before you leave is take note of the Client ID and the Key as shown in the image below (mine are blurred out!).

adstep4

For the rest of this walkthrough I’m assuming you’re configuring a web site rather than an Azure Web Role but the claims manager we are using uses the Azure Configuration Manager for both so if you are using  a Web Role you can simply put the settings in your .cscfg and .csdef files.

Firstly add the NuGet package to your project which you can do in the Package Manager GUI or in the console:

Install-Package accidentalfish.aspnet.identity.azure

Then you need to edit your web.config file with a couple of app settings. For this you need your Client ID and Key that you noted down earlier.

adstep5

The RoleClaimIssuer is optional but is the claim issuer you want inserted into the claim, if you leave this out the issuer will be set as DefaultRoleIssuer.

The final step you need to take is to tell the ASP.Net identity model about the claims manager. To do this locate the <system.identitymodel> section of the web.config file and insert the line highlighted below at the bottom:

adstep6

To save you some typing the line to paste is:

<claimsAuthenticationManager type="AccidentalFish.AspNet.Identity.Azure.GraphRoleClaimsAuthenticationManager, AccidentalFish.AspNet.Identity.Azure"/>

With that you’re done. You can use the groups you’ve configured in the Azure AD as roles with the [Authorize(Roles=”…”)] attribute.

I hope all this is useful, if you have any feedback then please do get in touch.

Contact

  • If you're looking for help with C#, .NET, Azure, Architecture, or would simply value an independent opinion then please get in touch here or over on Twitter.

Recent Posts

Recent Tweets

Invalid or expired token.

Recent Comments

Archives

Categories

Meta

GiottoPress by Enrique Chavez