2016-09-03 06:03:13 +02:00
|
|
|
|
function TokenService() {
|
2016-09-04 06:34:24 +02:00
|
|
|
|
initTokenService();
|
2017-07-14 21:34:05 +02:00
|
|
|
|
}
|
2016-09-03 06:03:13 +02:00
|
|
|
|
|
2016-09-04 06:34:24 +02:00
|
|
|
|
function initTokenService() {
|
2017-01-18 05:07:46 +01:00
|
|
|
|
var _token,
|
2017-01-22 04:00:02 +01:00
|
|
|
|
_authBearer,
|
2017-01-18 05:07:46 +01:00
|
|
|
|
_decodedToken,
|
|
|
|
|
_refreshToken;
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.setTokens = function (accessToken, refreshToken, callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
|
self.setToken(accessToken, function () {
|
|
|
|
|
self.setRefreshToken(refreshToken, function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
2016-09-03 06:03:13 +02:00
|
|
|
|
|
|
|
|
|
TokenService.prototype.setToken = function (token, callback) {
|
2016-09-02 07:20:41 +02:00
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-02 06:50:57 +02:00
|
|
|
|
_token = token;
|
2017-01-18 05:07:46 +01:00
|
|
|
|
_decodedToken = null;
|
2016-09-02 06:50:57 +02:00
|
|
|
|
chrome.storage.local.set({
|
2017-01-18 05:07:46 +01:00
|
|
|
|
'accessToken': token
|
2016-09-02 06:50:57 +02:00
|
|
|
|
}, function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-03 06:03:13 +02:00
|
|
|
|
TokenService.prototype.getToken = function (callback) {
|
2016-09-02 07:20:41 +02:00
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-02 06:50:57 +02:00
|
|
|
|
if (_token) {
|
|
|
|
|
return callback(_token);
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
chrome.storage.local.get('accessToken', function (obj) {
|
|
|
|
|
if (obj && obj.accessToken) {
|
|
|
|
|
_token = obj.accessToken;
|
2016-09-02 06:50:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callback(_token);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-22 04:00:02 +01:00
|
|
|
|
TokenService.prototype.getAuthBearer = function (callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_authBearer) {
|
|
|
|
|
return callback(_authBearer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chrome.storage.local.get('authBearer', function (obj) {
|
|
|
|
|
if (obj && obj.authBearer) {
|
|
|
|
|
_authBearer = obj.authBearer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callback(_authBearer);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.setRefreshToken = function (refreshToken, callback) {
|
2016-09-02 07:20:41 +02:00
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
_refreshToken = refreshToken;
|
|
|
|
|
chrome.storage.local.set({
|
|
|
|
|
'refreshToken': refreshToken
|
|
|
|
|
}, function () {
|
2016-09-02 06:50:57 +02:00
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
2016-09-03 06:11:57 +02:00
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.getRefreshToken = function (callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_refreshToken) {
|
|
|
|
|
return callback(_refreshToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chrome.storage.local.get('refreshToken', function (obj) {
|
|
|
|
|
if (obj && obj.refreshToken) {
|
|
|
|
|
_refreshToken = obj.refreshToken;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callback(_refreshToken);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2017-06-27 04:24:10 +02:00
|
|
|
|
TokenService.prototype.setTwoFactorToken = function (token, email, callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var obj = {};
|
|
|
|
|
obj['twoFactorToken_' + email] = token;
|
|
|
|
|
|
|
|
|
|
chrome.storage.local.set(obj, function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.getTwoFactorToken = function (email, callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var prop = 'twoFactorToken_' + email;
|
|
|
|
|
|
|
|
|
|
chrome.storage.local.get(prop, function (obj) {
|
|
|
|
|
if (obj && obj[prop]) {
|
|
|
|
|
callback(obj[prop]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callback(null);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.clearTwoFactorToken = function (email, callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chrome.storage.local.remove('twoFactorToken_' + email, function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-22 04:00:02 +01:00
|
|
|
|
TokenService.prototype.clearAuthBearer = function (callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_authBearer = null;
|
|
|
|
|
chrome.storage.local.remove('authBearer', function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.clearToken = function (callback) {
|
|
|
|
|
if (!callback || typeof callback !== 'function') {
|
|
|
|
|
throw 'callback function required';
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-22 04:00:02 +01:00
|
|
|
|
_token = _decodedToken = _refreshToken = _authBearer = null;
|
|
|
|
|
chrome.storage.local.remove('authBearer', function () {
|
|
|
|
|
chrome.storage.local.remove('accessToken', function () {
|
|
|
|
|
chrome.storage.local.remove('refreshToken', function () {
|
|
|
|
|
callback();
|
|
|
|
|
});
|
2017-01-18 05:07:46 +01:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-03 06:11:57 +02:00
|
|
|
|
// jwthelper methods
|
|
|
|
|
// ref https://github.com/auth0/angular-jwt/blob/master/src/angularJwt/services/jwt.js
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.decodeToken = function () {
|
|
|
|
|
if (_decodedToken) {
|
|
|
|
|
return _decodedToken;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_token) {
|
|
|
|
|
throw 'Token not found.';
|
|
|
|
|
}
|
2016-09-03 06:11:57 +02:00
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
var parts = _token.split('.');
|
2016-09-03 06:11:57 +02:00
|
|
|
|
if (parts.length !== 3) {
|
2017-01-18 05:07:46 +01:00
|
|
|
|
throw 'JWT must have 3 parts';
|
2016-09-03 06:11:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var decoded = urlBase64Decode(parts[1]);
|
|
|
|
|
if (!decoded) {
|
2017-01-18 05:07:46 +01:00
|
|
|
|
throw 'Cannot decode the token';
|
2016-09-03 06:11:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-05 03:58:16 +01:00
|
|
|
|
_decodedToken = JSON.parse(decoded);
|
|
|
|
|
return _decodedToken;
|
2016-09-03 06:11:57 +02:00
|
|
|
|
};
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.getTokenExpirationDate = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
2016-09-03 06:11:57 +02:00
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
if (typeof decoded.exp === 'undefined') {
|
2016-09-03 06:11:57 +02:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var d = new Date(0); // The 0 here is the key, which sets the date to the epoch
|
|
|
|
|
d.setUTCSeconds(decoded.exp);
|
|
|
|
|
|
|
|
|
|
return d;
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-19 06:21:20 +01:00
|
|
|
|
TokenService.prototype.tokenSecondsRemaining = function (offsetSeconds) {
|
|
|
|
|
var d = this.getTokenExpirationDate();
|
|
|
|
|
offsetSeconds = offsetSeconds || 0;
|
|
|
|
|
if (d === null) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var msRemaining = d.valueOf() - (new Date().valueOf() + (offsetSeconds * 1000));
|
|
|
|
|
return Math.round(msRemaining / 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.tokenNeedsRefresh = function (minutes) {
|
|
|
|
|
minutes = minutes || 5; // default 5 minutes
|
|
|
|
|
var sRemaining = this.tokenSecondsRemaining();
|
|
|
|
|
return sRemaining < (60 * minutes);
|
|
|
|
|
};
|
|
|
|
|
|
2017-01-18 05:07:46 +01:00
|
|
|
|
TokenService.prototype.getUserId = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
|
|
|
|
|
|
|
|
|
if (typeof decoded.sub === 'undefined') {
|
|
|
|
|
throw 'No user id found';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return decoded.sub;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.getEmail = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
|
|
|
|
|
2017-01-25 04:57:21 +01:00
|
|
|
|
if (typeof decoded.email === 'undefined') {
|
2017-01-18 05:07:46 +01:00
|
|
|
|
throw 'No email found';
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-25 04:57:21 +01:00
|
|
|
|
return decoded.email;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TokenService.prototype.getName = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
|
|
|
|
|
|
|
|
|
if (typeof decoded.name === 'undefined') {
|
|
|
|
|
throw 'No name found';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return decoded.name;
|
2017-01-18 05:07:46 +01:00
|
|
|
|
};
|
|
|
|
|
|
2017-07-11 20:54:36 +02:00
|
|
|
|
TokenService.prototype.getPremium = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
|
|
|
|
|
|
|
|
|
if (typeof decoded.premium === 'undefined') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !!decoded.premium;
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-06 05:19:38 +02:00
|
|
|
|
TokenService.prototype.getIssuer = function () {
|
|
|
|
|
var decoded = this.decodeToken();
|
|
|
|
|
|
|
|
|
|
if (typeof decoded.iss === 'undefined') {
|
|
|
|
|
throw 'No issuer found';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return decoded.iss;
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-03 06:11:57 +02:00
|
|
|
|
function urlBase64Decode(str) {
|
|
|
|
|
var output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
|
|
|
switch (output.length % 4) {
|
|
|
|
|
case 0: { break; }
|
|
|
|
|
case 2: { output += '=='; break; }
|
|
|
|
|
case 3: { output += '='; break; }
|
|
|
|
|
default: {
|
|
|
|
|
throw 'Illegal base64url string!';
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-22 19:15:42 +02:00
|
|
|
|
|
|
|
|
|
//polyfill https://github.com/davidchambers/Base64.js
|
|
|
|
|
return window.decodeURIComponent(escape(window.atob(output)));
|
2017-07-14 21:34:05 +02:00
|
|
|
|
}
|
|
|
|
|
}
|