Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to write a simple Azure Function that calls the Microsoft Graph API. But I could not make the access_token work. Here is what I've done:

  1. Created a new Azure Function App from the Azure Portal
  2. Turned on the "App Service Authentication" setting and instructed it to sign in with AAD (management mode is Express).
  3. Configured the app to have delegated permissions like "Sign in and read user profile" for Microsoft Graph.
  4. Created a new JavaScript function HttpTriggerJS1
  5. Changed the authorization level of this function to "Anonymous" (otherwise by default the "Function" level would not even allow me to run the function, always returning 401 Unauthorized)
  6. Installed the necessary Node module (npm install request)
  7. And the actual function:

    var request = require('request');
    module.exports = function (context, req) {
        var token = req.headers['x-ms-token-aad-access-token'];
        var reqUrl = 'https://graph.microsoft.com/v1.0/me/';
        request.get(reqUrl, {'auth': {'bearer': token}}, function (err, response, msg) {
            context.res = {
                body: msg
            };
            context.done();
        });
    };
    
  8. Tested this function in a separate browser window. Signed me in to AAD correctly.

  9. But the message returned from Graph was:

    "{
      "error": {
        "code": "InvalidAuthenticationToken",
        "message": "CompactToken parsing failed with error code: -2147184105",
        "innerError": {
          "request-id": "4c78551d-f0fe-4104-b1d3-e2d96fd3c02c",
          "date": "2017-05-16T19:11:14"
        }
      }
    }"
    

I looked into the token I got from req.headers['x-ms-token-aad-access-token']. It's something like "AQABAA....", which seems different from the regular access_token I've seen before that starts with "eyJ....".

What could be wrong here? When calling the Graph API, am I supposed to be using the access_token from the request headers?

Thanks!

Edit:

According to Chris Gillum's suggestion, I also looked into the "on-behalf-of" flow. And here is my updated function, which acquires an access_token for a particular resource (https://graph.microsoft.com in my case) by providing the id_token (retrieved from the request headers).:

var request = require('request');


module.exports = function (context, req) {
    var parameters = {
        grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        client_id: process.env.WEBSITE_AUTH_CLIENT_ID,
        client_secret: process.env.WEBSITE_AUTH_CLIENT_SECRET,
        assertion: req.headers['x-ms-token-aad-id-token'],
        resource: 'https://graph.microsoft.com',
        requested_token_use: 'on_behalf_of'
    };
    request.post('https://login.microsoftonline.com/microsoft.com/oauth2/token', {form: parameters}, function (aadErr, aadResponse, aadMsg) {
        var msgJson = JSON.parse(aadMsg);
        request.get('https://graph.microsoft.com/v1.0/me/', {'auth': {'bearer': msgJson.access_token}}, function (err, response, msg) {
            context.res = {
                body: msg
            };
            context.done();
        });
    });
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
304 views
Welcome To Ask or Share your Answers For Others

1 Answer

There are two ways you can make this work when using Azure App Service Authentication / Authorization:

  1. Assign a default resource in your function app's AAD configuration.
  2. Use the AAD on-behalf-of flow to exchange your ID token (x-ms-token-aad-id-token) for an MS Graph access token.

The simplest approach which doesn't require any code changes is to do #1. I outline the process in my App Service Auth and the Azure AD Graph API blog post (which needs some updates), but I'll give you the Functions-optimized version for the Microsoft Graph here.

The main things you need to do are:

  1. Ensure your AAD settings include a client-secret (you already have this).
  2. Ensure your AAD settings have the permissions to access the Microsoft Graph (you have already done this).
  3. Open your function app in Resource Explorer (use the link in the portal under Platform Settings), navigate to config/authsettings on the left-hand panel, change "additionalLoginParams" from null to ["resource=https://graph.microsoft.com"], and save the changes.

After doing this and logging in again, the x-ms-token-aad-access-token request header will always give you an access token that works with the Microsoft Graph.

The disadvantage of the above approach is that it doesn't help you if you need to access more than one AAD-protected resource from your function app. If that's a problem for you, then you'll need to use approach #2 above.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...