【问题标题】:Why my API Management not autorize my application using AD B2C?为什么我的 API 管理不使用 AD B2C 自动化我的应用程序?
【发布时间】:2018-03-30 14:54:14
【问题描述】:

我正在开发一个使用 AD B2C 作为 OpenID Connect Provider 的云应用程序。

在我的配置环境下:

广告 B2C

在我的 AD B2C 中,我创建了两个应用程序:

  • DeveloperPortal - 用于在开发者门户中配置授权。
  • MyClient - 用于在内部配置授权。

API 网关

我创建了一个API Management。在 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>

我的客户

我的客户端是一个 Angular 4 应用程序。我正在使用MSAL.js微软官方库。

这是我的授权服务 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." }

但如果我尝试通过 Developer Portal 直接访问,我可以成功调用相同的 API。

为什么我的 API Manager 不授权我的应用程序?

非常感谢

【问题讨论】:

  • 您是否将令牌添加到您的 http 请求中?例如:authentication.httpInterceptor.ts
  • 嗨,spotmahn,我也尝试过使用邮递员,并使用浏览器检查了请求。

标签: angular typescript azure-ad-b2c azure-api-management


【解决方案1】:

我认为发生上述错误是因为 API 网关无法识别从 Angular 客户端传递的访问令牌的 aud(受众)声明。

上述场景类似于"Azure AD B2C: Call a .NET web API from a .NET web app",其中 Angular 客户端是 Web 应用,API 网关是 Web API。

我推荐你:

1) Create an Azure AD B2C app 代表 API 网关。输入此应用的 App ID URI 以识别 API 网关。

2) Add one or more permission scopes 到此网关应用程序和/或保留user_impersonation 的默认权限范围。

3) Create an Azure AD B2C app 代表 Angular 客户端。您已经创建了这个客户端应用程序。

4) Grant access by the client app to the gateway app 以便客户端应用程序可以获取访问令牌以代表登录用户调用网关应用程序。

5) Update the validate-jwt policy 带有网关应用的应用 ID。

<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 数组中。

【讨论】:

  • 我们在现有的 ADAL Angular SPA 中使用了openid-config url 没有 /v2.0/。这样 validate-jwt 函数每次都会失败。我只是尝试输入 v1.0 url 和 v2.0 以及那些适用于现有客户端和我们从 ADAL 更新到 MSAL 库的。可惜没有更好的文档记录,或者我找不到它。
【解决方案2】:

基于

{ "statusCode": 401, "message": "未经授权。访问令牌丢失或无效。" }

在发出 http 请求时,您似乎没有从 Angular 应用程序发送令牌。在 Angular 中执行此操作的一种方法是使用 interceptor

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

来源:authentication.httpInterceptor.ts

【讨论】:

  • 您好,我向您保证我发送了授权码。在我的应用程序中,我有一个注入令牌的拦截器,我用邮递员手动尝试了令牌。
猜你喜欢
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2017-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多