Can postman authenticate with a microsoft AD user? Doesnt seem to

Our react web application, which is only visible inside our organsisation, uses our microsoft AD to authenticate. I.e. our web app requires logging in via our organisations microsoft account. Then it hits our API services which require this authentication.

The problem is that any request postman send fails, because the response is HTML telling you to login with microsoft.

We havent been able to find any documentation on this, other than this page:

https://www.postman.com/saranyaswaminathan/workspace/microsoft-graph/documentation/3661119-157e8b7c-9005-4327-99f6-7c3ef5f32290

We dont know if this page is relevant to our issue, but trying the first GET on the page:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=code&redirect_uri=http://localhost/myapp/&response_mode=query&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read&state=12345

gives this response:

AADSTS7000112: Application ā€˜6731de76-14a6-49ae-97bc-6eba6914391eā€™(Tutorial Sample App) is disabled.

When I call this URL, I am already logged in with my MS account.

If I open an incognito window, and open our web application, it redirects to this URL to login:

https://login.microsoftonline.com/60c43c0a-64ac-4050-bf3e-31e1cdfffdeb/saml2?SAMLRequest=nZJLT8MwEIT%2FSuR7EjdJW2H1oVIkqASiohEHLmhrb4qlZB28LvTno%2FSBeoAeet7ā€¦

The answer is yes. You can either use the authorization helpers, or you can do this in a pre-request script.

You need to have the correct scope and grant type for your application.

You will call the Microsoft token endpoint directly to get a token for your application\grant.

The following is an example, that you can tailor to your requirements.

let moment = require('moment');
let currentDateTime = moment(new Date()).format("YYYYMMDDHHmmss");
let tokenExpiry = moment(pm.environment.get("bearerTokenExpiresOn")).format("YYYYMMDDHHmmss");

// console.log("currentDateTime: " + currentDateTime);
// console.log("tokenExpiry: " + tokenExpiry);
// console.log(pm.environment.get("bearerToken"));


if (!pm.environment.get("bearerToken") || currentDateTime > tokenExpiry) {
    pm.test("Pre-request check for Environment Variables", function () {
        let vars = ['client_id', 'scope', 'tenant_id', 'client_secret', 'scope'];
        vars.forEach(function (item) {
            // console.log(item);
            pm.expect(pm.environment.get(item), item + " variable not set").to.not.be.undefined;
            pm.expect(pm.environment.get(item), item + " variable not set").to.not.be.empty;
        });
        pm.sendRequest({
            url: 'https://login.microsoftonline.com/' + pm.environment.get("tenant_id") + '/oauth2/v2.0/token',
            method: 'POST',
            header: 'Content-Type: application/x-www-form-urlencoded',
            body: {
                mode: 'urlencoded',
                urlencoded: [
                    { key: "client_id", value: pm.environment.get("client_id"), disabled: false },
                    { key: "scope", value: pm.environment.get("scope"), disabled: false },
                    { key: "client_secret", value: pm.environment.get("client_secret"), disabled: false },
                    { key: "grant_type", value: "client_credentials", disabled: false },
                ]
            }
        }, function (err, res) {
            if (err) {
                console.log(err);
            } else {
                pm.test("Pre-request Microsoft login Status code is 200", () => {
                    pm.expect(res).to.have.status(200);
                    let resJson = res.json();
                    // console.log(resJson);
                    let token = resJson.access_token;
                    // console.log(token);

                    function parseJwt(token) {
                        var base64Url = token.split('.')[1];
                        var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
                        var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
                            return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
                        }).join(''));

                        return JSON.parse(jsonPayload);
                    }

                    let decoded = parseJwt(token);
                    // console.log(decoded);
                    let expiryDate = new Date(decoded.exp * 1000);
                    // console.log(expiryDate);

                    pm.environment.set("bearerToken", token);
                    pm.environment.set("bearerTokenExpiresOn", expiryDate);
                    // console.log("bearerTokenExpiresOn: " + pm.environment.get("bearerTokenExpiresOn"));
                });
            }
        });
    });
};

Pay attention to the expiry date, as I find that its different for some Microsoft endpoints. For some grant types you get an expiry date direct in the response, and in other situations like this one for client credentials, you have to pull apart the token. (The point Iā€™m making is that you need to test this bit properly).

All you then need to use is use the bearerToken variable in the auth for your request.

image