角度5 adal.js自动令牌更新负载角度两次或更多

Tho*_*ter 3 azure-active-directory adal.js angular angular5

我尝试了许多角度adal库,但令牌的更新不是自动完成的.

这是我使用的配置.

在package.json中

"@types/adal": "^1.0.29",
"@types/adal-angular": "^1.0.0",
"adal-angular": "^1.0.17",
Run Code Online (Sandbox Code Playgroud)

adal-angular带有两个脚本adal.jsadal-angular.js.我认为adal.angular.js仅适用于旧angularjs解决方案.所以我使用了adal.js和一个包装@ types/adal.

并包括adal.js.angular-cli.json

  "scripts": [
    "../node_modules/adal-angular/lib/adal.js"
  ],
Run Code Online (Sandbox Code Playgroud)

在我的angular 5应用程序中,我使用adal登录并向另一个URL上的网站发出请求api请求.

使用的配置

  JwtConfig: {
    tenant: "a1d50521-9687-4e4d-a76d-xxxxxxxxx",
    clientId: "8d708afe-2966-40b7-918c-xxxxxxxx",
    isAngular: true
  },
Run Code Online (Sandbox Code Playgroud)

我的authService看起来像

  import { } from "adal";
  @Injectable()
  export class AuthService {
  private _config: adal.Config;
  private _context: adal.AuthenticationContext;
  constructor() {
    Logging = {
      level: 3,
      log: function (message) {
        console.log(message);
      }
    };
    this._config = environment.JwtConfig;
    this._context = new AuthenticationContext(this._config);
  }
Run Code Online (Sandbox Code Playgroud)

不需要日志记录,但启用adal.js日志记录

很多示例在localstorage中存储令牌,但此令牌仅在1小时内有效.为了解决这个问题,我每次都调用acquireToken.如果它已过期,它将为我提供缓存的令牌或续订令牌.

  acquireToken(): Observable<string> {
    return new Observable<string>((subscriber: Subscriber<string>) => {
      if (window.frameElement && window.frameElement.id === "adalIdTokenFrame")
        subscriber.next(null);
      else {
        const user = this._context.getCachedUser();
        return this._context.acquireToken(environment.JwtConfig.clientId, (message: string, token: string) => {
          subscriber.next(token);
        });
      }
    });
  }
Run Code Online (Sandbox Code Playgroud)

为了使这项工作正常,有许多棘手的事情.

更新是在隐藏的I帧中完成的,这是对Microsoft AD的请求

https://login.microsoftonline.com/xxxtenantIDxxx/oauth2/authorize?response_type=id_token&client_id=xxx-xx-x-xx

响应将重定向到http://localhost:4200/...在此隐藏的IFrame中启动另一个角度应用程序

此检查if (window.frameElement && window.frameElement.id === "adalIdTokenFrame")将阻止无限循环的隐藏IFrame.

该行const user = this._context.getCachedUser();是必需的,以便adal知道有用户并且将更新用户而不是用户必须登录的消息.

这似乎工作正常.如果令牌已过期New Date(profile.exp*1000)数小时.用户仍然可以续订此令牌.

有没有办法阻止我的Angular应用程序加载到隐藏的Iframe中?使用工作包装或其他技巧?

Tho*_*ter 6

添加脚本以防止在隐藏框架中加载角度.这使得令牌的登录/续订更快.它防止在浏览器中第一次加载时开始树的角度.

此脚本可以添加到index.html.它检查它是否加载到隐藏帧中,解码令牌并防止加载角度.

<script>
    if (window.parent && window.parent.AuthenticationContext) {
      var self = window.parent._adalInstance;
      var hash = window.location.hash;

      if (self.isCallback(hash)) {
        self.info("Returned from redirect url");

        var requestInfo = self.getRequestInfo(hash);
        var tokenReceivedCallback = self._callBackMappedToRenewStates[requestInfo.stateResponse];

        self.saveTokenFromHash(requestInfo);

        var token = requestInfo.parameters[self.CONSTANTS.ACCESS_TOKEN] || requestInfo.parameters[self.CONSTANTS.ID_TOKEN];
        var tokenType = self.CONSTANTS.ACCESS_TOKEN;
        var errorDesc = requestInfo.parameters[self.CONSTANTS.ERROR_DESCRIPTION];
        var error = requestInfo.parameters[self.CONSTANTS.ERROR];
        try {
          if (tokenReceivedCallback)
            tokenReceivedCallback(errorDesc, token, error, tokenType);
        } catch (err) {
          self.error("Error occurred in user defined callback function: " + err);
        }
        document.write('<style type="text/undefined">');
      }
    }
  </script>
Run Code Online (Sandbox Code Playgroud)