Share via

msgraph API permissions 403 even though admin access granted

Jim C 0 Reputation points
2025-04-07T14:46:10.5533333+00:00

I'm trying to build an application in Go which will notify my team of results from its work. It gets errors after receiving a token that it doesn't have the correct permissions to perform steps I need it to perform.

I'm using the /.default scope in the token request, which is supposed to grab the permissions assigned to the service account, except that it only gets a few permissions instead of all of the application permissions assigned to the service account.

Screenshot 2025-04-04 at 16.00.56

I may not ever use the delegated permissions but they've been given just in case I need them. Is the fact that there are delegated and app permissions confusing the ability to grab a proper token?

I'm using the new Go Lang SDK, but I just switched to it. Before, I was using raw calls to the API endpoint, which was doing exactly the same thing.

My application shows the following error when using the requested token:

{"file":"notify.go:66","func":"notifications.(*Notifier).SendNotifications","level":"error","msg":"Failed to send Teams notification: failed to send recipients chat notification to team Postgres DB Notifications: failed to find team ID: failed to list teams: Missing role permissions on the request. API requires one of 'Team.ReadBasic.All, TeamSettings.Read.All, TeamSettings.ReadWrite.All'. Roles on the request 'Chat.ReadWrite.WhereInstalled, Chat.ReadWrite.All, Chat.Create'.","time":"2025-04-04 16:30:49"}

Obviously, from the list of permissions above, the roles have already been granted.

And the roles which are assigned to the token given to the client (as listed in the error):

"Token roles: [Chat.ReadWrite.WhereInstalled Chat.ReadWrite.All Chat.Create]"

Obviously, that's only three of the permissions out of all of the application permissions granted from the list above. I've tried adding the scopes in to the Graph client method call, but the API returns an error stating that I should just use /.default. Do I have to renew the token with additional scopes requested?

Some guidance on this would be greatly appreciated.

The code I'm using:

func (t *TeamsNotifier) GetMsClient(ctx context.Context, options azcore.TokenCredential) error {
  tenantID := t.TeamsConfig.Settings.TenantID
  clientID := t.TeamsConfig.Settings.ClientID
  clientSecret := t.TeamsConfig.Settings.ClientSecret

  if tenantID == "" || clientID == "" || clientSecret == "" {
   return fmt.Errorf("missing required Teams configuration: tenantID, clientID, or clientSecret")
  }

  cred, _ := azidentity.NewClientSecretCredential(
   tenantID,
   clientID,
   clientSecret,
   nil,
  )

  graphClient, err := msgraphsdk.NewGraphServiceClientWithCredentials(
   cred, []string{"https://graph.microsoft.com/.default"})
  if err != nil {
   return fmt.Errorf("failed to create Graph client: %w", err)
  }

  t.msclient = graphClient
  return nil
}
Microsoft Teams | Development
Microsoft Teams | Development

Building, integrating, or customizing apps and workflows within Microsoft Teams using developer tools and APIs


1 answer

Sort by: Most helpful
  1. Jim C 0 Reputation points
    2025-04-09T03:29:31.3066667+00:00

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.