AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.64k stars 2.65k forks source link

Can't get @azure/msal-browser working with ADO access #3254

Closed vishnu4 closed 3 years ago

vishnu4 commented 3 years ago

Library

Description

I'm having trouble using @azure/msal-browser and @azure/msal-react to connect to Azure DevOps. I've gotten it to authentication with your sample, and I'm successfully getting profile information and a bearer token, but when i try to use that token to access an ADO url like https://vsrm.dev.azure.com/microsoft/Universal%20Store/_apis/release/releases?definitionId=8792&$top=1, i just get a sign in response. The code i'm using is:

`import axios from "axios";
import { baseURL } from "../Utils/constants";
import { loginRequest } from "../Authentication/authConfig";
import { msalInstance } from "../Authentication/msalIsntance";

async function getParameters(accessToken?) {
  if (!accessToken) {
    const account = msalInstance.getActiveAccount();
    if (!account) {
      throw Error("No active account! Verify a user has been signed in and setActiveAccount has been called.");
    }

    const response = await msalInstance.acquireTokenSilent({
      ...loginRequest,
      account: account
    });
    accessToken = response.accessToken;
  }

  const authHeader = `Bearer ${accessToken}`;
  //accessToken = "<Enter PAT here>";
  //const authHeader = "Basic " + btoa("" + ":" + accessToken);
  const headers = {
    Authorization: authHeader
  };
  return {
    headers: headers,
    params: {
      "api-version": "6.0"
    }
  };
}

//https://vsrm.dev.azure.com/microsoft/Universal%20Store/_apis/release/releases?definitionId=8792&$top=1
async function getReleaseByDefinition(definitionId: string, top = "1") {
  const url = baseURL + `release/releases?definitionId=${definitionId}&$top=${top}`;
  const options = await getParameters();
  return axios
    .get(url, options)
    .then(({ data }) => {
      //console.log(data);
      return data;
    })
    .catch((error) => {
      return error;
    });
}`

Note that if i comment out the Bearer token, and use a PAT instead, it works fine, so i know my user has appropriate access.

If i check my application registration, you can see the following details i've added: platform api perms manifest

Please let me know if i'm missing anything, but it all seems set up correctly. Thank you!

Source

tnorling commented 3 years ago

@vishnu4 Can you clarify are you trying to use the MS Graph access token against an Azure DevOps resource? Access tokens are issued per resource so you'll need to request a separate access token for ADO.

vishnu4 commented 3 years ago

i'm using this as my loginRequest above if that answers your question. if it doesn't, let me know.

export const loginRequest: SilentRequest = {
  scopes: [
    "User.Read",
    "499b84ac-1321-427f-aa17-267ca6975798/user_impersonation",
    //"499b84ac-1321-427f-aa17-267ca6975798/.default"
  ]
};
tnorling commented 3 years ago

@vishnu4 User.Read is a MS Graph scope and the other 2 are not (assuming these are your ADO scopes?) On login you can request all of these to ensure your users are requested for consent. However you will only receive an access token back that can be redeemed for the first resource in the list, in this case MS Graph. If you need an ADO token you will need to make a 2nd request using only the ADO scopes. I would recommend reading through this doc for more information on this.

vishnu4 commented 3 years ago

got it @tnorling , thank you. I only need access to ADO (I don't need graph as well), so i can change my loginrequest to

export const loginRequest: SilentRequest = {
  scopes: [
    //"User.Read",
    "499b84ac-1321-427f-aa17-267ca6975798/user_impersonation",
    //"499b84ac-1321-427f-aa17-267ca6975798/.default"
  ]
};

But doing that results in the following error when i get my tokens: AADSTS65001: The user or administrator has not consented to use the application with ID 'XXX' where XXX is the application ID, which i show in the above images it should have API permissions to ADO

tnorling commented 3 years ago

Are you getting this error on the interactive call (redirect or popup) or on the silent call? If its the latter you should call an interactive API first to grant consent to the scopes.

vishnu4 commented 3 years ago

It's on the silent call, so that makes it sound like in this sample https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/samples/msal-react-samples/react-router-sample/src/ui-components/SignInButton.jsx , the instance.loginPopup(); should be instance.loginPopup(loginRequest); right? That definitely seems closer, but when i try that i get admin which i would have thought that i don't need because of the api permission image i show above, where 'admin consent required' is 'No'.
Regardless, i try to grant consent, since I'm the creator of the app registration i would have thought signing in as myself would work, but it doesn't seem to.
Thanks so much for helping with this BTW.

tnorling commented 3 years ago

The admin in this case isn't the person who owns the app registration but rather the admin of the organization. Is this app registered in the first party portal by chance?

vishnu4 commented 3 years ago

It isn't, should it be? I do work in Microsoft but didn't know if all app registrations must be registered in first party portal. If that's the case, then i will definitely go there!