Search code examples
azure-active-directorypassport-azure-ad

Is there a way to implement the Azure AD on-behalf-of (OBO) flow in NodeJS using a library like Passport?


I've found examples on how to use passport-azure-ad to secure a WebAPI in NodeJS (e.g. using the BearerStrategy), but I haven't found any examples of implementing the OBO flow in NodeJS specifically.

In my situation, I have a client application that sends a bearer auth token to my NodeJS service in the Authorization header. If my understanding is correct, if I then want to have my NodeJS service call the MS Graph API as the user, I have to exchange the token for a different one as part of the OBO flow.

In the examples I've found for a service that uses .NET, there is a library for this purpose (and you call something like AcquireTokenAsync with the Bearer token as the assertion). Is there a similar library that should be used if the service is NodeJS instead of .NET?

I know it can be done by issuing HTTP requests directly, I just didn't know if that was the preferred/only way to do it in NodeJS.

Thanks!


Solution

  • Actually, adal-node package does not support on-behalf-of flow. To implement that we have to make a new HTTP call and pass assertion in the request. I would suggest you to read the incoming token in your service and make a new http call to (https://login.microsoftonline.com/b2bc09c8-9386-47b1-8aexxxxxxxxxx/oauth2/token) endpoint with assertion to get the token for MS Graph API.

    Below is the screenshot to get the token in on-behalf-of flow using postman.

    enter image description here

    Below is the code to get the access token using on-behalf-of flow in node.js

    var qs = require("querystring");

    var http = require("https");

    var options = { "method": "POST", "hostname": [ "login", "microsoftonline", "com" ], "path": [ "b2bc09c8-9386-47xxxxxxxx", "oauth2", "token" ], "headers": { "Content-Type": "application/x-www-form-urlencoded", "cache-control": "no-cache", "Postman-Token": "739540c9-1e3d-4d74-bxxxxxxx" } };

    var req = http.request(options, function (res) { var chunks = [];

    res.on("data", function (chunk) {
        chunks.push(chunk);
    });
    
    res.on("end", function () {
        var body = Buffer.concat(chunks);
        console.log(body.toString());
    });
    

    });

    req.write(qs.stringify({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', client_id: 'd1538209-a56f-4301-863dxxxxxxxxxxxxx', resource: 'https://graph.microsoft.com/', client_secret: 'NITLQThsHDlPb0FR+8oXxxxxxxxxxxxxxxxxxxx', scope: 'openid', assertion: 'incoming access token from native app', requested_token_use: 'on_behalf_of', undefined: undefined })); req.end();

    You can extract the access token and use it against a resource in a bearer request. I hope this will solve your issue.