Vue.js Adal.js未在localStorage中设置道具

Vue.js Adal.js未在localStorage中设置道具,vue.js,adal,adal.js,Vue.js,Adal,Adal.js,使用adal.js库而不使用Angular时遇到问题。(我正在使用Vue.js。) 我有一个身份验证上下文实例,它是用以下选项构造的(精确值已更改以保护无辜者): let config={ 租户:'', 客户端ID:“”, 重定向URI:'http://myapplication.com/index.html', //是的, cacheLocation:“本地存储” } 在我的登录页面上,我调用authContext.login(),它首先将我重定向到我登录AAD的位置。成功登录后,另一个重定

使用adal.js库而不使用Angular时遇到问题。(我正在使用Vue.js。)

我有一个身份验证上下文实例,它是用以下选项构造的(精确值已更改以保护无辜者):

let config={
租户:'',
客户端ID:“”,
重定向URI:'http://myapplication.com/index.html',
//是的,
cacheLocation:“本地存储”
}
在我的登录页面上,我调用authContext.login(),它首先将我重定向到我登录AAD的位置。成功登录后,另一个重定向会将我带回到我的应用程序,在上面配置的URI处,以及URL中的id_令牌参数。但是,库不会将任何令牌或其他属性存储在本地存储中,只有少数属性是配置的结果

成功登录后,我在localStorage中的所有功能

{
  adal.access.token.key: "", 
  adal.error: ""
  adal.error.description: ""
  adal.expiration.key: "0"
  adal.idtoken: ""
  adal.login.error: ""
  adal.login.request: "http://myapplication.com/#/login"
  adal.nonce.idtoken: "<a non-empty string>"
  adal.session.state: ""
  adal.state.login: "<a non-empty string>"
  adal.token.keys: ""
  adal.username: ""
}
{
adal.access.token.key:“”,
adal.error:“
adal.error.description:“
adal.expiration.key:“0”
adal.idtoken:“
adal.login.error:“
adal.login.request:“http://myapplication.com/#/login"
adal.nonce.idtoken:“
adal.session.state:“
adal.state.login:“
adal.token.keys:“
adal.username:“
}
因此,就AAD而言,我已经成功地进行了身份验证,但库本身似乎不知道用户登录了什么,与它们关联的令牌是什么,令牌何时过期,等等。任何关于如何继续的建议都将不胜感激。提前感谢您的阅读

用于JavaScript的Active Directory身份验证库(ADAL JS)帮助您在单页应用程序中使用Azure AD处理身份验证。该库针对与AngularJS一起工作进行了优化

除非我们对其进行编码,否则它不会将令牌保存到缓存中。您可以从adal angular.js检查相关代码。以下是一段代码供您参考:

<html>
<head>
 <script src="https://unpkg.com/vue"></script>
 <script src="node_modules\adal-angular\lib\adal.js"> </script>
 <script src="config.js"> </script>
</head>

<body>
<div>
  <button onclick="login()" >Login</button>
</div>
   <script>

var authContext=new AuthenticationContext(config);
function login(){
authContext.login();

}

function init(configOptions){
  if (configOptions) {
                    // redirect and logout_redirect are set to current location by default
                    var existingHash = window.location.hash;
                    var pathDefault = window.location.href;
                    if (existingHash) {
                        pathDefault = pathDefault.replace(existingHash, '');
                    }
                    configOptions.redirectUri = configOptions.redirectUri || pathDefault;
                    configOptions.postLogoutRedirectUri = configOptions.postLogoutRedirectUri || pathDefault;


                    // create instance with given config                 
                } else {
                    throw new Error('You must set configOptions, when calling init');
                }

                // loginresource is used to set authenticated status
                updateDataFromCache(authContext.config.loginResource);

}

 var _oauthData = { isAuthenticated: false, userName: '', loginError: '', profile: '' };
   var updateDataFromCache = function (resource) {
                // only cache lookup here to not interrupt with events
                var token = authContext.getCachedToken(resource);
                _oauthData.isAuthenticated = token !== null && token.length > 0;
                var user = authContext.getCachedUser() || { userName: '' };
                _oauthData.userName = user.userName;
                _oauthData.profile = user.profile;
                _oauthData.loginError = authContext.getLoginError();
            };

init(config);

function saveTokenFromHash(){
    var hash = window.location.hash;
     var requestInfo = authContext.getRequestInfo(hash);
       if (authContext.isCallback(hash)) {
                        // callback can come from login or iframe request

                        var requestInfo = authContext.getRequestInfo(hash);
                        authContext.saveTokenFromHash(requestInfo);
                        window.location.hash = '';

                        if (requestInfo.requestType !== authContext.REQUEST_TYPE.LOGIN) {
                            authContext.callback = window.parent.AuthenticationContext().callback;
                        }                 
                    } 
}

saveTokenFromHash();
    </script>

</body>
</html>
saveTokenFromHash
方法也会将令牌保存到缓存中,该函数将在页面重定向回Angular应用程序后执行

adal.js:

AuthenticationContext.prototype.saveTokenFromHash = function (requestInfo) {
    this._logstatus('State status:' + requestInfo.stateMatch);
    this._saveItem(this.CONSTANTS.STORAGE.ERROR, '');
    this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, '');

    // Record error
    if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ERROR_DESCRIPTION)) {
        this._logstatus('Error :' + requestInfo.parameters.error);
        this._logstatus('Error description:' + requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);
        this._saveItem(this.CONSTANTS.STORAGE.FAILED_RENEW, requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);
        this._saveItem(this.CONSTANTS.STORAGE.ERROR, requestInfo.parameters.error);
        this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, requestInfo.parameters[this.CONSTANTS.ERROR_DESCRIPTION]);

        if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) {
            this._loginInProgress = false;
            this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, requestInfo.parameters.errorDescription);
        } else {
            this._renewActive = false;
        }
    } else {

        // It must verify the state from redirect
        if (requestInfo.stateMatch) {
            // record tokens to storage if exists
            this._logstatus('State is right');
            if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.SESSION_STATE)) {
                this._saveItem(this.CONSTANTS.STORAGE.SESSION_STATE, requestInfo.parameters[this.CONSTANTS.SESSION_STATE]);
            }

            var keys, resource;

            if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ACCESS_TOKEN)) {
                this._logstatus('Fragment has access token');
                // default resource
                this._renewActive = false;
                resource = this.config.loginResource;
                if (!this._hasResource(resource)) {
                    keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || '';
                    this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER);
                }

                if (requestInfo.requestType === this.REQUEST_TYPE.RENEW_TOKEN) {
                    resource = this._getResourceFromState(requestInfo.stateResponse);
                }

                // save token with related resource
                this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource, requestInfo.parameters[this.CONSTANTS.ACCESS_TOKEN]);
                this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource, this._expiresIn(requestInfo.parameters[this.CONSTANTS.EXPIRES_IN]));
            }

            if (requestInfo.parameters.hasOwnProperty(this.CONSTANTS.ID_TOKEN)) {
                this._loginInProgress = false;
                this._user = this._createUser(requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);
                if (this._user && this._user.profile) {
                    if (this._user.profile.nonce !== this._getItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN)) {
                        this._user = null;
                        this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'Nonce is not same as ' + this._idTokenNonce);
                    } else {
                        this._saveItem(this.CONSTANTS.STORAGE.IDTOKEN, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);

                        // Save idtoken as access token for app itself
                        resource = this.config.clientId;
                        if (!this._hasResource(resource)) {
                            keys = this._getItem(this.CONSTANTS.STORAGE.TOKEN_KEYS) || '';
                            this._saveItem(this.CONSTANTS.STORAGE.TOKEN_KEYS, keys + resource + this.CONSTANTS.RESOURCE_DELIMETER);
                        }
                        this._saveItem(this.CONSTANTS.STORAGE.ACCESS_TOKEN_KEY + resource, requestInfo.parameters[this.CONSTANTS.ID_TOKEN]);
                        this._saveItem(this.CONSTANTS.STORAGE.EXPIRATION_KEY + resource, this._user.profile.exp);
                    }
                }
            }
        } else {
            this._saveItem(this.CONSTANTS.STORAGE.ERROR, 'Invalid_state');
            this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, 'Invalid_state');
            if (requestInfo.requestType === this.REQUEST_TYPE.LOGIN) {
                this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, 'State is not same as ' + requestInfo.stateResponse);
            }
        }
    }
};
此函数将在
this.$get
中调用,如下所示:

