Windows Azure Active Directory Authentication: Setting up the application

Continuing where we left off in the previous post, we’ve got all the tools, so the next step is setting up the authentication itself. You probably don’t want to make a mess of the working state of your actual application. Or perhaps you don’t yet have an application to test with. For this walkthrough, you can start with a new ASP.NET MVC 4 project from Visual Studio and select Internet Application as the template. The template contains a layout that displays the current logged-in user, which demonstrates that the authentication mechanism integrates nicely with the rest of ASP.NET. After you’ve got your application open in Visual Studio, right-click on the project in Solution Explorer and select Enable Windows Azure Authentication.

vs-enable-waad-auth

Clicking on the menu item opens up a dialog that asks for your tenant domain name.

vs-enable-waad-auth-2

That is, unless it throws you a COMException instead. If that happens, ensure that you’ve got an IIS or IIS Express virtual directory set up for your web application. Visual Studio doesn’t let you misconfigure the virtual directory settings like this, but it might still happen if you’re running your web app as an Azure Web Role in the Compute Emulator.

Once you type in your tenant domain name, you’ll be prompted to log in. Log in with an account that has administrative access (for example, the account you created during the tenant setup process).

vs-enable-waad-auth-3

The prompt uses IE, so if you happen to be logged in an IE session with a Microsoft Online account that doesn’t exist in the tenant domain, you might end up with an error instead. This happens to me quite often, because I use our Office 365 apps with IE.

vs-enable-waad-auth-error

The easiest way to get rid of this error is to cancel the WAAD authentication setup, open up the Visual Studio web browser (View –> Other Windows –> Web Browser) and use it to navigate to the Microsoft Online logout page. Once the logout process is complete, close the Visual Studio web browser and try the WAAD authentication setup again. At this point, if everything went well, you’ll be presented with a happy green check mark.

vs-enable-waad-auth-4

You’ll have a number of changes in your Web.config, mostly under system.identitymodel:

vs-enable-waad-auth-result

The default authentication module for ASP.NET applications is the Forms Authentication module. You can only use a single authentication module for your application, and since the Forms Authentication module is configured at the web server level, it takes precedence. So make sure that your application doesn’t use the Forms Authentication module by adding this under system.webServer/modules:

<remove name="FormsAuthentication" />

A brief interlude on WAAD Single Sign-On

Before we go further, a few words on how SSO actually works. When a request comes in to your web application, the authentication module checks to see if the user is authenticated or not. This is typically done by looking at a cookie that holds some sort of authentication ticket. If the user is authenticated, then it’s all good. However, if the user is not authenticated, a bunch of things have to happen. First, the authentication module redirects the user’s browser to the identity provider. Among the information it passes on is a return address. Since the login process happens in the user’s browser, we can’t really control it. In order for things to work smoothly, we need to tell the identity provider what to do after the user has logged in. A return address tells the provider where the user should be redirected once authentication is completed. After the user logs in, the identity provider uses the return address combined with a login token to redirect back to our application. Our application invokes the authentication module, which takes the login token, verifies its validity and extracts the user’s identity. This is the point where the user is finally authenticated with our application.

browser-app-waad-interaction

I won’t pretend I understand all or even most of the security implications here, but one consideration is definitely this: you can’t let just anyone authenticate users against your directory, even if the only data you’d pass on to them would be the user name. Imagine a rogue third party that created an app that had your company’s branding and used your company’s official authentication mechanism – and then tricked your users into giving them confidential data. That’s no good, so we need to control who we give the login token out to. Which is what we’ll do next.

Configuring the Service Principal

Before your application can use WAAD authentication, it must be registered in WAAD. This registration is called a Service Principal, and a big part of what the Visual Studio wizard did for you involved creating the Service Principal. One of the things configured in the Service Principal settings is the list of accepted after-login return addresses. The wizard creates a Service Principal with a single return address: https://localhost:44302 — the port number is arbitrarily assigned, so yours might not be exactly the same. It also enables SSL for your app, so the return address will work. This is all well and good, unless your web application can’t run in that particular port – such as with Azure Web Roles in the Compute Emulator. That means you won’t get the login token from WAAD unless we add a new return address. Fire up Microsoft Online Services Module for PowerShell again. Call Connect-MsolService to authenticate, type Get-MsolService and hit tab. PowerShell will expand this to Get-MsolServicePrincipal. Hit enter… and boom! “Get-MsolServicePrincipal : The term ‘Get-MsolServicePrincipal’ is not recognized as the name of a cmdlet, function, script file, or operable program.”

msol-powershell-before-import

Wait… what? Yeah. So PowerShell’s autocomplete suggests that there is a commandlet with this name, but then it’s not there when you try to use it. This is a weird artifact of the way the commandlets are packaged. What you now want to do is run Import-Module MSOnlineExtended –Force, and then the command will work. The –Force flag is necessary, because the extended module lives in the same binary file as the regular one, and without it, PowerShell will think it’s already well and properly loaded. In order to configure the return addresses, we need a handle on the service principal created by the Visual Studio Wizard. In the MSOL PowerShell window, type Get-MsolServicePrincipal | select AppPrincipalId,DisplayName

PS C:\Windows\system32> Get-MsolServicePrincipal | select DisplayName,ObjectId

DisplayName                             ObjectId
-----------                             --------
Microsoft.Azure.ActiveDirectory         25294a23-e33f-4b06-9bd4-c0a04f4cc155
Microsoft.Azure.ActiveDirectoryUX       081e23f3-5c2b-44b5-89e7-23cbbe7a13dc
My test app                             3dc125e6-d518-40d2-9392-87a03dac8f68

