Azure active directory 带有移动应用程序的ADAL.JS

Azure active directory 带有移动应用程序的ADAL.JS,azure-active-directory,adal,oracle-maf,adal.js,Azure Active Directory,Adal,Oracle Maf,Adal.js,我正在尝试将一些Oracle提供的移动应用程序框架应用程序(MAF)移动应用程序与Azure AD身份验证进行集成。我已经尝试过Java方法,很明显 所以我决定尝试使用ADAL.JS使用Javascript登录页面选项。由于MAF通过转换成HTML5/Javascript/Cordova来创建跨平台兼容的代码,我认为我可以让JS选项工作,而不必求助于多个特定于SDK的解决方案,如ADAL Android或ADAL-IOS。因为我可以将所有内容包装在HTML页面中,因为我可以使用ADAL.JS所需

我正在尝试将一些Oracle提供的移动应用程序框架应用程序(MAF)移动应用程序与Azure AD身份验证进行集成。我已经尝试过Java方法,很明显

所以我决定尝试使用ADAL.JS使用Javascript登录页面选项。由于MAF通过转换成HTML5/Javascript/Cordova来创建跨平台兼容的代码,我认为我可以让JS选项工作,而不必求助于多个特定于SDK的解决方案,如ADAL Android或ADAL-IOS。因为我可以将所有内容包装在HTML页面中,因为我可以使用ADAL.JS所需的OAUTH隐式流选项。我让ADAL.JS部分在我的PC上使用本地节点/Webpack dev服务器作为重定向URI。(注意,就像那个例子一样,我更喜欢使用strict adal.js选项,避免使用任何角度的js内容)。然而,我在安卓移动设备上部署时遇到了一个问题。这似乎是由于回复URI造成的。提示输入Azure凭据并提供这些凭据后,会产生以下错误

AADSTS50011:回复地址'file:///data/user/0/com.company.app/storage/assets/FARs/ViewController/public_html/SignOn/login.html'具有无效的方案

我发现在部署到移动设备时,Azure注册的应用程序必须设置为“Native”类型,而不是我已经设置的“Web/API”。根据一个MSFT示例(由于我没有足够的rep来包含两个以上的链接,所以无法包含该示例),重定向URI必须设置为“”。但我还是犯了同样的错误

自@FeiXue回复后的更新

我使用的是原始端点,而不是2.0。当我将重定向URI设置为这样时:

重定向URI=

浏览器会在地址栏中返回此信息,并保持在空白屏幕上,不会发出令牌。它可以在PC浏览器和移动浏览器上实现这一点

id_token=EYJ0Exaiioijkv1qilchBgcioijsuzi1niising1dci6imezu4wqlptn3M0bk4qmry6imezu4wqlptn3M0bk4qmryAmjgmfgtgrntsj9.(为简洁而缩短)&state=e1ce94fb-6310-4dec-9e8b-053727ceb9b8&session\u state=1beaffa4d-af55-415b-85d5-83e4035594

但是,对于完全相同的代码,在PC上设置redirectURI时,它会返回一个访问令牌:


redirectURI=您是否正在使用Azure AD V2.0端点进行开发

如果没有,我们可以在门户上为本机应用程序配置所需的重定向URI。但是,错误消息表明文件协议不是验证方案

在这个场景中,我们可以使用http或https,因为您是使用HTML开发的

在Azure AD V2.0端点中,我们目前无法为本机应用设置重定向Uri。我们可以使用
urn:ietf:wg:oauth:2.0:oob
https://login.microsoftonline.com/common/oauth2/nativeclient
用于重定向Uri。第一个用于设备的本机应用程序,第二个用于在浏览器中托管的客户端(web视图)

最后,请确保请求中的重定向uri使用的是您为门户注册的正确uri。您还可以在浏览器上测试请求,以缩小此问题是否是请求中不正确的
重定向\u uri
造成的。关于授权请求,您可以参考以下链接:

更新(如果从磁盘打开HTML导致弹出页面未关闭,则没有href属性)
这个问题是因为当我们从设备(磁盘)打开HTML页面时,父HTML页面(登录页面)无法获取弹出页面的位置。因此,父页面无法根据弹出页面的位置关闭该页面。为了解决这个问题,我建议您使用web API后端开发或托管登录页面。

根据我对这个主题的研究,这里是关于ADAL.JS和本机(移动)设备支持的要点

