Home > Enterprise >  Microsoft Graph permission scopes throwing error when I pass more than one scope
Microsoft Graph permission scopes throwing error when I pass more than one scope

Time:01-02

I need to programmatically upload files to OneDrive. I won't have a front-end to generate the keys, because of that I need to generate them without user interaction and that's my problem. I've already managed to do this with a simple POC, but it necessarily needs user interaction because it uses the login and password credentials to authenticate to the Microsoft account, and only after that it uses clientId and clientSecret

When I try to generate a token using @msal-node, it doesn't use the scopes defined in Azure.

const msal = require('@azure/msal-node')
const config = require('../config')
const azConfig = {
  auth: {
    clientId: config.azureAppId,
    authority: `https://login.microsoftonline.com/${config.azureTenantId}`,
    clientSecret: config.azureAuthSecret
  }
}

const pca = new msal.ConfidentialClientApplication(azConfig)

return await pca.acquireTokenByClientCredential({
  scopes: [`${config.azureAppId}/.default`]
})

And I also can't pass new scopes through the acquireTokenByClientCredential() function because it thrown a error.

const msal = require('@azure/msal-node')
const config = require('../config')
const azConfig = {
  auth: {
    clientId: config.azureAppId,
    authority: `https://login.microsoftonline.com/${config.azureTenantId}`,
    clientSecret: config.azureAuthSecret
  }
}

const pca = new msal.ConfidentialClientApplication(azConfig)

return await pca.acquireTokenByClientCredential({
  scopes: [
    `${config.azureAppId}/.default`,
    'Files.Read'
  ]
})

ServerError: invalid_scope: 70011 - [2021-12-30 01:02:11Z]: AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope api://<azureAppId>/.default Files.Read openid profile offline_access is not valid.

The only scope supported by the function is /.default, which doesn't use the permissions added in Azure and when I try to add scopes into the function code, it returns an error saying the scopes parameter is not valid.

But when I generate a token using Postman with the same credentials, it works and adds the scopes I need to access OneDrive

CodePudding user response:

It's difficult to say exactly how to resolve your issue. We don't know what is the purpose of obtaining that token - Azure is using a combination of authentication and access tokens. Given you're defining a 'Files.Read' scope, you probably aim to authorize the user.

After looking into:

https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/2c58d3ff42a04052e16758f5496a30e76b4c39b2/lib/msal-common/docs/request.md

and personal experience, I would recommend you try to following:

  1. Clarify the purpose of the token and where would be the best place (FE/BE) to achieve that. For instance, when logging the user in or authorizing requests to your backend, best practice would be to use the msal library on the frontend (obtain the authentication token there) and hide your backend behind and API Management service, and configure its policies to authorize requests based on access token - also generated on the frontend.

  2. Make sure your application (Web API) is registered in Active Directory. The Azure Documentation starts here: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant

  3. Add relevant scope to your registration: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis

  4. In your code, start by using a single value for your scopes e.g. Mail.Read and test that (i.e. obtain the token) first before experimenting with multiple scopes.

CodePudding user response:

Unfortunately I don't have experience working with OneDrive programmatically, but regardless I've done some digging into this.

According to MS documentation 'Files.Read' is a valid scope.

The application you're developing is called a daemon, service account or back-end service by MS (thanks MS for making our lives simple). In other words it is a server application which wants to authenticate with Azure without user interaction. See this diagram for reference.

Organise your code into functions or classes to avoid things like using return statement outside of function / method body.

Refer to this example to call the MS Graph API to authenticate and authorise your application. This should allow you to get the access token.

Once you're able to get the token, refer to this walkthrough of OneDrive REST API for details on how to programmatically access it and interact with it.

PS A general advice on working with MS Azure documentation: don't count on finding a page that gives you an exact recipe for what you're trying to achieve (though you might be sometimes lucky). Azure is just too big. Try to get a high level understanding of the steps that need to happen - diagrams are usually helpful. Then, just dig around to find pages on each of the steps for your specific use case.

  • Related