使用adal.js 1.0.14时无限登录循环

时间:2017-07-21 07:52:01

标签: javascript adal.js

我遇到了adal.js 1.0.14的无限登录循环。 我没有使用角度,但我的应用是SPA。问题出现在Chrome和Edge中。

Repro步骤

  1. 以隐身模式访问我的SPA以确保清洁状态
  2. 创建身份验证上下文并调用handleWindowCallback()
  3. 应用程序提示我登录,因为getCachedToken(myClientId)为空
  4. 重定向到AAD登录页面
  5. 成功登录后重定向回网站
  6. 创建身份验证上下文并调用handleWindowCallback()
  7. 登录成功,一切都很顺利......
  8. 等待id_token过期(我通过在localStorage中将时间设置为0来模拟此事)
  9. 通过浏览器的刷新按钮
  10. 刷新SPA
  11. 创建身份验证上下文并调用handleWindowCallback()
  12. 应用程序提示我登录,因为getCachedToken(myClientId)为空
  13. 重定向到AAD登录页面
  14. 成功登录后重定向回网站
  15. 步骤10-13从此处无限重复
  16. 调试器逐步执行步骤10的handleWindowCallback(),我看到adal.login.error设置为" Nonce is not same as undefined"在adal.js代码的saveTokenFromHash范围内。

    adal.js详细记录

    以下是步骤11中控制台中的内容:

    authenticator.js:26 Fri, 21 Jul 2017 05:37:50 GMT:1.0.14-VERBOSE: State: 84c5d552-3f24-4f7f-a871-71e67f8d6482
    authenticator.js:26 Fri, 21 Jul 2017 05:37:50 GMT:1.0.14-INFO: Returned from redirect url
    authenticator.js:26 Fri, 21 Jul 2017 05:37:51 GMT:1.0.14-INFO: State status:true; Request type:LOGIN
    authenticator.js:26 Fri, 21 Jul 2017 05:37:51 GMT:1.0.14-INFO: State is right
    authenticator.js:26 Fri, 21 Jul 2017 05:37:51 GMT:1.0.14-INFO: Fragment has id token
    

    adal配置

    {
        cacheLocation: 'localStorage',
        clientId: 'my applicationId goes in here...',
        instance: 'https://login.microsoftonline.com/',
        postLogoutRedirectUri: window.location.origin,
        tenant: 'microsoft.onmicrosoft.com'
    }
    

    代码

    此代码在加载我的SPA时会提前执行(换句话说,重复步骤1-3和9-11)。

    var authenticationContext = new AuthenticationContext(configuration);
    
    authenticationContext.handleWindowCallback();
    
    if (!authenticationContext.getCachedToken(authenticationContext.config.clientId)) {
        authenticationContext.login();
    }
    

    我尝试了什么?

    • 我想在调用登录之前避免清除缓存。据我了解,这将解决问题,但不可取。
    • GitHub issue建议将anonymousEndpoints = []添加到a​​dal配置中,但这没有帮助。

    如果需要更多详细信息,请与我们联系。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我正在尝试使用版本为1.0.14的adal.js重现此问题但是失败了。要检查这是否是代码问题,我将附加我正在测试的代码演示:

<html>
<head>
<script src="js\adal.js"></script>
</head>
<body>
    <script>
        var configuration = {
            cacheLocation: 'localStorage',
            clientId: 'eca61fd9-f491-4f03-a622-90837bbc1711',
            instance: 'https://login.microsoftonline.com/',
            postLogoutRedirectUri: window.location.origin,
            tenant: 'adfei.onmicrosoft.com'
        }

        var authenticationContext = new AuthenticationContext(configuration);

        authenticationContext.handleWindowCallback();

        if (!authenticationContext.getCachedToken(authenticationContext.config.clientId)) {
            authenticationContext.login();
        }

        function login(){
            authenticationContext.login();
        }
    </script>

    <div>
    <button id="button1" onclick="login()">Login</button>
</div>
</body>    
</html>

在我将adal.expiration.key{clientId}设置为0后,应用程序成功获取了令牌。

答案 1 :(得分:2)

经过更多调试后,我已经解决了我的具体问题。

由于Javascript的性质,执行authenticationContext.login()之后的代码。调用login()会将应用程序导航到AAD登录页面,但在导航发生之前,我的代码仍然意外执行。我错误地假设一旦调用了login(),我的代码就完成了,并且它在ADAL手中。

我的未经证实的预感是,在acquireToken(authenticationContext.config.clientId)之后立即调用login(),状态正在被破坏,Nonce is not same as undefined显示为acquireToken,显示为错误。

我说未经证实因为我无法调试到导致问题的确切状态。但是,我将代码路径更改为在login()之后不立即调用acquireToken,并且问题不再发生。

费孝通的回答帮助我解决了我的问题,谢谢!本着为了别人的利益而分享我所得到的功能代码的精神,我改编了Fei的样本。基本上,我想在它们过期后续订令牌,所以我设置了一个间隔,每20秒调用一次login(),但不会在应用程序启动后立即调用(当<html> <head> <script src="js\adal.js"></script> </head> <body> <script> var configuration = { cacheLocation: 'localStorage', clientId: 'my client id', instance: 'https://login.microsoftonline.com/', postLogoutRedirectUri: window.location.origin, tenant: 'mytenant.onmicrosoft.com' } var authenticationContext = new AuthenticationContext(configuration); authenticationContext.handleWindowCallback(); if (!authenticationContext.getCachedToken(authenticationContext.config.clientId)) { authenticationContext.login(); } setInterval(function () { authenticationContext.acquireToken(authenticationContext.config.clientId, function (errorDescription, token, error) { // do callback stuff... }); }, 20000); function login() { authenticationContext.login(); } </script> <div> <button id="button1" onclick="login()">Login</button> </div> </body> </html> 可能发生时)。

{{1}}