Sending Graph API invite (POST Request) from Web API works fine, Consuming it in an Angular App fails

Viewed 237

When I send a Graph API Invite to a user through Postman, the User get's an invitational Url by Email.

This is how I instantiate the GraphClientService - API Code:

var tokenProvider = new AzureServiceTokenProvider();
string token = tokenProvider.GetAccessTokenAsync("https://graph.microsoft.com", "tenant-id-mqksmlsqdkjf").GetAwaiter().GetResult(); 
_graphServiceClient = new GraphServiceClient(
    new DelegateAuthenticationProvider(x =>
    {
        x.Headers.Authorization = new AuthenticationHeaderValue(
            "Bearer", token);

        return Task.FromResult(0);
    }));

Post Request - API Code:

var invitation = new Invitation()
{
    InvitedUserEmailAddress = data["email"].ToString(),
    InviteRedirectUrl = Configuration["AzureAd:urlFrontEnd"],
    SendInvitationMessage = true
};

await _graphServiceClient.Invitations
    .Request()
    .AddAsync(invitation);

return Ok("Invitation sent to " + data["email"].ToString());

Post Request Consumption - Angular/Front-end Code:

inviteUser() {
    const body = JSON.stringify(
      {
        "email": "user@mail.com"
      }
    );
    this.http.post('https://apiUrl.azurewebsites.net/api/user/invite', body, {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + localStorage.getItem('jwt')
      })
    }).subscribe(response => {
      this.router.navigate(['/']);
    }, err => {
      this.errorMessage = 'Invalid Email or Password.';
    });
}

Calling that same Post Request in the Front-end fails with the Message :

"Code: Unauthorized\r\nMessage: Insufficient privileges to perform requested operation by the application '00000003-0000-0000-c000-000000000000'. ControllerName=MSGraphInviteAPI, ActionName=CreateInvite, URL absolute path=/api/..."

I made Unauthorized bold, because I am logged in and CanActivate - AuthGuard is applied on the page. So I am authorized + I assign my Bearer token in the header of the Post Request.

In Azure Portal I registered the Web API and the Front-End Applications (Azure AD). I added permissions for the necessary scopes in both Apps (Directory.ReadWrite.All, User.Invite.All & User.ReadWrite.All). On top of that I granted Admin Consent...

1 Answers

Changing how I instantiate the GraphClientService did the job. Validation on SigninKey was true - so I had to provide this too

string authority = "https://login.microsoftonline.com/{0}";
string graphResourceId = "https://graph.microsoft.com";
string tenantId = Configuration["AzureAd:TenantId"];
string clientId = Configuration["AzureAd:ClientId"];
string secret = Configuration["AzureAd:SigninKey"];
authority = String.Format(authority, tenantId);
AuthenticationContext authContext = new AuthenticationContext(authority);
var accessToken = authContext.AcquireTokenAsync(graphResourceId, new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(clientId, secret)).Result.AccessToken;
_graphServiceClient = new GraphServiceClient(
                new DelegateAuthenticationProvider(
                    requestMessage =>
                    {
                        requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);

                        return Task.FromResult(0);
                    }));

I also use a repository service in the FE where I add the necessary headers when sending a POST request

inviteUser() {

    const body = JSON.stringify(
      {
        email: 'user@email.com'
      }
    );

    this.repoService.create('api/user/invite', body)
      .subscribe(res => { ...
      },
      (error => { ...
      })
    );
}
Related