mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 02:33:46 +00:00
totp code management and countdown timer
This commit is contained in:
@@ -8,8 +8,8 @@ function ApiService(tokenService, appIdService, utilsService, logoutCallback) {
|
||||
//this.identityBaseUrl = 'https://localhost:44392';
|
||||
|
||||
// Desktop external
|
||||
//this.baseUrl = 'http://192.168.1.6:4000';
|
||||
//this.identityBaseUrl = 'http://192.168.1.6:33656';
|
||||
//this.baseUrl = 'http://192.168.1.4:4000';
|
||||
//this.identityBaseUrl = 'http://192.168.1.4:33656';
|
||||
|
||||
// Preview
|
||||
//this.baseUrl = 'https://preview-api.bitwarden.com';
|
||||
@@ -441,7 +441,7 @@ function initApiService() {
|
||||
deviceName: self.utilsService.getBrowser()
|
||||
}, function (token) {
|
||||
self.tokenService.clearAuthBearer(function () {
|
||||
tokenService.setTokens(token.accessToken, token.refreshToken, function () {
|
||||
self.tokenService.setTokens(token.accessToken, token.refreshToken, function () {
|
||||
resolveTokenQs(token.accessToken, self, deferred);
|
||||
});
|
||||
});
|
||||
@@ -462,7 +462,7 @@ function initApiService() {
|
||||
client_id: 'browser',
|
||||
refresh_token: refreshToken
|
||||
}, function (token) {
|
||||
tokenService.setTokens(token.accessToken, token.refreshToken, function () {
|
||||
self.tokenService.setTokens(token.accessToken, token.refreshToken, function () {
|
||||
resolveTokenQs(token.accessToken, self, deferred);
|
||||
});
|
||||
}, function (jqXHR) {
|
||||
|
||||
@@ -41,6 +41,9 @@ function initLoginService() {
|
||||
return self.cryptoService.encrypt(login.notes, orgKey);
|
||||
}).then(function (cs) {
|
||||
model.notes = cs;
|
||||
return self.cryptoService.encrypt(login.totp, orgKey);
|
||||
}).then(function (cs) {
|
||||
model.totp = cs;
|
||||
return model;
|
||||
});
|
||||
};
|
||||
@@ -193,7 +196,7 @@ function initLoginService() {
|
||||
|
||||
function apiSuccess(response) {
|
||||
login.id = response.id;
|
||||
userService.getUserId(function (userId) {
|
||||
self.userService.getUserId(function (userId) {
|
||||
var data = new LoginData(response, userId);
|
||||
self.upsert(data, function () {
|
||||
deferred.resolve(login);
|
||||
|
||||
93
src/services/totpService.js
Normal file
93
src/services/totpService.js
Normal file
@@ -0,0 +1,93 @@
|
||||
function TotpService() {
|
||||
initTotpService();
|
||||
};
|
||||
|
||||
function initTotpService() {
|
||||
var b32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||
|
||||
var leftpad = function (s, l, p) {
|
||||
if (l + 1 >= s.length) {
|
||||
s = Array(l + 1 - s.length).join(p) + s;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
var dec2hex = function (d) {
|
||||
return (d < 15.5 ? '0' : '') + Math.round(d).toString(16);
|
||||
};
|
||||
|
||||
var hex2dec = function (s) {
|
||||
return parseInt(s, 16);
|
||||
};
|
||||
|
||||
var hex2bytes = function (s) {
|
||||
var bytes = new Uint8Array(s.length / 2);
|
||||
for (var i = 0; i < s.length; i += 2) {
|
||||
bytes[i / 2] = parseInt(s.substr(i, 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
var buff2hex = function (buff) {
|
||||
var bytes = new Uint8Array(buff);
|
||||
var hex = [];
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
hex.push((bytes[i] >>> 4).toString(16));
|
||||
hex.push((bytes[i] & 0xF).toString(16));
|
||||
}
|
||||
return hex.join('');
|
||||
}
|
||||
|
||||
var b32tohex = function (s) {
|
||||
var bits = '';
|
||||
var hex = '';
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
var val = b32Chars.indexOf(s.charAt(i).toUpperCase());
|
||||
bits += leftpad(val.toString(2), 5, '0');
|
||||
}
|
||||
for (var i = 0; i + 4 <= bits.length; i += 4) {
|
||||
var chunk = bits.substr(i, 4);
|
||||
hex = hex + parseInt(chunk, 2).toString(16);
|
||||
}
|
||||
return hex;
|
||||
};
|
||||
|
||||
var b32tobytes = function (s) {
|
||||
return hex2bytes(b32tohex(s));
|
||||
};
|
||||
|
||||
var sign = function (keyBytes, timeBytes) {
|
||||
return window.crypto.subtle.importKey('raw', keyBytes,
|
||||
{ name: 'HMAC', hash: { name: 'SHA-1' } }, false, ['sign']).then(function (key) {
|
||||
return window.crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-1' } }, key, timeBytes);
|
||||
}).then(function (signature) {
|
||||
return buff2hex(signature);
|
||||
}).catch(function (err) {
|
||||
return null;
|
||||
});
|
||||
};
|
||||
|
||||
TotpService.prototype.getCode = function (keyb32) {
|
||||
var epoch = Math.round(new Date().getTime() / 1000.0);
|
||||
var timeHex = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
|
||||
var timeBytes = hex2bytes(timeHex);
|
||||
var keyBytes = b32tobytes(keyb32);
|
||||
|
||||
if (!keyBytes.length || !timeBytes.length) {
|
||||
return Q.fcall(function () {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return sign(keyBytes, timeBytes).then(function (hashHex) {
|
||||
if (!hashHex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var offset = hex2dec(hashHex.substring(hashHex.length - 1));
|
||||
var otp = (hex2dec(hashHex.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
|
||||
otp = (otp).substr(otp.length - 6, 6);
|
||||
return otp;
|
||||
});
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user