Почему мое управление API не авторизует мое приложение с помощью AD B2C?

Я разрабатываю облачное приложение, использующее AD B2C в качестве поставщика OpenID Connect.

Ниже моей среды конфигурации:

AD B2C

В моем AD B2C я создал два приложения:

  • DeveloperPortal - используется для настройки авторизации внутри портала разработчика.
  • MyClient - используется для настройки авторизации внутри.

API-шлюз

Я создал одно Управление API. После импорта API я добавил одну политику вроде следующей:

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
            <openid-config url="https://login.microsoftonline.com/{myTenantAzureId}/.well-known/openid-configuration?p={myPolicies}" />
</validate-jwt>

MyClient

Мой клиент - приложение Angular 4. Я использую официальную библиотеку MSAL.js Microsoft.

Это мой класс TypeScript службы авторизации:

import { Injectable } from '@angular/core';
declare var bootbox: any;
declare var Msal: any;

@Injectable()
export class MsalService {
  public access_token: string;
  private logger = new Msal.Logger(this.loggerCallback, { level: Msal.LogLevel.Verbose });

  tenantConfig = {
    tenant: "{myTenant}.onmicrosoft.com",
    clientID: '{MyClientClientId}',
    signUpSignInPolicy: "{myPolicies}",
    b2cScopes: ["openid"]
  };

  options = {
    logger: this.logger,
    postLogoutRedirectUri: window.location.protocol + "//" + window.location.host
  }

  //authority = null;
  authority = "https://login.microsoftonline.com/tfp/" + this.tenantConfig.tenant + "/" + this.tenantConfig.signUpSignInPolicy;


  clientApplication = new Msal.UserAgentApplication(
    this.tenantConfig.clientID,
    this.authority,
    this.authCallback,
    this.options
  );

  public login(callback: Function): void {
    var _this = this;
    this.clientApplication.loginPopup(this.tenantConfig.b2cScopes).then(function (idToken: any) {
      _this.clientApplication.acquireTokenSilent(_this.tenantConfig.b2cScopes).then(
        function (accessToken: any) {
          _this.access_token = accessToken;
          localStorage.setItem("access_token", accessToken);
          if (callback) {
            callback(accessToken);
          }
        }, function (error: any) {
          _this.clientApplication.acquireTokenPopup(_this.tenantConfig.b2cScopes).then(
            function (accessToken: any) {
              _this.access_token = accessToken;
              console.log(accessToken);
            }, function (error: any) {
              bootbox.alert("Error acquiring the popup:\n" + error);
            });
        })
    }, function (error: any) {
      console.log(error);
      bootbox.alert("Error during login:\n" + error);
    });
  }

  public logout(callback: Function): void {
    this.clientApplication.logout();
    if (callback) {
      callback();
    }
  }

  private loggerCallback(logLevel, message, piiLoggingEnabled) {
    console.log(message);
  }
  private authCallback(errorDesc: any, token: any, error: any, tokenType: any) {
    if (token) {
    }
    else {
      console.error(error + ":" + errorDesc);
    }
  }
}

Проблема

Если я попытаюсь вызвать один API управления API с заголовком авторизации с токеном доступа, я получаю эту ошибку:

{ "statusCode": 401, "message": "Unauthorized. Access token is missing or invalid." }

Но если я попытаюсь получить доступ напрямую через портал разработчика, я смогу успешно вызвать тот же API. введите здесь описание изображения

Почему мой API Manager не авторизует мое приложение?

Большое спасибо


person ilMattion    schedule 30.03.2018    source источник
comment
Вы добавляете токен в свой HTTP-запрос? пример: https://github.com/Gimly/NetCoreAngularAzureB2CMsal/blob/master/ClientApp/app/interceptors/authentication.httpInterceptor.ts   -  person spottedmahn    schedule 30.03.2018
comment
Привет, spottedmahn, я пробовал также с почтальоном, и я проверил запрос с помощью браузера.   -  person ilMattion    schedule 30.03.2018


Ответы (2)


Я считаю, что указанная выше ошибка возникает из-за того, что шлюз API не распознает требование aud (аудитория) для токена доступа, который передается от клиента Angular.

Вышеупомянутый сценарий похож на " Azure AD B2C: вызов веб-API .NET из веб-приложения .NET ", где клиент Angular - это веб-приложение, а шлюз API - это веб-API.

Я рекомендую вам:

1) Создайте приложение Azure AD B2C, представляющее шлюз API. Введите URI идентификатора приложения для этого приложения, чтобы идентифицировать шлюз API.

2) Добавьте одну или несколько областей разрешений к этому приложению шлюза и / или оставьте область разрешений по умолчанию user_impersonation.

3) Создайте приложение Azure AD B2C, которое представляет клиент Angular. Вы уже создали это клиентское приложение.

4) Предоставьте клиентскому приложению доступ к приложению шлюза, чтобы клиентское приложение могло получить токен доступа, чтобы действовать от имени вошедшего в систему пользователя для вызова приложения шлюза.

5) Обновите validate-jwt политику, указав идентификатор приложения для шлюза.

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">  
  <openid-config url="https://login.microsoftonline.com/tfp/{tenant}/{policy}/v2.0/.well-known/openid-configuration" />
  <audiences>
    <audience><!-- Paste the app ID for the gateway app --></audience>
  </audiences>
</validate-jwt>

6) Включите все области разрешений, которые были добавлены на шаге 2, для выдачи клиентскому приложению в массив tenantConfig.b2cScopes.

person Chris Padgett    schedule 31.03.2018
comment
Мы использовали openid-config url без /v2.0/ для существующего ADAL Angular SPA. При этом функция validate-jwt каждый раз терпела неудачу. Я просто попытался ввести URL-адрес v1.0 И v2.0, и они работали как для существующих клиентов, так и для нашей обновленной библиотеки ADAL до MSAL. Жалко, что это не где-то лучше задокументировано, или я не смог его найти. - person DHFW; 07.10.2019

Основано на

{"statusCode": 401, "message": "Неавторизовано. Токен доступа отсутствует или недействителен". }

Казалось бы, вы не отправляете токен из приложения Angular при выполнении HTTP-запроса. Один из способов сделать это в Angular - использовать перехватчик.

@Injectable()
export class AuthenticationHttpInterceptor implements HttpInterceptor {

    constructor(private authenticationService: AuthenticationService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return Observable.fromPromise(this.authenticationService.getAuthenticationToken())
            .switchMap(token => {
                req = req.clone({
                    setHeaders: {
                        Authorization: `Bearer ${token}`
                    }
                });
                return next.handle(req);
            });
    }
}

Источник: https://github.com/Gimly/NetCoreAngularAzureB2CMsal/blob/master/ClientApp/app/interceptors/authentication.httpInterceptor.ts

person spottedmahn    schedule 30.03.2018
comment
Привет, гарантирую, что пришлю код авторизации. Внутри моего приложения у меня есть один перехватчик, который вводит токен, и я попробовал токен вручную с почтальоном. - person ilMattion; 30.03.2018