The last principal in the list is the one the wizard generated for you. Visual Studio always registers your application as “My test app”, regardless of what your app is actually called – for instance, the name of my application is the far more sensible “WAADDemo”. Winking smile In my example, the generated principal’s object id is 3dc125e6-d518-40d2-9392-87a03dac8f68. In order to get a handle on that particular principal, we can run

$principal = Get-MsolServicePrincipal -ObjectId 3dc125e6-d518-40d2-9392-87a03dac8f68

To list the configured reply addresses, we type:

$principal.Addresses | select Address,AddressType

and get a return address listing

PS C:\Windows\system32> $principal.Addresses | select Address,AddressType

Address                                                             AddressType
-------                                                             -----------
https://localhost:44302/                                                  Reply

To add the final deployment and Compute Emulator reply addresses, we modify the address list we just got, then set it back to the principal:

$addresses = $principal.Addresses
$addresses.Add((New-MsolServicePrincipalAddresses -Address http://localhost:81))
$addresses.Add((New-MsolServicePrincipalAddresses -Address http://my-app.example.com))
Set-MsolServicePrincipal –ObjectId 3dc125e6-d518-40d2-9392-87a03dac8f68 -Addresses $addresses `
 -DisplayName "WAADDemo App"

The first line gets the current address list to a new variable. The next two lines create the address objects and add them to the list. The final command associates the updated address list with the principal and changes its name to “WAADDemo App” for good measure.

Finishing up

The last thing you need to do is ensure that you’re sending the correct reply address to WAAD. Edit web.config at system.identityModel.services/federationConfiguration/wsFederation and replace the value of the reply attribute with one of the reply addresses you configured in the previous step:

<wsFederation passiveRedirectEnabled="true" issuer="https://accounts.accesscontrol.windows.net/a071bf68-ee1d-46aa-ac6d-cfddf3826050/v2/wsfederation" realm="spn:e8a3050f-0c61-46bd-9808-ff7dd5dcdb4b@a071bf68-ee1d-46aa-ac6d-cfddf3826050" reply="http://localhost:81/" requireHttps="false" />

By now, when you run the application, you should be automatically redirected to the Windows Azure Authentication portal:

waad-federated-login

When you log in, you’ll be redirected back to your app as an authenticated user:

waad-app-after-login

If you play with the app a bit, you’ll notice that logging out doesn’t actually work. That’s a quirk of Azure federated login – you can visit the logout URL if you like, but it won’t really take effect unless you close the browser session. Phew, that was a lot of stuff to go through! What’s interesting here is that you didn’t have to write a single line of C# code. Now, that in itself is not really a goal worth pursuing, particularly if it results in an ungodly mess of XML configuration. However, what is remarkable and desirable is that once you understand all this, setting up new applications that share the same credentials is actually a breeze. So there is a point to all this, believe it or not. Smile Next up: User details! We’ll be reading group memberships using the Graph API.

7 comments

  • Nice article, thanks dude! :)

    Also noticed that there might be one pic missing after sentence: “To add the final deployment and Compute Emulator reply addresses, we modify the address list we just got, then set it back to the principal:”

  • Welcome to my world. Now quickly take the blue pill.

  • Thanks for pointing that out, Tomi! It was a code block that was missing — I had written it as a noscript element, thinking I’d embed it as a Gist instead.

  • I’m currently getting “Unable to configure Windows Azure Authentication. Please try again later” in the Enable Windows Azure Authentication dialog (instead of the nice green checkbox). Is this a known issue currently? I noticed on Microsoft’s tutorial they have a warning from 12/7 that there could be errors. Is that what I’m experiencing? I’ve tried the logout trick mentioned to make sure I’m not authenticated with another domain.

  • Hi Jon, I’d expect the errors mentioned in the tutorial you linked should manifest within the browser window that asks for your crendentials — it would look a bit like this: http://lh5.ggpht.com/-WQ6_ZUiZb8M/UL76Mjl485I/AAAAAAAAAUw/lVlNVOpVsN4/s1600-h/vs-enable-waad-auth-error2.png That said, I tried to activate WAAD authentication for two different tenants just now, and got the same error as you did. Tracing the request made by Visual Studio, it looks like login works and I get an access token, but when VS tries to query for Service Principals in my domain, the response is Authentication_Unauthorized. I’m afraid I don’t know what’s going on — I’ll let you know if I figure it out.

  • The adding addresses bit above used to work – I know because I have done it before. Now, it doesn’t:

    +CategoryInfo : OperationStopped: Set-MsolServicePrincipal, MicrosoftOnlineException
    +FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.InternalService,Microsoft.Online.Administration.Automation.Se
    tServicePrincipal

    I’ve even taken it down to the simplistic example of getting the single existing address, not changing it at all, and just pushing it back into the principal – the same error occurs.

    Something has changed in WAAD recently. Clues on how to add the second reply address most welcome!

    Cheers, Nick

  • Lauri Kotilainen

    Hi again, Nick.

    One thing that has definitely changed is that WAAD now has an administrative console in the Windows Azure Portal, and you can configure the reply addresses there. That’d be the first thing I would try. There may be an updated MSOL PowerShell module as well, but unfortunately I don’t have the time to search for one just now. :)

Leave a Reply

Your email address will not be published. Required fields are marked *