正如@fei xue msft所提到的,ADAL.JS既不适用于本地/移动设备,也不适用于本地/移动设备。ADAL.JS是在考虑“原始”Azure端点的情况下编写的,而不是为移动/本机设备提供更多功能的v2.0端点(请参阅下面关于两个不同端点选项的更多信息)。不过,您可以尝试一种方法(使用v2.0端点),但它不再被主动更新,因此您可以自己进行更新。新的MSFT方法是使用新的MSAL库,它是针对v2.0端点编写的。然而,JS库还没有MSAL,但有传言说在某个时候会有MSAL。有关两个不同Azure端点(“原始”与“v2.0”)的更多信息,请参阅下面的链接。对这一点的困惑是我在排除故障时感到沮丧的原因,因此我帮助其他人走上这条道路

因此,如果您希望在移动设备上获得Azure Oauth身份验证,请首先决定要使用哪一个Azure端点(下面作为v2.0的支持链接确实有一些原始端点没有的限制)。您可以通过查看下面列出的元数据文档链接来确定您的租户的特定端点,只需替换您的租户名称或ID。您应该可以使用其中一个

要为特定类型的端点(原始版本与v2.0版本)注册应用程序,请使用下面引用的相应应用程序注册门户链接。然后,要决定为本机/移动设备创建Azure auth解决方案的选项,请参阅每个端点版本的代码示例,并确保该示例用于“本机”,否则它可能无法在移动设备上工作。例如,您将不会看到原始端点库选项的ADAL.JS示例,但会看到Cordova的示例(这就是@fei xue msft建议使用该方法的原因)。对于v2.0端点示例,您将看到MSAL/Xamarin选项,对于Javascript选项,您可以尝试以下方法
<!DOCTYPE html>
<html>
<head>
    <title>Authenticate User with ADAL JS</title>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/adal.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            "use strict";

            var variables = {
                azureAD: "mytenant.onmicrosoft.com",
                clientId: "cc8ed7e0-56e9-45c9-b01e-xxxxxxxxxx"
            }

            window.config = {
                tenant: variables.azureAD,
                clientId: variables.clientId,
                postLogoutRedirectUri: window.location.origin,
                redirectUri: "https://login.microsoftonline.com/common/oauth2/nativeclient",
                endpoints: {
                    aisApiUri: "cc8ed7e0-56e9-45c9-b01e-xxxxxxxxxx"
                }
                //cacheLocation: "localStorage"
            };

            var authContext = new AuthenticationContext(config);

            var isCallback = authContext.isCallback(window.location.hash);

            authContext.handleWindowCallback();

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

            var user = authContext.getCachedUser();

            if (!user) {

                authContext.login();
            }

            authContext.acquireToken(config.endpoints.aisApiUri, function (error, token) {
                if (error || !token) {
                    console.log("ADAL error occurred in acquireToken: " + error);
                    return;
                }
                else {

                    var accessToken = "Authorization:" + " Bearer " + token;

                    console.log("SUCCESSFULLY FETCHED TOKEN: " + accessToken);

                }
            });

        });
    </script>
</head>
<body>
    <h1>Test Login</h1>
</body>
</html>
AuthenticationContext.prototype._loginPopup = function (urlNavigate) {
        var popupWindow = this._openPopup(urlNavigate, "login", this.CONSTANTS.POPUP_WIDTH, this.CONSTANTS.POPUP_HEIGHT);
        if (popupWindow == null) {
            this.warn('Popup Window is null. This can happen if you are using IE');
            this._saveItem(this.CONSTANTS.STORAGE.ERROR, 'Error opening popup');
            this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, 'Popup Window is null. This can happen if you are using IE');
            this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'Popup Window is null. This can happen if you are using IE');
            if (this.callback)
                this.callback(this._getItem(this.CONSTANTS.STORAGE.LOGIN_ERROR), null, this._getItem(this.CONSTANTS.STORAGE.ERROR));
            return;
        }
        if (this.config.redirectUri.indexOf('#') != -1)
            var registeredRedirectUri = this.config.redirectUri.split("#")[0];
        else
            var registeredRedirectUri = this.config.redirectUri;
        var that = this;
        var pollTimer = window.setInterval(function () {
            if (!popupWindow || popupWindow.closed || popupWindow.closed === undefined) {
                that._loginInProgress = false;
                window.clearInterval(pollTimer);
            }
            try {
                //there is no href property if open the HTML from disk
                if (popupWindow.location.href.indexOf(registeredRedirectUri) != -1) {
                    if (that.isAngular) {
                        that._onPopUpHashChanged(popupWindow.location.hash);
                    }
                    else {
                        that.handleWindowCallback(popupWindow.location.hash);
                    }
                    window.clearInterval(pollTimer);
                    that._loginInProgress = false;
                    that.info("Closing popup window");
                    popupWindow.close();
                }
            } catch (e) {
            }
        }, 20);
    };