vue-jwt-auth
Advanced tools
Comparing version 0.7.0 to 0.8.0
@@ -19,3 +19,3 @@ { | ||
}, | ||
"version": "0.7.0" | ||
"version": "0.8.0" | ||
} |
@@ -25,3 +25,10 @@ # vue-jwt-auth | ||
**NOTE:** If you do not set your router as `Vue.router = new VueRouter()` then you will need to feed the `router` in directly as an optional third argument. | ||
~~~ | ||
var router = new VueRouter(); | ||
Vue.use(Auth, options, router); | ||
~~~ | ||
## Loading | ||
@@ -28,0 +35,0 @@ |
module.exports = (function () { | ||
var _tokenRefreshTimeout = null | ||
var _tokenRefreshTimeout = null; | ||
// Default | ||
function _beforeEach(transition) { | ||
var roles, | ||
auth = _toArray(transition.to.auth); | ||
function _beforeEach (transition) { | ||
var auth = _toArray(transition.to.auth) | ||
if (auth && (auth === true || auth.constructor === Array)) { | ||
if ( ! this.check()) { | ||
this.$router.replace(this.getOption('authRedirect')); | ||
if (!this.check()) { | ||
this.$router.replace(this.getOption('authRedirect')) | ||
} else if (auth.constructor === Array && !_compare(auth, _toArray(this.user()[this.getOption('rolesVar')]))) { | ||
this.$router.replace(this.getOption('forbiddenRedirect')) | ||
} else { | ||
return transition.next() | ||
} | ||
else if (auth.constructor === Array && ! _compare(auth, _toArray(this.user()[this.getOption('rolesVar')]))) { | ||
this.$router.replace(this.getOption('forbiddenRedirect')); | ||
} | ||
else { | ||
return transition.next(); | ||
} | ||
} else if (auth === false && this.check()) { | ||
this.$router.replace(this.getOption('notFoundRedirect')) | ||
} else { | ||
return transition.next() | ||
} | ||
else if (auth === false && this.check()) { | ||
this.$router.replace(this.getOption('notFoundRedirect')); | ||
} | ||
else { | ||
return transition.next(); | ||
} | ||
} | ||
function _userData(resp) { | ||
return resp.data; | ||
function _userData (res) { | ||
return res.data || res | ||
} | ||
function _cookieDomain() { | ||
return window.location.hostname; | ||
function _cookieDomain () { | ||
return window.location.hostname | ||
} | ||
function _invalidToken (res) { | ||
if (res.status === 401) { | ||
this.logout(this.getOption('logoutRedirect')) | ||
} | ||
} | ||
// Utils | ||
function _getUrl() { | ||
var port = window.location.port; | ||
function _getUrl () { | ||
var port = window.location.port | ||
return window.location.protocol + '//' + window.location.hostname + (port ? ':' + port : ''); | ||
return window.location.protocol + '//' + window.location.hostname + (port ? ':' + port : '') | ||
} | ||
function _compare(one, two) { | ||
var i, ii; | ||
function _compare (one, two) { | ||
var i, ii | ||
one = _toArray(one); | ||
two = _toArray(two); | ||
one = _toArray(one) | ||
two = _toArray(two) | ||
if (one.constructor !== Array || two.constructor !== Array) { | ||
return false; | ||
return false | ||
} | ||
@@ -58,23 +59,23 @@ | ||
if (two.indexOf(one[i]) >= 0) { | ||
return true; | ||
return true | ||
} | ||
} | ||
return false; | ||
return false | ||
} | ||
function _toArray(val) { | ||
return (typeof val) === 'string' ? [val] : val; | ||
function _toArray (val) { | ||
return (typeof val) === 'string' ? [val] : val | ||
} | ||
// Remember Me | ||
function _setCookie(name, value, timeOffset) { | ||
var domain = this.getOption('cookieDomain').call(this), | ||
expires = (new Date((new Date).getTime() + timeOffset)).toUTCString(); | ||
document.cookie = (name + '=' + value + '; domain=' + domain + '; path=/;' + (timeOffset ? ' expires=' + expires + ';' : '') ); | ||
function _setCookie (name, value, timeOffset) { | ||
var domain = this.getOption('cookieDomain').call(this), | ||
expires = (new Date((new Date()).getTime() + timeOffset)).toUTCString() | ||
document.cookie = (name + '=' + value + '; domain=' + domain + '; path=/;' + (timeOffset ? ' expires=' + expires + ';' : '')) | ||
} | ||
function _setRememberMeCookie(rememberMe) { | ||
function _setRememberMeCookie (rememberMe) { | ||
_setCookie.call(this, | ||
@@ -84,7 +85,7 @@ 'rememberMe', | ||
rememberMe === true ? 12096e5 : undefined | ||
); | ||
) | ||
} | ||
function _removeRememberMeCookie() { | ||
_setCookie.call(this, 'rememberMe', 'false', -12096e5); | ||
function _removeRememberMeCookie () { | ||
_setCookie.call(this, 'rememberMe', 'false', -12096e5) | ||
} | ||
@@ -94,98 +95,147 @@ | ||
function _setToken(token) { | ||
function _setToken (token) { | ||
if (token) { | ||
localStorage.setItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'), token); | ||
localStorage.setItem((this.other() ? 'login-as-' : '') + this.getOption('tokenName'), token) | ||
} | ||
} | ||
function _getToken() { | ||
return localStorage.getItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName')); | ||
function _getToken () { | ||
return localStorage.getItem((this.other() ? 'login-as-' : '') + this.getOption('tokenName')) | ||
} | ||
function _removeToken() { | ||
localStorage.removeItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName')); | ||
function _removeToken () { | ||
localStorage.removeItem((this.other() ? 'login-as-' : '') + this.getOption('tokenName')) | ||
} | ||
function _refreshToken() { | ||
var _this = this; | ||
function _refreshToken () { | ||
var _this = this | ||
if (_getToken.call(this)) { | ||
this.$http.get(this.getOption('tokenUrl')); | ||
this.$http.get(this.getOption('tokenUrl'), function (res) { | ||
var tokenJSON = _decodeToken(_getToken.call(_this)), | ||
expireTime = _getTokenExpirationDate(tokenJSON).valueOf(), | ||
nowTime = new Date().valueOf(), | ||
offsetTime = this.getOption('tokenTimeoutOffset'), | ||
timeout = expireTime - nowTime - offsetTime; | ||
clearTimeout(_tokenRefreshTimeout); | ||
clearTimeout(_tokenRefreshTimeout) | ||
_tokenRefreshTimeout = setTimeout(function () { | ||
_refreshToken.call(_this); | ||
}, this.getOption('tokenTimeout')); | ||
_tokenRefreshTimeout = setTimeout(function () { | ||
_refreshToken.call(_this) | ||
}, timeout) | ||
}); | ||
} | ||
} | ||
// Router | ||
// Token util | ||
function _urlBase64Decode (str) { | ||
let output = str.replace(/-/g, '+').replace(/_/g, '/') | ||
switch (output.length % 4) { | ||
case 0: { break } | ||
case 2: { output += '=='; break } | ||
case 3: { output += '='; break } | ||
default: { | ||
console.log('Illegal base64url string!') | ||
} | ||
} | ||
function _setRoute(route, router) { | ||
this.$route = route; | ||
this.$router = router; | ||
return decodeURIComponent(escape(window.atob(output))) // polifyll https://github.com/davidchambers/Base64.js | ||
} | ||
function _decodeToken (token) { | ||
if ( ! token) { return; } | ||
let parts = token.split('.') | ||
if (parts.length !== 3) { | ||
throw new Error('JWT must have 3 parts') | ||
} | ||
let decoded = _urlBase64Decode(parts[1]) | ||
if ( ! decoded) { | ||
throw new Error('Cannot decode the token') | ||
} | ||
return JSON.parse(decoded) | ||
} | ||
function _getTokenExpirationDate (tokenJSON) { | ||
if ( ! tokenJSON || ! tokenJSON.exp) { return } | ||
let d = new Date(0) // The 0 here is the key, which sets the date to the epoch | ||
d.setUTCSeconds(tokenJSON.exp) | ||
return d | ||
} | ||
// Router | ||
function _setRoute (route, router) { | ||
this.$route = route | ||
this.$router = router | ||
} | ||
// Auth | ||
function _login(path, data, rememberMe, redirectUrl, options) { | ||
options = options || {}; | ||
function _login (path, data, rememberMe, redirectUrl, options) { | ||
options = options || {} | ||
this.$http.post(path, data, function(resp) { | ||
var _this = this; | ||
this.$http.post(path, data, function (res) { | ||
var _this = this | ||
_setRememberMeCookie.call(this, rememberMe); | ||
_setRememberMeCookie.call(this, rememberMe) | ||
_setToken.call(this, resp[this.getOption('tokenVar')]); | ||
_setToken.call(this, res[this.getOption('tokenVar')]) | ||
this.authenticated = null; | ||
this.authenticated = null | ||
this.fetch(function () { | ||
if (options.success) { | ||
options.success.call(_this, resp); | ||
options.success.call(_this, res) | ||
} | ||
if (redirectUrl && _this.check()) { | ||
_this.$router.go(redirectUrl); | ||
_this.$router.go(redirectUrl) | ||
} | ||
}); | ||
}) | ||
}, { | ||
error: function (resp) { | ||
error (res) { | ||
if (options.error) { | ||
options.error.call(this, resp); | ||
options.error.call(this, res) | ||
} | ||
} | ||
}); | ||
}) | ||
} | ||
function _social(type, data, rememberMe, redirectUrl, options) { | ||
function _social (type, data, rememberMe, redirectUrl, options) { | ||
var state, | ||
params = ''; | ||
params = '' | ||
data = data || {}; | ||
data = data || {} | ||
if (data.code) { | ||
state = JSON.parse(this.$route.query.state); | ||
state = JSON.parse(this.$route.query.state) | ||
_login.call(this, this.getOption(type + 'Url'), data, state.rememberMe, state.redirect, options); | ||
} | ||
else { | ||
data.state = data.state || {}; | ||
data.state.rememberMe = rememberMe === true ? true : false; | ||
data.state.redirect = redirectUrl || ''; | ||
_login.call(this, this.getOption(type + 'Url'), data, state.rememberMe, state.redirect, options) | ||
} else { | ||
data.state = data.state || {} | ||
data.state.rememberMe = rememberMe === true | ||
data.state.redirect = redirectUrl || '' | ||
data.appId = data.appId || this.getOption(type + 'AppId'); | ||
data.clientId = data.clientId || this.getOption(type + 'ClientId'); | ||
data.scope = data.scope || this.getOption(type + 'Scope'); | ||
data.redirect = data.redirect || this.getOption(type + 'Redirect'); | ||
data.appId = data.appId || this.getOption(type + 'AppId') | ||
data.clientId = data.clientId || this.getOption(type + 'ClientId') | ||
data.scope = data.scope || this.getOption(type + 'Scope') | ||
data.redirect = data.redirect || this.getOption(type + 'Redirect') | ||
params = '?client_id=' + data.appId + '&redirect_uri=' + data.redirect + '&scope=' + data.scope + '&response_type=code&state=' + JSON.stringify(data.state); | ||
params = '?client_id=' + data.appId + '&redirect_uri=' + data.redirect + '&scope=' + data.scope + '&response_type=code&state=' + JSON.stringify(data.state) | ||
if (type === 'facebook') { | ||
window.location = 'https://www.facebook.com/v2.5/dialog/oauth' + params; | ||
window.location = 'https://www.facebook.com/v2.5/dialog/oauth' + params | ||
} else if (type === 'google') { | ||
window.location = 'https://accounts.google.com/o/oauth2/auth' + params | ||
} | ||
else if (type === 'google') { | ||
window.location = 'https://accounts.google.com/o/oauth2/auth' + params; | ||
} | ||
// else if (type === 'twitter') { | ||
@@ -197,18 +247,18 @@ // window.location = 'https://oauth.twitter.com/2/authorize?oauth_callback_url=' + data.redirect + '&oauth_mode=flow_web_client&oauth_client_identifier=' + data.appId + '&redirect_uri=' + data.redirect + '&response_type=token&client_id=' + data.clientId; | ||
function _fetch(cb) { | ||
cb = cb || function () {}; | ||
function _fetch (cb) { | ||
cb = cb || function () {} | ||
this.$http.get(this.getOption('fetchUrl'), function(resp) { | ||
this.authenticated = true; | ||
this.data = this.getOption('userData').call(this, resp); | ||
this.loaded = true; | ||
this.$http.get(this.getOption('fetchUrl'), function (res) { | ||
this.authenticated = true | ||
this.data = this.getOption('userData').call(this, res) | ||
this.loaded = true | ||
return cb(); | ||
return cb() | ||
}, { | ||
error: function() { | ||
this.loaded = true; | ||
error () { | ||
this.loaded = true | ||
return cb(); | ||
return cb() | ||
} | ||
}); | ||
}) | ||
} | ||
@@ -220,34 +270,35 @@ | ||
options: { | ||
authType : 'bearer', | ||
authType: 'bearer', | ||
fetchUrl : '/auth/user', | ||
tokenUrl : '/auth/token', | ||
loginUrl : '/auth/login', | ||
loginAsUrl : '/auth/login-as', | ||
fetchUrl: 'auth/user', | ||
tokenUrl: 'auth/token', | ||
loginUrl: 'auth/login', | ||
loginAsUrl: 'auth/login-as', | ||
logoutRedirect : '/', | ||
notFoundRedirect : '/404', | ||
forbiddenRedirect : '/403', | ||
logoutRedirect: '/', | ||
notFoundRedirect: '/404', | ||
forbiddenRedirect: '/403', | ||
rolesVar : 'roles', | ||
tokenVar : 'token', | ||
tokenName : 'jwt-auth-token', | ||
tokenTimeout : 3000 * 1000, // 50 minutes (in milliseconds). | ||
rolesVar: 'roles', | ||
tokenVar: 'token', | ||
tokenName: 'jwt-auth-token', | ||
tokenTimeoutOffset: 5 * 1000, // 5 minutes. | ||
cookieDomain : _cookieDomain, | ||
userData : _userData, | ||
beforeEach : _beforeEach, | ||
facebookUrl : '/auth/facebook', | ||
facebookAppId : '', | ||
facebookScope : 'email', | ||
facebookRedirect : _getUrl() + '/login/facebook', | ||
googleUrl : '/auth/google', | ||
googleAppId : '', | ||
googleScope : 'https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read', | ||
googleRedirect : _getUrl() + '/login/google', | ||
cookieDomain: _cookieDomain, | ||
userData: _userData, | ||
beforeEach: _beforeEach, | ||
invalidToken: _invalidToken, | ||
facebookUrl: 'auth/facebook', | ||
facebookAppId: '', | ||
facebookScope: 'email', | ||
facebookRedirect: _getUrl() + '/login/facebook', | ||
googleUrl: 'auth/google', | ||
googleAppId: '', | ||
googleScope: 'https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read', | ||
googleRedirect: _getUrl() + '/login/google' | ||
}, | ||
data: function () { | ||
data () { | ||
return { | ||
@@ -257,3 +308,3 @@ data: null, | ||
authenticated: null | ||
}; | ||
} | ||
}, | ||
@@ -265,9 +316,9 @@ | ||
getOption: function (key) { | ||
return this.$options.options[key]; | ||
getOption (key) { | ||
return this.$options.options[key] | ||
}, | ||
setOptions: function (options) { | ||
setOptions (options) { | ||
for (var i in options) { | ||
this.$options.options[i] = options[i]; | ||
this.$options.options[i] = options[i] | ||
} | ||
@@ -278,26 +329,26 @@ }, | ||
login: function (data, rememberMe, redirectUrl, options) { | ||
_login.call(this, this.getOption('loginUrl'), data, rememberMe, redirectUrl, options); | ||
login (data, rememberMe, redirectUrl, options) { | ||
_login.call(this, this.getOption('loginUrl'), data, rememberMe, redirectUrl, options) | ||
}, | ||
facebook: function (data, rememberMe, redirectUrl, options) { | ||
_social.call(this, 'facebook', data, rememberMe, redirectUrl, options); | ||
facebook (data, rememberMe, redirectUrl, options) { | ||
_social.call(this, 'facebook', data, rememberMe, redirectUrl, options) | ||
}, | ||
google: function (data, rememberMe, redirectUrl, options) { | ||
_social.call(this, 'google', data, rememberMe, redirectUrl, options); | ||
google (data, rememberMe, redirectUrl, options) { | ||
_social.call(this, 'google', data, rememberMe, redirectUrl, options) | ||
}, | ||
logout: function(redirectUrl, force) { | ||
_removeRememberMeCookie.call(this); | ||
logout (redirectUrl, force) { | ||
_removeRememberMeCookie.call(this) | ||
// Need to call twice to remove both tokens. | ||
_removeToken.call(this); | ||
_removeToken.call(this); | ||
_removeToken.call(this) | ||
_removeToken.call(this) | ||
this.authenticated = false; | ||
this.data = null; | ||
this.authenticated = false | ||
this.data = null | ||
if (redirectUrl && (this.$route.auth || force)) { | ||
this.$router.go(redirectUrl); | ||
this.$router.go(redirectUrl) | ||
} | ||
@@ -308,3 +359,5 @@ }, | ||
check: function (role) { | ||
check (role) { | ||
var token = _getToken.call(this) | ||
if (this.data !== null) { | ||
@@ -321,96 +374,95 @@ if (role) { | ||
fetch: function(cb) { | ||
cb = cb || function () {}; | ||
fetch (cb) { | ||
cb = cb || function () {} | ||
if ( ! this.loaded) { | ||
_refreshToken.call(this); | ||
if (!this.loaded) { | ||
_refreshToken.call(this) | ||
} | ||
if (this.authenticated === null && _getToken.call(this)) { | ||
if ( ! document.cookie.match(/rememberMe/)) { | ||
_removeToken.call(this); | ||
this.loaded = true; | ||
return cb(); | ||
if (!document.cookie.match(/rememberMe/)) { | ||
_removeToken.call(this) | ||
this.loaded = true | ||
return cb() | ||
} | ||
this.authenticated = false; | ||
_fetch.call(this, cb); | ||
this.authenticated = false | ||
_fetch.call(this, cb) | ||
} else { | ||
this.loaded = true | ||
return cb() | ||
} | ||
else { | ||
this.loaded = true; | ||
return cb(); | ||
} | ||
}, | ||
user: function() { | ||
return this.data; | ||
user () { | ||
return this.data | ||
}, | ||
ready: function() { | ||
return this.loaded; | ||
ready () { | ||
return this.loaded | ||
}, | ||
// Login As | ||
loginAs (data, redirectUrl, options) { | ||
options = options || {} | ||
loginAs: function(data, redirectUrl, options) { | ||
options = options || {}; | ||
this.$http.post(this.getOption('loginAsUrl'), data, function (res) { | ||
var _this = this | ||
this.$http.post(this.getOption('loginAsUrl'), data, function(resp) { | ||
var _this = this; | ||
localStorage.setItem('login-as-' + this.getOption('tokenName'), res[this.getOption('tokenVar')]) | ||
localStorage.setItem('login-as-' + this.getOption('tokenName'), resp[this.getOption('tokenVar')]); | ||
_fetch.call(this, function () { | ||
if (options.success) { | ||
options.success.call(this, resp); | ||
options.success.call(this, res) | ||
} | ||
if (redirectUrl && _this.check()) { | ||
_this.$router.go(redirectUrl); | ||
_this.$router.go(redirectUrl) | ||
} | ||
}); | ||
}) | ||
}, { | ||
error: function (resp) { | ||
error (res) { | ||
if (options.error) { | ||
options.error.call(this, resp); | ||
options.error.call(this, res) | ||
} | ||
} | ||
}); | ||
}) | ||
}, | ||
logoutAs: function(redirectUrl) { | ||
var _this = this; | ||
logoutAs (redirectUrl) { | ||
var _this = this | ||
localStorage.removeItem('login-as-' + this.getOption('tokenName')); | ||
localStorage.removeItem('login-as-' + this.getOption('tokenName')) | ||
_fetch.call(this, function () { | ||
if (redirectUrl) { | ||
_this.$router.go(redirectUrl); | ||
_this.$router.go(redirectUrl) | ||
} | ||
}); | ||
}) | ||
}, | ||
other: function() { | ||
this.data; // TODO: Strange thing, need this to make the check fire consistently ?? | ||
other () { | ||
this.data // TODO: Strange thing, need this to make the check fire consistently ?? | ||
return localStorage.getItem('login-as-' + this.getOption('tokenName')); | ||
return localStorage.getItem('login-as-' + this.getOption('tokenName')) | ||
} | ||
} | ||
}; | ||
} | ||
return function install(Vue, options, router) { | ||
var auth = new Vue(Auth); | ||
return function install (Vue, options, router) { | ||
var auth = new Vue(Auth) | ||
auth.setOptions(options || {}); | ||
auth.setOptions(options || {}) | ||
Object.defineProperties(Vue.prototype, { | ||
$auth: { | ||
get: function () { | ||
_setRoute.call(auth, this.$route, this.$router); | ||
get () { | ||
_setRoute.call(auth, this.$route, this.$router) | ||
return auth; | ||
return auth | ||
} | ||
@@ -422,41 +474,41 @@ } | ||
(Vue.router || router).beforeEach(function (transition) { | ||
// Make sure to use $auth.fetch so context is loaded. | ||
transition.to.router.app.$auth.fetch(function () { | ||
auth.getOption('beforeEach').bind(auth)(transition); | ||
}); | ||
}); | ||
auth.getOption('beforeEach').bind(auth)(transition) | ||
}) | ||
}) | ||
// Set interceptors. | ||
Vue.http.interceptors.push({ | ||
// Send auth token on each request. | ||
request: function (req) { | ||
var token = _getToken.call(auth); | ||
request (req) { | ||
var token = _getToken.call(auth) | ||
if (token) { | ||
if (auth.getOption('authType') === 'bearer') { | ||
req.headers.Authorization = 'Bearer: ' + token; | ||
} | ||
if (token && auth.getOption('authType') === 'bearer') { | ||
req.headers.Authorization = 'Bearer: ' + token | ||
} | ||
return req; | ||
return req | ||
}, | ||
// Reset auth token if provided in response. | ||
response: function (res) { | ||
var authorization = res.headers('authorization'); | ||
response (res) { | ||
var authorization = res.headers('Authorization') | ||
if (authorization) { | ||
authorization = authorization.split(' '); | ||
authorization = authorization.split(' ') | ||
if (authorization[1]) { | ||
_setToken.call(auth, authorization[1]); | ||
_setToken.call(auth, authorization[1]) | ||
} | ||
} | ||
return res; | ||
auth.getOption('invalidToken').bind(auth)(res) | ||
return res | ||
} | ||
}); | ||
}) | ||
} | ||
})(); | ||
})() |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29523
8
399
352
1