Vue.js Adal.js未在localStorage中设置道具
使用adal.js库而不使用Angular时遇到问题。(我正在使用Vue.js。) 我有一个身份验证上下文实例,它是用以下选项构造的(精确值已更改以保护无辜者):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的位置。成功登录后,另一个重定
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
?如果有的话,是的。它也应该起作用。你介意分享一下你正在开发的代码吗?