1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-02-25 02:51:59 +01:00

WIP convert web vault to new identity server

This commit is contained in:
Kyle Spearrin 2017-01-28 01:19:43 -05:00
parent 3df5a9454e
commit 1fe673951b
6 changed files with 117 additions and 66 deletions

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService, $state, appSettings, $analytics) { .controller('accountsLoginController', function ($scope, $rootScope, $cookies, apiService, cryptoService, authService,
$state, appSettings, $analytics) {
var rememberedEmail = $cookies.get(appSettings.rememberedEmailCookieName); var rememberedEmail = $cookies.get(appSettings.rememberedEmailCookieName);
if (rememberedEmail) { if (rememberedEmail) {
$scope.model = { $scope.model = {
@ -10,10 +11,13 @@ angular
}; };
} }
var email,
masterPassword;
$scope.login = function (model) { $scope.login = function (model) {
$scope.loginPromise = authService.logIn(model.email, model.masterPassword); $scope.loginPromise = authService.logIn(model.email, model.masterPassword);
$scope.loginPromise.then(function () { $scope.loginPromise.then(function (twoFactorProviders) {
if (model.rememberEmail) { if (model.rememberEmail) {
var cookieExpiration = new Date(); var cookieExpiration = new Date();
cookieExpiration.setFullYear(cookieExpiration.getFullYear() + 10); cookieExpiration.setFullYear(cookieExpiration.getFullYear() + 10);
@ -27,8 +31,10 @@ angular
$cookies.remove(appSettings.rememberedEmailCookieName); $cookies.remove(appSettings.rememberedEmailCookieName);
} }
var profile = authService.getUserProfile(); if (twoFactorProviders && twoFactorProviders.length > 0) {
if (profile.twoFactor) { email = model.email;
masterPassword = model.masterPassword;
$analytics.eventTrack('Logged In To Two-step'); $analytics.eventTrack('Logged In To Two-step');
$state.go('frontend.login.twoFactor'); $state.go('frontend.login.twoFactor');
} }
@ -40,8 +46,8 @@ angular
}; };
$scope.twoFactor = function (model) { $scope.twoFactor = function (model) {
// Only supporting Authenticator provider for now // Only supporting Authenticator (0) provider for now
$scope.twoFactorPromise = authService.logInTwoFactor(model.code, "Authenticator"); $scope.twoFactorPromise = authService.logIn(email, masterPassword, model.code, 'Authenticator');
$scope.twoFactorPromise.then(function () { $scope.twoFactorPromise.then(function () {
$analytics.eventTrack('Logged In From Two-step'); $analytics.eventTrack('Logged In From Two-step');

View File

@ -2,11 +2,38 @@ angular
.module('bit') .module('bit')
.config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, $uibTooltipProvider, toastrConfig) { .config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, $uibTooltipProvider, toastrConfig) {
jwtInterceptorProvider.urlParam = 'access_token'; var refreshingToken = null;
jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (config, appSettings, tokenService) { jwtInterceptorProvider.urlParam = 'access_token2';
if (config.url.indexOf(appSettings.apiUri) === 0) { jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (config, appSettings, tokenService, apiService, jwtHelper) {
return tokenService.getToken(); if (config.url.indexOf(appSettings.apiUri) !== 0) {
return;
} }
var token = tokenService.getToken();
var refreshToken = tokenService.getRefreshToken();
if (!token) {
return;
}
if (!jwtHelper.isTokenExpired(tokenService.getToken())) {
return token;
}
if (refreshingToken === null) {
refreshingToken = apiService.identity.token({
grant_type: 'refresh_token',
client_id: 'web',
refresh_token: refreshToken
}, function (response) {
tokenService.setToken(response.access_token);
tokenService.setRefreshToken(response.refresh_token);
refreshingToken = null;
}, function () {
refreshingToken = null;
});
}
return refreshingToken;
}; };
angular.extend(toastrConfig, { angular.extend(toastrConfig, {
@ -129,7 +156,7 @@ angular
.run(function ($rootScope, authService, jwtHelper, tokenService, $state) { .run(function ($rootScope, authService, jwtHelper, tokenService, $state) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if (!toState.data || !toState.data.authorize) { if (!toState.data || !toState.data.authorize) {
if (authService.isAuthenticated() && !jwtHelper.isTokenExpired(tokenService.getToken())) { if (authService.isAuthenticated()) {
event.preventDefault(); event.preventDefault();
$state.go('backend.vault'); $state.go('backend.vault');
} }
@ -137,7 +164,7 @@ angular
return; return;
} }
if (!authService.isAuthenticated() || jwtHelper.isTokenExpired(tokenService.getToken())) { if (!authService.isAuthenticated()) {
event.preventDefault(); event.preventDefault();
authService.logOut(); authService.logOut();
$state.go('frontend.login.info'); $state.go('frontend.login.info');

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.services') .module('bit.services')
.factory('apiService', function ($resource, tokenService, appSettings) { .factory('apiService', function ($resource, tokenService, appSettings, $httpParamSerializer) {
var _service = {}, var _service = {},
_apiUri = appSettings.apiUri; _apiUri = appSettings.apiUri;
@ -57,5 +57,19 @@
tokenTwoFactor: { url: _apiUri + '/auth/token/two-factor', method: 'POST', params: {} } tokenTwoFactor: { url: _apiUri + '/auth/token/two-factor', method: 'POST', params: {} }
}); });
_service.identity = $resource(_apiUri + '/connect', {}, {
token: {
url: _apiUri + '/connect/token',
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
transformRequest: transformUrlEncoded,
params: {}
}
});
function transformUrlEncoded(data) {
return $httpParamSerializer(data);
}
return _service; return _service;
}); });

View File

@ -5,51 +5,42 @@ angular
var _service = {}, var _service = {},
_userProfile = null; _userProfile = null;
_service.logIn = function (email, masterPassword) { _service.logIn = function (email, masterPassword, token, provider) {
email = email.toLowerCase(); email = email.toLowerCase();
var key = cryptoService.makeKey(masterPassword, email); var key = cryptoService.makeKey(masterPassword, email);
var request = { var request = {
email: email, username: email,
masterPasswordHash: cryptoService.hashPassword(masterPassword, key) password: cryptoService.hashPassword(masterPassword, key),
grant_type: 'password',
scope: 'api offline_access',
client_id: 'web'
}; };
if (token && typeof (provider) !== 'undefined' && provider !== null) {
request.twoFactorToken = token.replace(' ', '');
request.twoFactorProvider = provider;
}
// TODO: device information one day?
var deferred = $q.defer(); var deferred = $q.defer();
apiService.auth.token(request, function (response) { apiService.identity.token(request, function (response) {
if (!response || !response.Token) { if (!response || !response.access_token) {
return; return;
} }
tokenService.setToken(response.Token); tokenService.setToken(response.access_token);
tokenService.setRefreshToken(response.refresh_token);
cryptoService.setKey(key); cryptoService.setKey(key);
_service.setUserProfile(response.Profile); deferred.resolve();
deferred.resolve(response);
}, function (error) { }, function (error) {
deferred.reject(error); if (error.status === 400 && error.data.TwoFactorProviders && error.data.TwoFactorProviders.length) {
}); deferred.resolve(error.data.TwoFactorProviders);
return deferred.promise;
};
_service.logInTwoFactor = function (code, provider) {
var request = {
code: code.replace(' ', ''),
provider: provider
};
var deferred = $q.defer();
apiService.auth.tokenTwoFactor(request, function (response) {
if (!response || !response.Token) {
return;
} }
else {
tokenService.setToken(response.Token);
_service.setUserProfile(response.Profile);
deferred.resolve(response);
}, function (error) {
deferred.reject(error); deferred.reject(error);
}
}); });
return deferred.promise; return deferred.promise;
@ -57,6 +48,7 @@ angular
_service.logOut = function () { _service.logOut = function () {
tokenService.clearToken(); tokenService.clearToken();
tokenService.clearRefreshToken();
cryptoService.clearKey(); cryptoService.clearKey();
_userProfile = null; _userProfile = null;
}; };
@ -69,27 +61,20 @@ angular
return _userProfile; return _userProfile;
}; };
_service.setUserProfile = function (profile) { _service.setUserProfile = function () {
var token = tokenService.getToken(); var token = tokenService.getToken();
if (!token) { if (!token) {
return; return;
} }
var decodedToken = jwtHelper.decodeToken(token); var decodedToken = jwtHelper.decodeToken(token);
var twoFactor = decodedToken.authmethod === "TwoFactor";
_userProfile = { _userProfile = {
id: decodedToken.nameid, id: decodedToken.name,
email: decodedToken.email, email: decodedToken.email
twoFactor: twoFactor
}; };
if (!twoFactor && profile) {
loadProfile(profile);
}
else if (!twoFactor && !profile) {
apiService.accounts.getProfile({}, loadProfile); apiService.accounts.getProfile({}, loadProfile);
}
}; };
function loadProfile(profile) { function loadProfile(profile) {
@ -101,11 +86,7 @@ angular
} }
_service.isAuthenticated = function () { _service.isAuthenticated = function () {
return _service.getUserProfile() !== null && !_service.getUserProfile().twoFactor; return tokenService.getToken() !== null;
};
_service.isTwoFactorAuthenticated = function () {
return _service.getUserProfile() !== null && _service.getUserProfile().twoFactor;
}; };
return _service; return _service;

View File

@ -3,24 +3,43 @@ angular
.factory('tokenService', function ($sessionStorage) { .factory('tokenService', function ($sessionStorage) {
var _service = {}, var _service = {},
_token; _token = null,
_refreshToken = null;
_service.setToken = function (token) { _service.setToken = function (token) {
$sessionStorage.authBearer = token; $sessionStorage.accessToken = token;
_token = token; _token = token;
}; };
_service.getToken = function () { _service.getToken = function () {
if (!_token) { if (!_token) {
_token = $sessionStorage.authBearer; _token = $sessionStorage.accessToken;
} }
return _token; return _token ? _token : null;
}; };
_service.clearToken = function () { _service.clearToken = function () {
_token = null; _token = null;
delete $sessionStorage.authBearer; delete $sessionStorage.accessToken;
};
_service.setRefreshToken = function (token) {
$sessionStorage.refreshToken = token;
_refreshToken = token;
};
_service.getRefreshToken = function () {
if (!_refreshToken) {
_refreshToken = $sessionStorage.refreshToken;
}
return _refreshToken ? _refreshToken : null;
};
_service.clearRefreshToken = function () {
_refreshToken = null;
delete $sessionStorage.refreshToken;
}; };
return _service; return _service;

View File

@ -14,6 +14,10 @@
return; return;
} }
if (data && data.ErrorModel) {
data = data.ErrorModel;
}
if (!data.ValidationErrors) { if (!data.ValidationErrors) {
if (data.Message) { if (data.Message) {
form.$errors.push(data.Message); form.$errors.push(data.Message);