Токен доступа пользователя Azure AD запрашивается библиотекой angular MSAL и подтверждается WEB API с помощью django_auth_adfs

Я пытаюсь настроить одностраничное приложение Angular с использованием библиотеки MS MSAL Angular для запроса Access token для получения данных пользователя из Microsoft Graph API и для аутентификации в пользовательском WEB API, построенном с помощью DJango Python Framework. Я использую библиотеки django_auth_adfs и rest_framework для создания этого API. Для настройки окружения я использовал следующие руководства :

В моем приложении Angular App я могу войти в систему с помощью учетных данных Azure AD. Я вижу, что маркеры доступа для MS Graph и для моего API получены, но последний не принимается моим WEB API.

На Azure AD я настроил два приложения. Одно для Angular frontend и одно для django backend. Вот мои конфигурации:

  1. Для бэкенда DJango:
  • Аутентификация с использованием веб-конфигурации с перенаправлением URI на http://localhost:8000/oauth2/callback и только учетных записей организационного каталога (без неявного потока).
  • Пробовали без и с секретом клиента (тот же результат).
  • Без конфигурации токенов
  • Разрешения на MS Ggaph без согласия администратора требуются и предоставлены для моей организации как статус.
  • Определена область для раскрытия API: api://xxxxxxxx-32d5-4175-9b05-xxxxxxxxxxxxx/access_as_user (согласие администраторов и пользователей включено) и мой фронтенд добавлен как авторизованное клиентское приложение.
  1. Для Angular App:
  • Аутентификация с использованием одностраничного приложения с URI перенаправления на http://localhost:4200/ и только учетных записей организационного каталога.
  • Нет секрета
  • .
  • Нет конфигурации токенов
  • API разрешение на MS Graph User.Read и на мой бэкенд API (доступ как пользователь). Оба разрешения подтверждены администратором.

Вот мои конфигурации django в settings.py:

INSTALLED_APPS = [
    ...
    "django_auth_adfs",
    "rest_framework",
    ...
]
MIDDLEWARE = [
    ...
    "django_auth_adfs.middleware.LoginRequiredMiddleware",
    "corsheaders.middleware.CorsMiddleware",
]
AUTHENTICATION_BACKENDS = (
    "django_auth_adfs.backend.AdfsAuthCodeBackend",
    "django_auth_adfs.backend.AdfsAccessTokenBackend",
)
AUTH_ADFS = {
    "TENANT_ID": AZURE_AD_TENANT_ID,
    "CLIENT_ID": AZURE_CLIENT_ID,
    "RELYING_PARTY_ID": AZURE_CLIENT_ID,
    "AUDIENCE": AZURE_CLIENT_ID,
    # "CLIENT_SECRET": AZURE_CLIENT_SECRET,   # Tried with or without it
    "CLAIM_MAPPING": {
        "first_name": "given_name",
        "last_name": "family_name",
        "email": "upn",
    },
    "GROUPS_CLAIM": "roles",
    "MIRROR_GROUPS": True,
    "USERNAME_CLAIM": "upn",
    "LOGIN_EXEMPT_URLS": [
        "^api/v0/",  # Prevent API from triggering a login redirect
    ],
}
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "django_auth_adfs.rest_framework.AdfsAccessTokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
    ],
    "DEFAULT_RENDERER_CLASSES": [
        "rest_framework.renderers.JSONRenderer",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        # Restrict API access for authenticated user by default
        "rest_framework.permissions.IsAuthenticated",
    ],
}

Вот мои конфигурации приложения angular: В app.module.ts:

export function MSALInstanceFactory(): IPublicClientApplication {
  return new PublicClientApplication({
    auth: {
      clientId: environment.azure.client_app_id,
      authority: environment.azure.authority,
      redirectUri: environment.azure.redirectUri,
      postLogoutRedirectUri: environment.azure.redirectUri,
      navigateToLoginRequestUrl: true
    },
    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> | null>();
  protectedResourceMap.set('https://graph.microsoft.com/v1.0/me', ['user.read']);
  protectedResourceMap.set('http://localhost:8000/api/v0/', ['api://xxxxxxxx-32d5-4175-9b05-xxxxxxxxxxxx/access_as_user']);

  return {
    interactionType: InteractionType.Redirect,
    protectedResourceMap,
  };
}

export function MSALGuardConfigFactory(): MsalGuardConfiguration {
  return {
    interactionType: InteractionType.Redirect,
    authRequest:   {
      scopes: [
        'user.read',
        'openid',
        'profile',
        'api://xxxxxxxx-32d5-4175-9b05-xxxxxxxxxxxx/access_as_user'
      ]
    },
    loginFailedRoute: "/"
  };
}

В сетевом шпионе браузера я вижу, что запросы токена доступа хорошо выполняются библиотекой Angular MSAL для обоих защищенных ресурсов (MS graph и мой DJango API), но тот, который вводится в качестве Bearer при взаимодействии с моим API, получает 401 ошибку.

Кто-нибудь видит, что я упускаю? Заранее благодарю за помощь.

Я наконец-то нашел ответ самостоятельно! В конфигурации Django, конфигурация AUDIENCE была неправильной:

"AUDIENCE": AZURE_CLIENT_ID, должно быть "AUDIENCE": "api://" + AZURE_CLIENT_ID,

После этого исправления маркер доступа подтвержден.

Вернуться на верх