// special function that exposes methods in Angular controller
// $rootScope, $window, $q, $location, $timeout are injected by Angular
this.$get = ['$rootScope', '$window', '$q', '$location', '$timeout', function ($rootScope, $window, $q, $location, $timeout) {

    var locationChangeHandler = function () {
        var hash = $window.location.hash;

        if (_adal.isCallback(hash)) {
            // callback can come from login or iframe request

            var requestInfo = _adal.getRequestInfo(hash);
            _adal.saveTokenFromHash(requestInfo);
            $window.location.hash = '';

            if (requestInfo.requestType !== _adal.REQUEST_TYPE.LOGIN) {
                _adal.callback = $window.parent.AuthenticationContext().callback;
            }

            // Return to callback if it is send from iframe
            if (requestInfo.stateMatch) {
                if (typeof _adal.callback === 'function') {
                    // Call within the same context without full page redirect keeps the callback
                    if (requestInfo.requestType === _adal.REQUEST_TYPE.RENEW_TOKEN) {
                        // Idtoken or Accestoken can be renewed
                        if (requestInfo.parameters['access_token']) {
                            _adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), requestInfo.parameters['access_token']);
                            return;
                        } else if (requestInfo.parameters['id_token']) {
                            _adal.callback(_adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION), requestInfo.parameters['id_token']);
                            return;
                        }
                    }
                } else {
                    // normal full login redirect happened on the page
                    updateDataFromCache(_adal.config.loginResource);
                    if (_oauthData.userName) {
                        //IDtoken is added as token for the app
                        $timeout(function () {
                            updateDataFromCache(_adal.config.loginResource);
                            $rootScope.userInfo = _oauthData;
                            // redirect to login requested page
                            var loginStartPage = _adal._getItem(_adal.CONSTANTS.STORAGE.START_PAGE);
                            if (loginStartPage) {
                                $location.path(loginStartPage);
                            }
                        }, 1);
                        $rootScope.$broadcast('adal:loginSuccess');
                    } else {
                        $rootScope.$broadcast('adal:loginFailure', _adal._getItem(_adal.CONSTANTS.STORAGE.ERROR_DESCRIPTION));
                    }
                }
            }
        } else {
            // No callback. App resumes after closing or moving to new page.
            // Check token and username             
            updateDataFromCache(_adal.config.loginResource);
            if (!_adal._renewActive && !_oauthData.isAuthenticated && _oauthData.userName) {
                if (!_adal._getItem(_adal.CONSTANTS.STORAGE.FAILED_RENEW)) {
                    // Idtoken is expired or not present
                    _adal.acquireToken(_adal.config.loginResource, function (error, tokenOut) {
                        if (error) {
                            $rootScope.$broadcast('adal:loginFailure', 'auto renew failure');
                        } else {
                            if (tokenOut) {
                                _oauthData.isAuthenticated = true;
                            }
                        }
                    });
                }
            }
        }

        $timeout(function () {
            updateDataFromCache(_adal.config.loginResource);
            $rootScope.userInfo = _oauthData;
        }, 1);
    }
