6
votes

I'm trying to authenticate a HTML app against an Azure Mobile Service app.

The Setup

Both apps use AAD as authentication backend, so both apps have an application registered in the Active Directory:

Azure Mobile Service app:

HTML app:

  • in "permissions to other applications" i added the Azure Mobile Service app with the delegated permission "access"

The Azure Mobile Service uses a .NET backend, where i included and configured the NuGet Package "Microsoft Azure Mobile Services .NET Backend Security Extension" as described in https://azure.microsoft.com/en-gb/documentation/articles/mobile-services-dotnet-backend-windows-phone-get-started-users/

The HTML app uses ADAL.JS and Angular:

adalAuthenticationServiceProvider.init(
{
    // Config to specify endpoints and similar for your app
    clientId: "<html app aad client id>",
    redirectUri: "<html app redirect uri>",
    endpoints: {
        '<AMS app client id>': 'https://ampapp.azure-mobile.net/'
    }
},
$httpProvider
);

This setup works as expected, i open my html app, authenticate against Azure AD, get a redirect to my App and I'm logged in. Also, when i try to access my Azure Mobile Service i see that Adal.js injects the bearer token.

The Problem

The bearer token is not accepted by the Azure Mobile Service - i get a 401 not authorized. I don't know why, but the Azure Mobile Service uses it's own authentication header - but ok.

MSDN defines a so called "Client-directed login operation" for the Azure Mobile Service:

