mirror of
https://github.com/amark/gun.git
synced 2025-06-22 22:12:33 +00:00
'remember-me' now fully functional with essential test cases
This commit is contained in:
parent
2f69bddc2a
commit
49e76826d8
212
sea.js
212
sea.js
@ -51,7 +51,7 @@
|
|||||||
validity: 60 * 60 * 12, // 12 hours
|
validity: 60 * 60 * 12, // 12 hours
|
||||||
session: true,
|
session: true,
|
||||||
// or return new Promise(function(resolve, reject){(resolve(props))})
|
// or return new Promise(function(resolve, reject){(resolve(props))})
|
||||||
hook: function(props) {return props} // { iat, exp, alias, proof }
|
hook: function(props) {return props} // { iat, exp, alias, remember }
|
||||||
};
|
};
|
||||||
|
|
||||||
// let's extend the gun chain with a `user` function.
|
// let's extend the gun chain with a `user` function.
|
||||||
@ -115,7 +115,7 @@
|
|||||||
var at = one.at, pub = one.pub;
|
var at = one.at, pub = one.pub;
|
||||||
var remaining = (aliases.length - index) > 1;
|
var remaining = (aliases.length - index) > 1;
|
||||||
if(!at.put){
|
if(!at.put){
|
||||||
return (!remaining) && reject({err: 'Public key does not exist!'})
|
return (!remaining) && reject({err: 'Public key does not exist!'});
|
||||||
}
|
}
|
||||||
// attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.)
|
// attempt to PBKDF2 extend the password with the salt. (Verifying the signature gives us the plain text salt.)
|
||||||
SEA.read(at.put.salt, pub).then(function(salt){
|
SEA.read(at.put.salt, pub).then(function(salt){
|
||||||
@ -124,16 +124,21 @@
|
|||||||
}).catch(function(e){reject({err: 'Failed to create proof!'})})
|
}).catch(function(e){reject({err: 'Failed to create proof!'})})
|
||||||
.then(function(proof){
|
.then(function(proof){
|
||||||
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
||||||
return SEA.read(at.put.auth, pub).then(function(auth){
|
SEA.read(at.put.auth, pub).then(function(auth){
|
||||||
return SEA.de(auth, proof)
|
return SEA.de(auth, proof)
|
||||||
.catch(function(e){reject({err: 'Failed to decrypt secret!'})});
|
.catch(function(e){reject({err: 'Failed to decrypt secret!'})});
|
||||||
}).then(function(priv){
|
}).then(function(priv){
|
||||||
// now we have AES decrypted the private key, from when we encrypted it with the proof at registration.
|
// now we have AES decrypted the private key, from when we encrypted it with the proof at registration.
|
||||||
// if we were successful, then that meanswe're logged in!
|
// if we were successful, then that meanswe're logged in!
|
||||||
return remaining ? undefined // Not done yet
|
if(priv){
|
||||||
: priv ? resolve({pub: pub, priv: priv, at: at, proof: proof})
|
resolve({pub: pub, priv: priv, at: at, proof: proof})
|
||||||
// Or else we failed to log in...
|
} else if(!remaining){
|
||||||
: reject({err: 'Failed to decrypt private key!'});
|
reject({err: 'Public key does not exist!'});
|
||||||
|
}
|
||||||
|
// return remaining ? undefined // Not done yet
|
||||||
|
// : priv ? resolve({pub: pub, priv: priv, at: at, proof: proof})
|
||||||
|
// // Or else we failed to log in...
|
||||||
|
// : reject({err: 'Failed to decrypt private key!'});
|
||||||
}).catch(function(e){reject({err: 'Failed read secret!'})});
|
}).catch(function(e){reject({err: 'Failed read secret!'})});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -154,8 +159,7 @@
|
|||||||
user._.pub = key.pub;
|
user._.pub = key.pub;
|
||||||
//console.log("authorized", user._);
|
//console.log("authorized", user._);
|
||||||
// persist authentication
|
// persist authentication
|
||||||
return authpersist(user._, key.proof, opts)
|
return authpersist(user._, key.proof, opts).then(function(){
|
||||||
.then(function(){
|
|
||||||
// emit an auth event, useful for page redirects and stuff.
|
// emit an auth event, useful for page redirects and stuff.
|
||||||
Gun.on('auth', user._);
|
Gun.on('auth', user._);
|
||||||
// returns success with the user data credentials.
|
// returns success with the user data credentials.
|
||||||
@ -163,6 +167,42 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updatestorage(proof,priv,pin){
|
||||||
|
return function(props){
|
||||||
|
return new Promise(function(resolve, reject){
|
||||||
|
if(!Gun.obj.has(props, 'alias')){return resolve()}
|
||||||
|
if (proof && Gun.obj.has(props, 'iat')) {
|
||||||
|
props.proof = proof;
|
||||||
|
delete props.remember; // Not stored if present
|
||||||
|
|
||||||
|
var remember = (pin && {alias: props.alias, pin: pin }) || props;
|
||||||
|
var protected = !authsettings.session && pin && props;
|
||||||
|
|
||||||
|
return SEA.write(JSON.stringify(remember), priv).then(function(signed){
|
||||||
|
sessionStorage.setItem('user', props.alias);
|
||||||
|
sessionStorage.setItem('remember', signed);
|
||||||
|
if (!protected) {
|
||||||
|
localStorage.removeItem('remember');
|
||||||
|
}
|
||||||
|
return !protected || SEA.en(protected, pin).then(function(encrypted){
|
||||||
|
return encrypted && SEA.write(encrypted, priv)
|
||||||
|
.then(function(encsig){
|
||||||
|
localStorage.setItem('remember', encsig);
|
||||||
|
}).catch(reject);
|
||||||
|
}).catch(reject);
|
||||||
|
}).then(function(){
|
||||||
|
resolve(props);
|
||||||
|
}).catch(function(e){reject({err: 'Session persisting failed!'})});
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('remember');
|
||||||
|
sessionStorage.removeItem('user');
|
||||||
|
sessionStorage.removeItem('remember');
|
||||||
|
}
|
||||||
|
resolve(props);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This internal func persists User authentication if so configured
|
// This internal func persists User authentication if so configured
|
||||||
function authpersist(user,proof,opts){
|
function authpersist(user,proof,opts){
|
||||||
// opts = { pin: 'string' }
|
// opts = { pin: 'string' }
|
||||||
@ -172,51 +212,25 @@
|
|||||||
// IF authsettings.validity === 0 THEN no remember-me, ever
|
// IF authsettings.validity === 0 THEN no remember-me, ever
|
||||||
// IF authsettings.session === true THEN no window.localStorage in use; nor PIN
|
// IF authsettings.session === true THEN no window.localStorage in use; nor PIN
|
||||||
// ELSE if no PIN then window.sessionStorage
|
// ELSE if no PIN then window.sessionStorage
|
||||||
return new Promise(function(resolve, reject){
|
var pin = Gun.obj.has(opts, 'pin') && opts.pin
|
||||||
var pin = Gun.obj.has(opts, 'pin') && opts.pin;
|
&& new Buffer(opts.pin, 'utf8').toString('base64');
|
||||||
var doIt = function(props){
|
var args = { alias: user.alias };
|
||||||
if (props.alias) {
|
|
||||||
if (props.proof && props.iat) {
|
|
||||||
pin = pin && new Buffer(pin, 'utf8').toString('base64');
|
|
||||||
var remember = (pin && {alias: props.alias, pin: pin }) || props;
|
|
||||||
var protected = !authsettings.session && pin && props;
|
|
||||||
|
|
||||||
return SEA.write(JSON.stringify(remember), user.sea).then(function(signed){
|
if(proof && authsettings.validity){
|
||||||
sessionStorage.setItem('user', props.alias);
|
args.iat = Math.ceil(Date.now() / 1000); // seconds
|
||||||
sessionStorage.setItem('remember', signed);
|
args.exp = authsettings.validity * 60; // seconds
|
||||||
if (!protected) {
|
if (Gun.obj.has(opts, 'pin')){
|
||||||
localStorage.removeItem('remember');
|
args.remember = true; // for hook - not stored
|
||||||
}
|
|
||||||
return !protected || SEA.en(protected, pin).then(function(encrypted){
|
|
||||||
return encrypted && SEA.write(encrypted, user.sea)
|
|
||||||
.then(function(encsig){
|
|
||||||
localStorage.setItem('remember', encsig);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).then(function(){
|
|
||||||
resolve({ok: 0});
|
|
||||||
}).catch(function(){reject({err: 'Session persisting failed!'});});
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('remember');
|
|
||||||
sessionStorage.removeItem('user');
|
|
||||||
sessionStorage.removeItem('remember');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolve({ok: 0});
|
|
||||||
};
|
|
||||||
var args = { alias: user.alias };
|
|
||||||
|
|
||||||
if(proof && authsettings.validity){
|
|
||||||
args.proof = proof;
|
|
||||||
args.iat = Math.ceil(Date.now() / 1000); // seconds
|
|
||||||
args.exp = authsettings.validity * 60; // seconds
|
|
||||||
var props = authsettings.hook(args);
|
|
||||||
if(props instanceof Promise){props.then(doIt);
|
|
||||||
} else {doIt(props)}
|
|
||||||
} else {
|
|
||||||
doIt(args);
|
|
||||||
}
|
}
|
||||||
});
|
var props = authsettings.hook(args);
|
||||||
|
if(props instanceof Promise){
|
||||||
|
return props.then(updatestorage(proof, user.sea, pin));
|
||||||
|
} else {
|
||||||
|
return updatestorage(proof, user.sea, pin)(props);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return updatestorage()(args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This internal func recalls persisted User authentication if so configured
|
// This internal func recalls persisted User authentication if so configured
|
||||||
@ -225,6 +239,7 @@
|
|||||||
var remember = sessionStorage.getItem('remember');
|
var remember = sessionStorage.getItem('remember');
|
||||||
var alias = sessionStorage.getItem('user');
|
var alias = sessionStorage.getItem('user');
|
||||||
var err = 'Not authenticated';
|
var err = 'Not authenticated';
|
||||||
|
var pin;
|
||||||
|
|
||||||
// Already authenticated?
|
// Already authenticated?
|
||||||
if(Gun.obj.has(root._.user._, 'pub')){
|
if(Gun.obj.has(root._.user._, 'pub')){
|
||||||
@ -243,29 +258,55 @@
|
|||||||
return (!remaining) && reject({err: 'Public key does not exist!'})
|
return (!remaining) && reject({err: 'Public key does not exist!'})
|
||||||
}
|
}
|
||||||
// got pub, time to unwrap Storage data...
|
// got pub, time to unwrap Storage data...
|
||||||
return SEA.read(remember, pub).then(function(props){
|
return SEA.read(remember, pub, true).then(function(props){
|
||||||
props = !props.slice ? props : JSON.parse(props);
|
props = !props.slice ? props : JSON.parse(props);
|
||||||
|
var checkProps = function(decr){
|
||||||
|
return new Promise(function(resolve){
|
||||||
|
if(Gun.obj.has(decr, 'proof')
|
||||||
|
&& Gun.obj.has(decr, 'alias') && decr.alias === alias){
|
||||||
|
var proof = decr.proof;
|
||||||
|
var iat = decr.iat; // No way hook to update this
|
||||||
|
delete decr.proof; // We're not gonna give proof to hook!
|
||||||
|
var doIt = function(args){
|
||||||
|
if(Math.floor(Date.now() / 1000) < (iat + args.exp)){
|
||||||
|
args.iat = iat;
|
||||||
|
args.proof = proof;
|
||||||
|
return args;
|
||||||
|
} else {Gun.log('Authentication expired!')}
|
||||||
|
};
|
||||||
|
var hooked = authsettings.hook(decr);
|
||||||
|
return resolve(((hooked instanceof Promise)
|
||||||
|
&& hooked.then(doIt))
|
||||||
|
|| doIt(decr));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
};
|
||||||
// Got PIN ?
|
// Got PIN ?
|
||||||
if(Gun.obj.has(props, 'pin')){
|
if(Gun.obj.has(props, 'pin')){
|
||||||
|
pin = props.pin;
|
||||||
// Yes! We can get localStorage secret if signature is ok
|
// Yes! We can get localStorage secret if signature is ok
|
||||||
return SEA.read(localStorage.getItem('remember'), pub)
|
return SEA.read(localStorage.getItem('remember'), pub)
|
||||||
.then(function(encrypted){
|
.then(function(encrypted){
|
||||||
// And decrypt it
|
// And decrypt it
|
||||||
return SEA.de(encrypted, props.pin);
|
return SEA.de(encrypted, pin);
|
||||||
}).then(function(decr){
|
}).then(function(decr){
|
||||||
decr = !decr.slice ? decr : JSON.parse(decr);
|
decr = !decr.slice ? decr : JSON.parse(decr);
|
||||||
// And return proof if for matching alias
|
// And return proof if for matching alias
|
||||||
return Gun.obj.has(decr, 'proof')
|
return checkProps(decr);
|
||||||
&& Gun.obj.has(decr, 'alias') && decr.alias === alias
|
|
||||||
&& decr.proof;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// No PIN, let's try short-term proof if for matching alias
|
// No PIN, let's try short-term proof if for matching alias
|
||||||
return Gun.obj.has(props, 'proof')
|
return checkProps(props);
|
||||||
&& Gun.obj.has(props, 'alias') && props.alias === alias
|
}).then(function(args){
|
||||||
&& props.proof;
|
var proof = args && args.proof;
|
||||||
}).then(function(proof){
|
if (!proof){
|
||||||
if (!proof){return reject({err: 'No secret found!'})}
|
return updatestorage()(args).then(function(){
|
||||||
|
reject({err: 'No secret found!'});
|
||||||
|
}).catch(function(){
|
||||||
|
reject({err: 'No secret found!'});
|
||||||
|
});
|
||||||
|
}
|
||||||
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
// the proof of work is evidence that we've spent some time/effort trying to log in, this slows brute force.
|
||||||
return SEA.read(at.put.auth, pub).then(function(auth){
|
return SEA.read(at.put.auth, pub).then(function(auth){
|
||||||
return SEA.de(auth, proof)
|
return SEA.de(auth, proof)
|
||||||
@ -273,21 +314,24 @@
|
|||||||
}).then(function(priv){
|
}).then(function(priv){
|
||||||
// now we have AES decrypted the private key,
|
// now we have AES decrypted the private key,
|
||||||
// if we were successful, then that means we're logged in!
|
// if we were successful, then that means we're logged in!
|
||||||
return remaining ? undefined // Not done yet
|
return updatestorage(proof, priv, pin)(args).then(function(){
|
||||||
: priv ? resolve({pub: pub, priv: priv, at: at, proof: proof})
|
return remaining ? undefined // Not done yet
|
||||||
// Or else we failed to log in...
|
: priv ? resolve({pub: pub, priv: priv, at: at, proof: proof})
|
||||||
: reject({err: 'Failed to decrypt private key!'});
|
// Or else we failed to log in...
|
||||||
|
: reject({err: 'Failed to decrypt private key!'});
|
||||||
|
}).catch(function(e){reject({err: 'Failed to store credentials!'})});
|
||||||
}).catch(function(e){reject({err: 'Failed read secret!'})});
|
}).catch(function(e){reject({err: 'Failed read secret!'})});
|
||||||
}).catch(function(e){
|
}).catch(function(e){
|
||||||
reject({err: 'Failed to access stored credentials!'})})
|
reject({err: 'Failed to access stored credentials!'})})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).then(function(user){
|
}).then(function(user){
|
||||||
return finalizelogin(alias, user, root).then(resolve)
|
finalizelogin(alias, user, root).then(resolve).catch(function(e){
|
||||||
.catch(function(e){
|
|
||||||
Gun.log('Failed to finalize login with new password!');
|
Gun.log('Failed to finalize login with new password!');
|
||||||
reject({err: 'Finalizing new password login failed! Reason: '+(e && e.err) || e || ''});
|
reject({err: 'Finalizing new password login failed! Reason: '+(e && e.err) || e || ''});
|
||||||
});
|
});
|
||||||
|
}).catch(function(e){
|
||||||
|
reject({err: 'No authentication session found!'});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
reject({err: 'No authentication session found!'});
|
reject({err: 'No authentication session found!'});
|
||||||
@ -390,8 +434,7 @@
|
|||||||
root.get(tmp).put(null);
|
root.get(tmp).put(null);
|
||||||
root.get(tmp).put(user);
|
root.get(tmp).put(user);
|
||||||
// then we're done
|
// then we're done
|
||||||
finalizelogin(alias, key, root, pin).then(resolve)
|
finalizelogin(alias, key, root, pin).then(resolve).catch(function(e){
|
||||||
.catch(function(e){
|
|
||||||
Gun.log('Failed to finalize login with new password!');
|
Gun.log('Failed to finalize login with new password!');
|
||||||
reject({err: 'Finalizing new password login failed! Reason: '+(e && e.err) || e || ''});
|
reject({err: 'Finalizing new password login failed! Reason: '+(e && e.err) || e || ''});
|
||||||
});
|
});
|
||||||
@ -404,8 +447,7 @@
|
|||||||
reject({err: 'Password set attempt failed! Reason: '+(e && e.err) || e || ''});
|
reject({err: 'Password set attempt failed! Reason: '+(e && e.err) || e || ''});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
finalizelogin(alias, key, root, pin).then(resolve)
|
finalizelogin(alias, key, root, pin).then(resolve).catch(function(e){
|
||||||
.catch(function(e){
|
|
||||||
Gun.log('Failed to finalize login!');
|
Gun.log('Failed to finalize login!');
|
||||||
reject({err: 'Finalizing login failed! Reason: '+(e && e.err) || e || ''});
|
reject({err: 'Finalizing login failed! Reason: '+(e && e.err) || e || ''});
|
||||||
});
|
});
|
||||||
@ -445,6 +487,7 @@
|
|||||||
// If authentication is to be remembered over reloads or browser closing,
|
// If authentication is to be remembered over reloads or browser closing,
|
||||||
// set validity time in seconds.
|
// set validity time in seconds.
|
||||||
User.recall = function(validity,cb,opts){
|
User.recall = function(validity,cb,opts){
|
||||||
|
var root = this.back(-1);
|
||||||
if(!opts){
|
if(!opts){
|
||||||
if(typeof cb !== 'function' && !Gun.val.is(cb)){
|
if(typeof cb !== 'function' && !Gun.val.is(cb)){
|
||||||
opts = cb;
|
opts = cb;
|
||||||
@ -477,9 +520,14 @@
|
|||||||
if(Gun.obj.has(opts, 'hook')){
|
if(Gun.obj.has(opts, 'hook')){
|
||||||
authsettings.hook = opt.hook;
|
authsettings.hook = opt.hook;
|
||||||
}
|
}
|
||||||
// TODO: per authsettings, dig possibly existing auth data and
|
authrecall(root).then(function(props){
|
||||||
// call SEA.auth
|
// All is good. Should we do something more with actual recalled data?
|
||||||
resolve({ok: 0, pub: 'TBD'})
|
resolve(root._.user._)
|
||||||
|
}).catch(function(e){
|
||||||
|
var err = 'No session!';
|
||||||
|
Gun.log(err);
|
||||||
|
resolve({ err: err });
|
||||||
|
});
|
||||||
};
|
};
|
||||||
if(cb){doIt(cb, cb)} else {return new Promise(doIt)}
|
if(cb){doIt(cb, cb)} else {return new Promise(doIt)}
|
||||||
};
|
};
|
||||||
@ -676,10 +724,10 @@
|
|||||||
return new Buffer(result, 'binary').toString('base64');
|
return new Buffer(result, 'binary').toString('base64');
|
||||||
}).then(resolve).catch(function(e){Gun.log(e); reject(e)});
|
}).then(resolve).catch(function(e){Gun.log(e); reject(e)});
|
||||||
}) || function(resolve, reject){ // For NodeJS crypto.pkdf2 rocks
|
}) || function(resolve, reject){ // For NodeJS crypto.pkdf2 rocks
|
||||||
nodeCrypto.pbkdf2(pass,new Buffer(salt, 'utf8'),pbkdf2.iter,pbkdf2.ks,nHash,function(err,hash){
|
try{
|
||||||
if(err){return reject(e)}
|
var hash = nodeCrypto.pbkdf2Sync(pass,new Buffer(salt, 'utf8'),pbkdf2.iter,pbkdf2.ks,nHash);
|
||||||
resolve(hash && hash.toString('base64'));
|
resolve(hash && hash.toString('base64'));
|
||||||
});
|
}catch(e){reject(e)};
|
||||||
};
|
};
|
||||||
if(cb){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
if(cb){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
||||||
};
|
};
|
||||||
@ -793,16 +841,16 @@
|
|||||||
};
|
};
|
||||||
SEA.read = function(m,p,cb){
|
SEA.read = function(m,p,cb){
|
||||||
var doIt = function(resolve, reject) {
|
var doIt = function(resolve, reject) {
|
||||||
if(!m){ return resolve(); }
|
if(!m){return resolve()}
|
||||||
if(!m.slice || 'SEA[' !== m.slice(0,4)){return resolve(m)}
|
if(!m.slice || 'SEA[' !== m.slice(0,4)){return resolve(m)}
|
||||||
m = m.slice(3);
|
m = m.slice(3);
|
||||||
try{m = !m.slice ? m : JSON.parse(m);}catch(e){return reject(e);}
|
try{m = !m.slice ? m : JSON.parse(m);}catch(e){return reject(e)}
|
||||||
m = m || '';
|
m = m || '';
|
||||||
SEA.verify(m[0], p, m[1]).then(function(ok){
|
SEA.verify(m[0], p, m[1]).then(function(ok){
|
||||||
resolve(ok && m[0])
|
resolve(ok && m[0])
|
||||||
});
|
}).catch(function(e){reject(e)});
|
||||||
};
|
};
|
||||||
if(cb){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
if(cb && typeof cb === 'function'){doIt(cb, function(){cb()})} else {return new Promise(doIt)}
|
||||||
};
|
};
|
||||||
|
|
||||||
Gun.SEA = SEA;
|
Gun.SEA = SEA;
|
||||||
|
@ -8093,10 +8093,16 @@ describe('Gun', function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('auth', function(){
|
describe('auth', function(){
|
||||||
var checkStorage = function(done){
|
var checkStorage = function(done, hasPin){
|
||||||
return function(){
|
return function(){
|
||||||
console.log('auth remember:', root.sessionStorage.getItem('remember'))
|
expect(root.sessionStorage.getItem('user')).to.not.be(undefined);
|
||||||
console.log('auth protected:', root.localStorage.getItem('remember'))
|
expect(root.sessionStorage.getItem('user')).to.not.be('');
|
||||||
|
expect(root.sessionStorage.getItem('remember')).to.not.be(undefined);
|
||||||
|
expect(root.sessionStorage.getItem('remember')).to.not.be('');
|
||||||
|
if(hasPin){
|
||||||
|
expect(root.localStorage.getItem('remember')).to.not.be(undefined);
|
||||||
|
expect(root.localStorage.getItem('remember')).to.not.be('');
|
||||||
|
}
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -8204,10 +8210,10 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
|
|
||||||
it('with PIN auth session stored to sessionStorage', function(done){
|
it('with PIN auth session stored to sessionStorage', function(done){
|
||||||
if(type === 'callback'){
|
if(type === 'callback'){
|
||||||
user.auth(alias+type, pass+' new', checkStorage(done), {pin: 'PIN'});
|
user.auth(alias+type, pass+' new', checkStorage(done, true), {pin: 'PIN'});
|
||||||
} else {
|
} else {
|
||||||
user.auth(alias+type, pass+' new', {pin: 'PIN'})
|
user.auth(alias+type, pass+' new', {pin: 'PIN'})
|
||||||
.then(checkStorage(done)).catch(done);
|
.then(checkStorage(done, true)).catch(done);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -8350,9 +8356,25 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
expect(root.localStorage.getItem('remember')).to.not.be(undefined);
|
expect(root.localStorage.getItem('remember')).to.not.be(undefined);
|
||||||
expect(root.localStorage.getItem('remember')).to.not.be('');
|
expect(root.localStorage.getItem('remember')).to.not.be('');
|
||||||
}
|
}
|
||||||
done();
|
return done();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
// This re-constructs 'remember-me' data modified by manipulate func
|
||||||
|
var manipulateStorage = function(manipulate, hasPin){
|
||||||
|
var usr = gun.back(-1)._.user;
|
||||||
|
var remember = hasPin ? localStorage.getItem('remember')
|
||||||
|
: sessionStorage.getItem('remember');
|
||||||
|
return Gun.SEA.read(remember, usr._.pub).then(function(props){
|
||||||
|
props = manipulate(JSON.parse(props));
|
||||||
|
return Gun.SEA.write(JSON.stringify(props), usr._.sea)
|
||||||
|
.then(function(remember){
|
||||||
|
// remember = JSON.stringify(remember);
|
||||||
|
return hasPin ? sessionStorage.setItem('remember', remember)
|
||||||
|
: sessionStorage.setItem('remember', remember);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
it('with PIN auth session stored to localStorage', function(done){
|
it('with PIN auth session stored to localStorage', function(done){
|
||||||
var doAction = function(){
|
var doAction = function(){
|
||||||
user.auth(alias+type, pass+' new', { pin: 'PIN' })
|
user.auth(alias+type, pass+' new', { pin: 'PIN' })
|
||||||
@ -8369,11 +8391,13 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
var doAction = function(){
|
var doAction = function(){
|
||||||
user.auth(alias+type, pass+' new').then(doCheck(done));
|
user.auth(alias+type, pass+' new').then(doCheck(done));
|
||||||
};
|
};
|
||||||
if(type === 'callback'){
|
user.leave().then(function(){
|
||||||
user.recall(doAction, { session: false });
|
if(type === 'callback'){
|
||||||
} else {
|
user.recall(doAction, { session: false });
|
||||||
user.recall({ session: false }).then(doAction).catch(done)
|
} else {
|
||||||
}
|
user.recall({ session: false }).then(doAction).catch(done)
|
||||||
|
}
|
||||||
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('no validity no session storing', function(done){
|
it('no validity no session storing', function(done){
|
||||||
@ -8400,10 +8424,6 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('valid sessionStorage session', function(done){
|
it('valid sessionStorage session', function(done){
|
||||||
var check = function(ack){
|
|
||||||
// TODO: check
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
user.auth(alias+type, pass+' new').then(function(usr){
|
user.auth(alias+type, pass+' new').then(function(usr){
|
||||||
var sUser;
|
var sUser;
|
||||||
var sRemember;
|
var sRemember;
|
||||||
@ -8436,11 +8456,7 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('valid localStorage session', function(done){
|
it('valid localStorage session bootstrap', function(done){
|
||||||
var check = function(ack){
|
|
||||||
// TODO: check
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
user.auth(alias+type, pass+' new', { pin: 'PIN' }).then(function(usr){
|
user.auth(alias+type, pass+' new', { pin: 'PIN' }).then(function(usr){
|
||||||
var sUser;
|
var sUser;
|
||||||
var sRemember;
|
var sRemember;
|
||||||
@ -8460,6 +8476,7 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
sRemember = root.sessionStorage.getItem('remember');
|
sRemember = root.sessionStorage.getItem('remember');
|
||||||
lRemember = root.localStorage.getItem('remember');
|
lRemember = root.localStorage.getItem('remember');
|
||||||
}catch(e){done(e); return};
|
}catch(e){done(e); return};
|
||||||
|
|
||||||
user.leave().then(function(ack){
|
user.leave().then(function(ack){
|
||||||
try{
|
try{
|
||||||
expect(ack).to.have.key('ok');
|
expect(ack).to.have.key('ok');
|
||||||
@ -8480,7 +8497,32 @@ console.log('auth protected:', root.localStorage.getItem('remember'))
|
|||||||
});
|
});
|
||||||
|
|
||||||
it.skip('invalid sessionStorage session');
|
it.skip('invalid sessionStorage session');
|
||||||
it.skip('expired session');
|
it.skip('valid localStorage data but not in sessionStorage');
|
||||||
|
|
||||||
|
it('expired session', function(done){
|
||||||
|
user.recall(60, {session: true}).then(function(){
|
||||||
|
return user.auth(alias+type, pass+' new');
|
||||||
|
}).then(doCheck(function(){
|
||||||
|
// Storage data OK, let's back up time of auth 65 minutes
|
||||||
|
return manipulateStorage(function(props){
|
||||||
|
props.iat -= 65 * 60;
|
||||||
|
return props;
|
||||||
|
}, false);
|
||||||
|
})).then(function(){
|
||||||
|
// Simulate browser reload
|
||||||
|
gun.back(-1)._.user = gun.back(-1).chain();
|
||||||
|
// TODO: re-make sessionStorage.remember to 65 seconds past
|
||||||
|
user.recall(60, {session: true}).then(function(props){
|
||||||
|
expect(props).to.not.be(undefined);
|
||||||
|
expect(props).to.not.be('');
|
||||||
|
expect(props).to.have.key('err');
|
||||||
|
expect(props.err).to.not.be(undefined);
|
||||||
|
expect(props.err).to.not.be('');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
it.skip('changed password');
|
it.skip('changed password');
|
||||||
it.skip('no session');
|
it.skip('no session');
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user