...
下面是一个示例代码,可以将令牌保存到缓存中供您参考:

<html>
<head>
 <script src="https://unpkg.com/vue"></script>
 <script src="node_modules\adal-angular\lib\adal.js"> </script>
 <script src="config.js"> </script>
</head>

<body>
<div>
  <button onclick="login()" >Login</button>
</div>
   <script>

var authContext=new AuthenticationContext(config);
function login(){
authContext.login();

}

function init(configOptions){
  if (configOptions) {
                    // redirect and logout_redirect are set to current location by default
                    var existingHash = window.location.hash;
                    var pathDefault = window.location.href;
                    if (existingHash) {
                        pathDefault = pathDefault.replace(existingHash, '');
                    }
                    configOptions.redirectUri = configOptions.redirectUri || pathDefault;
                    configOptions.postLogoutRedirectUri = configOptions.postLogoutRedirectUri || pathDefault;


                    // create instance with given config                 
                } else {
                    throw new Error('You must set configOptions, when calling init');
                }

                // loginresource is used to set authenticated status
                updateDataFromCache(authContext.config.loginResource);

}

 var _oauthData = { isAuthenticated: false, userName: '', loginError: '', profile: '' };
   var updateDataFromCache = function (resource) {
                // only cache lookup here to not interrupt with events
                var token = authContext.getCachedToken(resource);
                _oauthData.isAuthenticated = token !== null && token.length > 0;
                var user = authContext.getCachedUser() || { userName: '' };
                _oauthData.userName = user.userName;
                _oauthData.profile = user.profile;
                _oauthData.loginError = authContext.getLoginError();
            };