"Requests an authentication token from Microsoft Azure Mobile Services by using an identity token already obtained from an identity provider." (https://msdn.microsoft.com/en-us/library/azure/jj710106.aspx)

Ok, so lets do this:

 // obtain token for Azure Mobile Service from Adal.js
 var token = this.getAADToken(ZUMOAuthenticationProvider.Config().url);

 $http({
        method: 'POST',
        url: ZUMOAuthenticationProvider.Config().url + 'login/aad', 
        data: JSON.stringify({
                  "access_token" : token 
              }),
        headers: {
                 'X-ZUMO-APPLICATION': '<application key>'
       }).
       success(function (data, status, headers, config) {
            alert(data);
       }).
       error(function (data, status, headers, config) {
            alert(data);
       }); 

Note: The token acquired by the first line is really a the access token for the azure mobile service aad application and not for the HTML app.

This POST request also gets a 401 response. So i don't know how to authenticate my app. I also tried the azure mobile service js lib. This lib works, but it uses a popup for authentication, but i don't like to add another library to my projects for just a few REST calls.

Similar Problems

When trying to solve my problems i found other Stackoverflow post:

Why isn't my Azure Mobile Service accepting the bearer token ADAL.js is sending it?

  • same problem, no solution (even in the chatlog linked in the last comment)

How do I secure an Azure Mobile Service with Azure AD? ADAL.JS

  • same author as above, i checked everything mentioned in the accepted answer but it doesn't work

I also took a look at the new Azure Mobile apps from the new Azure Management portal but it seems that they are using the same authentication mechanism.

So, how can i get this working?

3
So, you set up two apps in your AAD? Did you enable client flow on both of them?PilotBob
Yes, 2 Apps in Azure AD, both client flow enabled because both should be able to authenticate via JS. Important: The HTML App should be granted to access the Azure Mobile ServiceSven Lauterbach
can you send me an example of the JWT you are sending to the /login/aad endpoint so I can compare it to mine.PilotBob
A good resource for inspecting the payload in your JWT is "jwt.io" This website has tools that will decode the contents of your token. I am having troubles authenticating the token I got back from using Auth0. I compared this to the token I get when using pure azure and realized it was quite different.Manuel Hernandez

3 Answers

2
votes

Ok, i found my bug:

endpoints: {
    '<AMS app client id>': 'https://ampapp.azure-mobile.net/'
}

This should be

endpoints: {
    'https://ampapp.azure-mobile.net/': '<AMS app id uri>': 
}

After this it works! I'm goind to publish a Angular modul to github which injects the token in the X-Auth-User header to every request like adal.js does.

Edit:

As promised here a more detailed answer:

As mentioned in my question you have to setup 2 applications in Azure Active Directory:

  • an AAD app for the Azure Mobile Service
    • just follow the instructions from this article
  • an AAD app for the HTML app
    • set the "oauth2AllowImplicitFlow" to "true"
    • under "permissions to other applications" add the Azure Mobile Service AAD app enter image description here

Configure the Angular app to use the Azure Mobile Service as an endpoint

adalAuthenticationServiceProvider.init(
{
    clientId:"54110492-4ae3-4c9f-9530-3101458d43fb",
    redirectUri: "https://localhost:44304/",
    endpoints: {
        'https://zumodemoapp.azure-mobile.net/': 'https://zumodemoapp.azure-mobile.net/login/aad'
    }
},
$httpProvider
);

Now you can use the Client-directed login operation to get a Azure Mobile Service authentication token.

var zumoAppID = 'https://zumodemoapp.azure-mobile.net/login/aad';
var zumoLoginUri = 'https://zumodemoapp.azure-mobile.net/login/aad';
var zumoTodoController = 'https://zumodemoapp.azure-mobile.net/tables/TodoItem';

// 1. acquire a oath token for our zumo app from azure ad via adal.js
adalAuthenticationService.acquireToken(zumoAppID).then(function (data) {
     //2. we have the azure ad token, lets get a azure mobile service token
     $http.post(zumoLoginUri,
                JSON.stringify({
                    "access_token": data
                })).
                success(function (data, status, headers, config) {
                    //3. with the azure mobile service token we can authenticate our request
                    $http.get(zumoTodoController,
                                          {
                                              headers:  {
                                                      'X-ZUMO-AUTH': data.authenticationToken
                                              }
                                          }).
                                          success(function (data, status, headers, config) {
                                              alert(data); //yay!
                                          });
                }).
                error(function (data, status, headers, config) {
                    alert(data);
                });
});

As mentioned in the comment I created a more detailed blog post here. If you need more information please leave a comment :).

0
votes

You can use the AzureMobileServices client script to do a login with an already obtained token:

You need to include the follwing script: https://ajax.aspnetcdn.com/ajax/mobileservices/MobileServices.Web-1.2.8.min.js

Then after you obtained the token with ADAL.JS you can use it to login and obtain a Mobile Service Authentication Token:

var appUrl = 'https://foobar.azure-mobile.net'
  , appKey = 'zumo key' // found on the dashboard of the mobile service
  , client = new WindowsAzure.MobileServiceClient(appUrl, appKey);

// ...
var token = this.getAADToken(ZUMOAuthenticationProvider.Config().url);

client
  .login('aad', { 'access_token': token })
  .then(function() {
    // client.currentUser.mobileServiceAuthenticationToken
  });

This token then needs to be included in succeeding mobile service API requests:

var config = {
  headers: {
    'X-ZUMO-AUTH': client.currentUser.mobileServiceAuthenticationToken
  }
}

$http
  .get(appUrl + '/some/path', config)
  .then(function (r) {
     console.log(r);
  });
0
votes

The POST likely returns a 401 because the audience of the AAD token is incorrect. The Mobile Service expects this to be its /login/aad endpoint, but I suspect the token you are sending is actually scoped to the web site you are calling from. The delegated access permission just says that you can take a token from the site and transform it to a token for the Mobile Service. It does not change the nature of the issued token itself.

So the best suggestion is to make sure you are signing into the Mobile Service audience, or perform the delegated access flow. Unfortunately, there don't seem to be too many samples on the latter unless using ADAL.NET

One workaround would be to set the MS_AadAudience app setting on the mobile service to match that of your web site. You should only do this if the site and Mobile Service exist within the same logical security boundary for your application. That is, anything which can sign into your site can access the Mobile Service at this point. Overall, the better approach is to obtain an access token to the mobile service.