当我通过 loginRedirect 登录时,我可以看到重定向上填充了MSAL令牌,但是当尝试使用令牌时,我收到此错误:

无法以静默方式从存储中检索令牌 . AADB2C90077:用户没有现有会话,并且在通过连接到Azure B2C的Angular SPA应用程序成功登录后,请求提示参数的值为“无” .

我在GitHub Issue中发现了类似的东西,然后在由于没有令牌而被强制执行 tokenPopup() 之后出现错误之后对another issue发表了评论:

“此应用程序没有足够的权限来对此Web资源执行操作”

他们可能没有关联,但他们都阻止了我

在此代码中, loginredirect 工作,我可以在本地存储中看到令牌,然后在下次使用令牌时,我会收到控制台日志 authCallback-err ,然后记录"Could not silently retrieve token from storage..."并首先提到错误 .

@Injectable()
export class MsalService {
  private access_token: string;

  private tenantConfig = {
    tenant: environment.tenant,
    clientID: environment.clientID,
    signUpSignInPolicy: environment.signUpSignInPolicy,
    b2cScopes: environment.b2cScopes
  };

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

  private clientApplication: Msal.UserAgentApplication;

  private authCallback(errorDesc: any, token: any, error: any, tokenType: any) {
    var _this = this;
    console.log("authCallback");
    // For loginRedirect, tokenType = "id_token". For acquireTokenRedirect, tokenType:"access_token".
    if (token) {
      console.log("authCallback- Id token", token);
      this.access_token = token;
    } else {
      console.log("authCallback-err : " + error + ":" + errorDesc);
      alert("error here");
    }
  }

  constructor() {
    this.clientApplication = new Msal.UserAgentApplication(
      this.tenantConfig.clientID,
      this.authority,
      this.authCallback,
      {
        cacheLocation: "localStorage",
        redirectUri: "https://localhost:4200/msallogin"
      }
    );
  }

  get authenticated() {
    const user = this.clientApplication.getUser();
    if (user) {
      return true;
    }
    return false;
  }

  public loginRedirect(): void {
    this.clientApplication.loginRedirect(this.tenantConfig.b2cScopes);
  }

  public getAuthenticationToken(): Promise<string> {
    return this.clientApplication
      .acquireTokenSilent(this.tenantConfig.b2cScopes)
      .then(token => {
        console.log("Got silent access token: ", token);
        return token;
      })
      .catch(error => {
        console.log("Could not silently retrieve token from storage.", error);
        return this.clientApplication
          .acquireTokenPopup(this.tenantConfig.b2cScopes)
          .then(token => {
            console.log("Got popup access token: ", token);
            return token;
          })
          .catch(error => {
            console.log("Could not retrieve token from popup.", error);
            this.clientApplication.acquireTokenRedirect(
              this.tenantConfig.b2cScopes
            );
            return Promise.resolve("");
          });
      });
  }

  public login(): 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;
              console.log("ACCESS TOKEN: \n " + _this.access_token);
            },
            function(error: any) {
              _this.clientApplication
                .acquireTokenPopup(_this.tenantConfig.b2cScopes)
                .then(
                  function(accessToken: any) {
                    _this.access_token = accessToken;
                  },
                  function(error: any) {
                    alert("Error acquiring the popup:\n" + error);
                  }
                );
            }
          );
      },
      function(error: any) {
        alert("Error during login:\n" + error);
      }
    );
  }

  logout(): void {
    this.clientApplication.logout();
  }

  isOnline(): boolean {
    return this.clientApplication.getUser() != null;
  }

  public getUser(): string {
    const user = this.clientApplication.getUser();
    if (!user) {
      return null;
    }

    return user.name;
  }
}

然后,一旦我登录,重定向就会回来,我会以角度重定向到另一条路线 . 该组件注入了MSAL服务 .

此时,我调用 getUser() 并可以看到我的用户名 . 然后我单击一个按钮发出Web请求,将下一段代码作为拦截器发出,但由于没有令牌而失败

@Injectable()导出类MSALAuthenticationHttpInterceptor实现HttpInterceptor {constructor(private msalService:MsalService){}

@intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    return Observable.fromPromise(
      this.msalService.getAuthenticationToken()
    ).switchMap(token => {
      req = req.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`
        }
      });
      return next.handle(req);
    });
  }
}

我的B2C作为连接到Azure功能的邮递员应用程序,它绝对是B2C配置,我的代码或MSAL . If it is我无法从B2C策略刀片修改这些设置,因此不确定他是如何解决的 .

B2c配置列在1的评论中 . 我花了很多时间在这上面,它可能很容易,但是在各种应用程序中有多个范围,并且范围刀片的不同问题和更改看起来比它应该更难是

使用:

Angular: "5.2.0"
MSAL: "^0.1.5"