【发布时间】:2021-02-16 15:44:36
【问题描述】:
试图让它工作并且 GET / Patch 工作得很好,但是 POST 给了我 HTTP STATUS 400 和 403。必须是有作用域的东西。在 Azure AD 中,我设置了以下范围:
Mail.ReadWrite (Delegated)
Mail.ReadWrite (Application)
Mail.Send Delegated)
Mail.Send (Application)
因此,登录工作正常,获取/修补消息也是如此。只有 POST 似乎不起作用。 有关确切的错误消息,请参阅代码。
Angular10
App.module
export function MSALInstanceFactory(): IPublicClientApplication {
return new PublicClientApplication({
auth: {
clientId: 'xxxx',
authority: 'https://login.microsoftonline.com/common/',
redirectUri: '/',
postLogoutRedirectUri: '/#/login'
},
cache: {
cacheLocation: BrowserCacheLocation.LocalStorage,
storeAuthStateInCookie: isIE, // set to true for IE 11
},
system: {
loggerOptions: {
loggerCallback,
logLevel: LogLevel.Info,
piiLoggingEnabled: false
}
}
});
}
export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration {
const protectedResourceMap = new Map<string, Array<string>>();
protectedResourceMap.set('https://graph.microsoft.com/v1.0/me', ['user.read', 'mail.readWrite', 'email']);
// also tried these scopes ..
// protectedResourceMap.set('https://graph.microsoft.com/v1.0', ['user.read', 'mail.readWrite', 'email']);
// protectedResourceMap.set('https://graph.microsoft.com/v1.0/query', ['user.read', 'mail.readWrite', 'email']);
// protectedResourceMap.set('https://graph.microsoft.com/v1.0/search/query', ['user.read', 'mail.readWrite', 'email']);
return {
interactionType: InteractionType.Redirect,
protectedResourceMap
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return { interactionType: InteractionType.Redirect };
}
@NgModule({
imports: [
BrowserModule,
// etc..
],
declarations: [AppComponent],
providers: [
NgEventBus,
ChhServices,
SynclogService,
AppService,
AuthService,
GapiServices,
{
provide: ErrorHandler,
useClass: ErrorService,
},
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
},
{
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory
},
MsalService,
MsalGuard,
MsalBroadcastService
],
bootstrap: [AppComponent],
})
export class AppModule { }
身份验证服务
signIn() {
console.log('AuthService::signIn');
this.msalService.loginPopup().subscribe((result) => {
this.accessToken = result['accessToken'];
console.log('authority', result, this.accessToken);
});
}
testGraphApi() {
// 200 OK
const apiGet = this.httpClient.get(`https://graph.microsoft.com/v1.0/me/messages/`).subscribe((data) => {
console.log('get', '/me/messages', data);
});
const categories: any[] = ['custom'];
const body = {
subject: '2320, with tags',
flag: { flagStatus: 'flagged' }, // notFlagged
categories,
body: {
contentType: 'html',
content: 'lalala'
},
inferenceClassification: 'other'
};
const id = 'AQMkADAwATM3ZmYAZS0zOTkANy02MTAwAC0wMAItMDAKAEYAAAM_TfJTK-tISYhjZdaCkkbgBwCPpkVcscQ9QJF-EDzB8h_oAAACAQwAAACPpkVcscQ9QJF-EDzB8h_oAAACHbIAAAA=';
// 200 OK
const apiPatch = this.httpClient.patch(`https://graph.microsoft.com/v1.0/me/messages/${id}`, body).subscribe((data) => {
console.log('patch', '/me/messages', data);
});
const bodySendMail = {
'message': {
'subject': 'Meet for lunch?',
'body': {
'contentType': 'Text',
'content': 'The new cafeteria is open.'
},
// etc..
}
}
const headers = new HttpHeaders({ 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.accessToken}` });
// 403 Forbidden
// "code": "ErrorAccessDenied",
// "message": "Access is denied. Check credentials and try again.",
const apiSendMail = this.httpClient.post(`https://graph.microsoft.com/v1.0/me/sendMail`, bodySendMail, { headers }).subscribe((data) => {
console.log('post', '/me/sendMail', data);
});
const bodySearch = {
'requests': [
{
'entityTypes': [
'message'
],
'query': {
'queryString': 'ref:6019d6bf1ce3425fb833559e'
},
'from': 0,
'size': 5
}
]
}
// 400 Bad Request
// "code": "AuthenticationError",
// "message": "Error authenticating with resource",
const apiSearch = this.httpClient.post(`https://graph.microsoft.com/v1.0/search/query`, bodySearch, { headers }).subscribe((data) => {
console.log('post', '/search/query', data);
});
}
【问题讨论】:
-
我试过'/me/sendMail'和'/search/query'的api,都可以得到正确的响应。对于您的403错误,我认为您可以尝试使用'/users/{user id}'替换'/me'来排除错误流的错误。顺便说一句,您用来发送邮件的访问令牌更有可能没有正确的范围,我真的没有在您的代码中找到范围“Mail.Send”。对于 400 错误,我已将您的请求正文 json 对象复制到我的请求中并且它确实有效,所以我认为它也可能是由错误访问令牌引起的。我使用了 ropc 流程,它使用用户 ID 和密码来生成令牌。
-
以上有帮助吗?
-
@tiny-wa 1. ROPC 流程似乎不适合我的应用程序目的,服务于更大的匿名受众,但是,出于测试目的,它值得一试。 2. [mail.send] 已添加到范围中,现在可以正常工作了,所以谢谢 :-) 忽略了那个。 3. 似乎路径 /search/query 在组合中与我的令牌不被接受,是的.. 感觉就像我快到了,因为 post 和 patch 正在使用 /me 路径。仍在调查。
-
@SanJayFalcon 感谢您的回复,在出现 400 错误时,我认为您应该确保您使用的是具有 Delegated 权限的工作或学校帐户,它在 docs 中定义,只有这个可以支持如果您使用的是个人帐户,可能会导致 400 错误。
-
是的,工作/学校帐户仅支持委派权限。如果您使用的是应用场景,则不支持。据说我看到你正在调用 /me 端点,所以它不是应用场景。因此,只需确定您使用的是哪个帐户(个人/工作和学校)...
标签: post azure-active-directory microsoft-graph-api angular10 scopes