由于Azure AD Auth Web API超时,ADAL.js令牌续订操作失败

时间:2017-10-18 07:29:28

标签: javascript adal adal.js

我们遇到了以下问题: 我们已经实现了Azure AD身份验证的Web API,并且我们已经成功地使用ADAL 1.0.12调用它(我们有自己的包装器来处理静态登录的iframe)。

现在我们将我们的包装器全部拆除并升级到最新版本并开始解决此处描述的问题:令牌更新操作超时。

API背后的Azure AD架构非常简单:一个已注册的Web应用程序,具有读取目录数据和登录并读取用户配置文件权限。我们有另一个本地应用程序注册了Web应用程序的权限(此处访问Web APP名称)。两个应用程序都在其清单中将oauth2AllowImplicitFlow设置为true。

这两个应用都注册了https://ourtenant.sharepoint.com/ *的通配符重定向URI(我们正在从SharePoint调用Web API)。此外,本机客户端应用程序已将重定向URI注册到Web API应用程序的唯一URI(应用程序ID URI)。

这两个应用程序之前已获得管理员同意 - 它们与旧版本的ADAL.js一起正常工作

所以,这是一些代码。请注意,我们已经尝试了两个没有displayCall回调(直接在当前页面刷新页面)和页面刷新(检查initLogin方法中的注释代码)。此外,我们还有一个用于在成功登录时生成弹出窗口或带有回调的iframe的开关。

问题在于authContext.acquireToken。请注意,如果我们调用OurNamespace.authContext.getCachedToken(OurNamespace.clientId),我们将获得该资源的存储标记。

另请注意,我们在每次刷新/ iframe / popup后调用handleWindowCallback。

无论浏览器如何都会发生。

OurNamespace = {

serviceMainUrl: "https://localhost:44339",
webApiAppIdUri: "WEB-API-URI",
tenant: "TENANT",
clientId: "NATIVE-APP-GUID", // Native APP
adalEndPoints: {
    get: null
},
adal: null,
authContext: null,
dummyAuthPage: null,
usePopup: true,

init: function () {
    this.dummyAuthPage = "DummmyLogin.aspx";
    OurNamespace.adalEndPoints.get = OurNamespace.serviceMainUrl + "/api/values";
    OurNamespace.authContext = new AuthenticationContext({
        tenant: OurNamespace.tenant + '.onmicrosoft.com',
        clientId: OurNamespace.clientId,
        webApiAppIdUri: OurNamespace.webApiAppIdUri,
        endpoints: OurNamespace.adalEndPoints,
        popUp: false,
        postLogoutRedirectUri: window.location.origin,
        cacheLocation: "localStorage",
        displayCall: OurNamespace.displayCall,
        redirectUri: _spPageContextInfo.siteAbsoluteUrl + "/Pages/" + OurNamespace.dummyAuthPage
    });
    var user = OurNamespace.authContext.getCachedUser(); // OurNamespace.authContext.getCachedToken(OurNamespace.clientId)
    if (user) {
        OurNamespace.azureAdAcquireToken();
    } else {
        OurNamespace.initLogin();
    }
},

initLogin: function () {
    //OurNamespace.authContext.config.displayCall = null;
    //var isCallback = OurNamespace.authContext.isCallback(window.location.hash);
    //OurNamespace.authContext.handleWindowCallback();

    //if (isCallback && !OurNamespace.authContext.getLoginError()) {
    //    window.location.href = OurNamespace.authContext._getItem(OurNamespace.authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
    //}

    OurNamespace.authContext.login();
},

displayCall: function (url) {
    var iframeId = "azure-ad-tenant-login",
        popup = null;
    if (OurNamespace.usePopup) {
        popup = window.open(url, 'auth-popup', 'width=800,height=500');
    } else {
        var iframe = document.getElementById(iframeId);
        if (!iframe) {
            iframe = document.createElement("iframe");
            iframe.setAttribute('id', iframeId);
            document.body.appendChild(iframe);
        }
        iframe.style.visibility = 'hidden';
        iframe.style.position = 'absolute';
        iframe.src = url;
        popup = iframe.contentDocument;
    }
    var intervalId = window.setInterval(function () {
        try {
            // refresh the contnetDocument for iframe
            if (!OurNamespace.usePopup)
                popup = iframe.contentDocument;
            var isCallback = OurNamespace.authContext.isCallback(popup.location.hash);
            OurNamespace.authContext.handleWindowCallback(popup.location.hash);
            if (isCallback && !OurNamespace.authContext.getLoginError()) {
                popup.location.href = OurNamespace.authContext._getItem(OurNamespace.authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
                window.clearInterval(intervalId);
                if (OurNamespace.usePopup) {
                    popup.close();
                }
                var user = OurNamespace.authContext.getCachedUser();
                if (user) {
                    console.log(user);
                } else {
                    console.error(OurNamespace.authContext.getLoginError());
                }
            }
        } catch (e) { }
    }, 400);
},

azureAdAcquireToken: function () {
    OurNamespace.authContext.acquireToken(OurNamespace.adalEndPoints.get, function (error, token) {
        if (error || !token) {
            SP.UI.Status.addStatus("ERROR", ('acquireToken error occured: ' + error), true);
            return;
        } else {
            OurNamespace.processWebApiRequest(token);
        }
    });
},

processWebApiRequest: function (token) {
    // Alternatively, in MVC you can retrieve the logged in user in the web api with HttpContext.Current.User.Identity.Name
    $.ajax({
        type: "GET",
        url: OurNamespace.adalEndPoints.get,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: {},
        headers: {
            'Authorization': 'Bearer ' + token
        },
        success: function (results) {
            var dataObject = JSON.parse(results);
            SP.UI.Status.addStatus("Info", "ADAL GET data success: " + dataObject.webApiUser);
            $(".grid-info").html("<h1 class=\"h1\">Current Web API authenticated user: " + dataObject.webApiUser + "</h1>");
        },
        error: function (xhr, errorThrown, textStatus) {
            console.error(xhr);
            SP.UI.Status.addStatus("ERROR", ('Service error occured: ' + textStatus), true);
        }
    });
}
}

2 个答案:

答案 0 :(得分:0)

我正在使用1.0.15 adal.js进行测试,并使用实际调用authContext.acquireToken的{​​{1}}成功获取访问令牌,以获取隐藏iframe的访问令牌。以下是完整的测试示例代码供您参考:

this._renewToken(resource, callback)

有用吗?或者您是否介意为此问题共享可运行的代码示例?

答案 1 :(得分:0)

我不确定您使用的是哪个版本的adal.js。但是配置对象的loadFrameTimeout设置可以设置为毫秒。检查adal.js文件的顶部,它应该在那里。