angular 5 adal.js 自动令牌更新加载角度两次或更多次 [英] angular 5 adal.js automatic token renew in load angular twice or more

查看:31
本文介绍了angular 5 adal.js 自动令牌更新加载角度两次或更多次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have tried a number of angular-adal libraries but the renew of the token is not automatic done.

这是我使用的配置.

在 package.json 中

In package.json

"@types/adal": "^1.0.29",
"@types/adal-angular": "^1.0.0",
"adal-angular": "^1.0.17",

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

adal-angular come with two scripts adal.js and adal-angular.js. I think adal.angular.js is only for old angularjs solutions. So I used adal.js and an wrapper @types/adal.

并在 .angular-cli.json

  "scripts": [
    "../node_modules/adal-angular/lib/adal.js"
  ],

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

In my angular 5 application I use adal to log on and make request api request to website on another url.

使用的配置

  JwtConfig: {
    tenant: "a1d50521-9687-4e4d-a76d-xxxxxxxxx",
    clientId: "8d708afe-2966-40b7-918c-xxxxxxxx",
    isAngular: true
  },

我的 authService 看起来像

My authService looks like

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

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

The logging is not needed but enables adal.js logging

许多示例将令牌存储在 localstorage 中,但此令牌仅在 1 小时内有效.为了解决这个问题,我每次都调用acquireToken.它会给我缓存的令牌,如果它过期了,它会给我一个更新的.

A lot of examples store there token in localstorage but this token is only valid for 1 hour. To solve this problem I call acquireToken everytime. It will give me the cached token or a renewed if it is expired.

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

要使这项工作正常进行,有许多棘手的事情.

To get this working right there are a number of tricky things.

更新是在一个隐藏的 I 框架中完成的,它向 microsoft AD 发出请求

The renewal is done in a hidden I frame what makes a request to microsoft AD

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

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

the response will redirect to http://localhost:4200/... that will start another angular application in this hidden IFrame

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

this check if (window.frameElement && window.frameElement.id === "adalIdTokenFrame") will prevent an endless loop of hidden IFrames.

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

The line const user = this._context.getCachedUser(); is needed so that adal knows there is a user and will renew the user instead a message that the user must login.

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

This seems to work ok. If the token is expired New Date(profile.exp*1000) for several hours. The user can still renew this token.

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

Is there a way to prevent that my Angular apllication is loaded in the hidden Iframe? With a working wrapper or some other trick?

推荐答案

添加脚本以防止在隐藏框架中加载 angular.这使得令牌的登录/更新更快.它可以防止 angular 在浏览器中第一次加载时启动树次.

Add a script to prevent loading angular in the hidden frame. This makes the logon/renew of token faster. It prevent that angular is started tree times when loaded for the first time in the browser.

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

This script can be added to the index.html. It check if it is loaded in a hidden frame, decode the token and prevent loading angular.

<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>

更新:使用 Adal en MSAL,您可以使用弹出窗口,但某些 IE 版本对此存在问题.MSAL没有adal那么复杂

Update: with Adal en MSAL you can use popup but some IE versions have problems with this. MSAL is not as complex as adal

import * as Msal from 'msal';
export const config: Msal.Configuration  {
  auth: { clientId: '.....-1796-...'},
  cache: { cacheLocation: 'localStorage' },
};
constructor() {
    this.adAuthenticationContext = new Msal.UserAgentApplication(config);
  }

这篇关于angular 5 adal.js 自动令牌更新加载角度两次或更多次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