从 Web API 发送图形 API 邀请(POST 请求)工作正常,在 Angular 应用程序中使用它失败

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

当我通过 Postman 向用户发送图表 API 邀请时,用户会通过电子邮件收到邀请 Url。

这就是我如何实例化 GraphClientService - API 代码:

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 请求 - API 代码:

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请求消费-Angular/Front-end代码:

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.';
    });
}

在 Front-end 中调用同一个 Post 请求失败并显示消息:

"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/..."

我将 Unauthorized 设置为粗体,因为我已登录并在页面上应用了 CanActivate - AuthGuard。所以我被授权 + 我在 Post 请求的 header 中分配我的 Bearer 令牌。

在 Azure 门户中,我注册了 Web API 和 Front-End 应用程序 (Azure AD)。 我在两个应用程序 (Directory.ReadWrite.All、User.Invite.All 和 User.ReadWrite.All) 中添加了必要范围的权限。最重要的是,我授予了管理员同意...

改变我实例化 GraphClientService 的方式就完成了这项工作。 SigninKey 的验证是真的 - 所以我也必须提供这个

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);
                    }));

我还在 FE 中使用存储库服务,在发送 POST 请求时添加必要的 headers

inviteUser() {

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

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