init(config);

function saveTokenFromHash(){
    var hash = window.location.hash;
     var requestInfo = authContext.getRequestInfo(hash);
       if (authContext.isCallback(hash)) {
                        // callback can come from login or iframe request

                        var requestInfo = authContext.getRequestInfo(hash);
                        authContext.saveTokenFromHash(requestInfo);
                        window.location.hash = '';

                        if (requestInfo.requestType !== authContext.REQUEST_TYPE.LOGIN) {
                            authContext.callback = window.parent.AuthenticationContext().callback;
                        }                 
                    } 
}

saveTokenFromHash();
    </script>

</body>
</html>

登录
var authContext=新的AuthenticationContext(配置);
函数登录(){
authContext.login();
}
函数初始化(配置选项){
如果(配置选项){
//默认情况下,重定向和注销\重定向设置为当前位置
var existingHash=window.location.hash;
var pathDefault=window.location.href;
if(existingHash){
pathDefault=pathdault.replace(existingHash“”);
}
configOptions.redirectUri=configOptions.redirectUri | | pathDefault;
configOptions.postLogoutRedirectUri=configOptions.postLogoutRedirectUri | |路径默认值;
//使用给定的配置创建实例
}否则{
抛出新错误('调用init时必须设置configOptions');
}
//loginresource用于设置已验证状态
updateDataFromCache(authContext.config.loginResource);
}
var _oauthData={isAuthenticated:false,用户名:'',登录错误:'',配置文件:'};
var updateDataFromCache=函数(资源){
//此处仅缓存查找,不中断事件
var token=authContext.getCachedToken(资源);
_oauthData.isAuthenticated=token!==null&&token.length>0;
var user=authContext.getCachedUser()| |{用户名:''};
_oauthData.userName=user.userName;
_oauthData.profile=user.profile;
_oauthData.loginError=authContext.getLoginError();
};
初始化(配置);
函数saveTokenFromHash(){
var hash=window.location.hash;
var requestInfo=authContext.getRequestInfo(散列);
if(authContext.isCallback(哈希)){
//回调可以来自登录或iframe请求
var requestInfo=authContext.getRequestInfo(散列);
authContext.saveTokenFromHash(requestInfo);
window.location.hash='';
if(requestInfo.requestType!==authContext.REQUEST\u TYPE.LOGIN){
authContext.callback=window.parent.AuthenticationContext().callback;
}                 
} 
}
saveTokenFromHash();

非常感谢您的回复。当
handleWindowCallback
已经为我调用了这两个函数时,为什么需要手动调用
getRequestInfo
saveTokenFromHash
呢?你是说你自己调用了
handleWindowCallback
?如果有的话,是的。它也应该起作用。你介意分享一下你正在开发的代码吗?