Ошибка проверки токена API Microsoft Graph

Я бы использовал Microsoft Graph API в своем угловом веб-приложении.

Сначала я подключаюсь с помощью библиотеки msal. Когда я пытаюсь войти в систему с моим профилем, я получаю эту ошибку

Я настроил свое приложение как упомянутое в официальном образце git

MsalModule.forRoot({
  clientID: "Tenant ID",
  authority: "https://login.microsoftonline.com/common/",
  redirectUri: "http://localhost:4200/",
  validateAuthority : true,
  popUp: true
}),

Аутентификация работает, и я получаю токен.

Затем, когда я на домашней странице, я делаю второй запрос к Microsoft Graph API, чтобы получить информацию о пользователе, используя этот токен.

getProfile() {
  let header= new Headers();
  let tokenid= sessionStorage.getItem('msal.idtoken'); 
  header.set('Authorization', 'Bearer ' + tokenid)
  let url ="https://graph.microsoft.com/v1.0/me/"
  return this.http.get(url,{headers:header});
}

}

Я получаю 401 несанкционированную ошибку с ответом:

{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "Access token validation failure.",
    "innerError": {
      "request-id": "xxxxxx",
      "date": "2018-10-09T22:58:41"
    }
  }
}

Я не знаю, почему MG API не принимает мой токен. Использую ли я неверный URL-адрес?

ОБНОВЛЕНИЕ: я понял, что на самом деле я получаю id_token, который отличается от токена доступа. Как получить токен доступа из библиотеки MSAL для выполнения вызовов API MS GRAPH?

2 ответа

Решение

Согласно тому же образцу вы также можете прикрепить HttpInterceptorэто автоматически прикрепит токен доступа к каждому (внешнему) HTTP-вызову.

Прочитав документацию, я нашел следующую информацию.

acceptScopes: позволяет клиентууказывать желаемые области действия, на которые следует дать согласие. Области могут быть из нескольких ресурсов / конечных точек. Передавая здесь область действия, вы только согласитесь, и токен доступа не будет получен до тех пор, пока клиент фактически не вызовет API. Это необязательно, если вы используете MSAL только для входа (Аутентификация).

Это говорит о том, что с помощью HttpInterceptorне только прикрепляет токен доступа, но и извлекает его. Токен, который вы видите, вероятно, является просто токеном для вашего приложения, но не является допустимым токеном для Graph API.

Внутренне он используетgetCachedTokenInternal(scopes: Array<string>, user: User)чтобы получить новый токен доступа для определенного кода области, найденного здесь. Я не уверен, что вы также можете использовать этот метод для получения нового токена для этого ресурса. Я бы просто использовал перехватчик.

Вы можете попробовать скопировать токен доступа и посмотреть, как он выглядит на jwt.ms (программа просмотра токенов JWT от Microsoft) или jwt.io.

Любые токены, действительные для Graph, должны иметь аудиторию https://graph.microsoft.com, так что если вы проверяете токен (в jwt.ms), он должен как минимум иметь это значение.

"aud": "https://graph.microsoft.com",

Проблема в том, что вы используете id_token вместо токена доступа:

let tokenid= sessionStorage.getItem('msal.idtoken');

становится что-то вроде:

let tokenid= sessionStorage.getItem('msal.token'); // or msal.accesstoken

Обновление(согласно комментарию Филиппа)

Вам нужно выбрать области, на которые вы хотите ориентироваться в вашем приложении. Итак, похоже, что вам нужен профиль пользователя, поэтому вы захотите добавить свойство grantScopes, чтобы указать, какие области будет использовать ваше приложение:

MsalModule.forRoot({
  clientID: "Tenant ID",
  authority: "https://login.microsoftonline.com/common/",
  redirectUri: "http://localhost:4200/",
  validateAuthority : true,
  popUp: true,
  consentScopes: ["user.read"]
}),

Убедитесь, что вы добавили свою конечную точку в конфигурацию карты ресурсов. См. Эту ссылку: https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/samples/MSALAngularDemoApp

export const protectedResourceMap:[string, string[]][]=[ ['https://graph.microsoft.com/v1.0/me', ['user.read']] ];