Skip to content

Commit

Permalink
Auth uses cookies to store Token (#375)
Browse files Browse the repository at this point in the history
* Auth uses cookies to store Token

* Add comments

* Login / signup: autocomplete best practice added

* Cleanup, add comments

* Login: password is below username field

Not on the right side

* Remove comments

* Needs to save user.data in window.localStorage
  • Loading branch information
viktorsmari authored and pral2a committed May 27, 2019
1 parent 0edcb4b commit ffc6515
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 36 deletions.
11 changes: 6 additions & 5 deletions src/app/app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@

if(trans.to().authenticate === false) {
if(auth.isAuth()) {
e.preventDefault();
$state.go('landing');
console.log('-- already logged in users cannot go to /login or /signup');
// TODO: does not redirect because e is undefined
//e.preventDefault();
//$state.go('layout.home.kit');
return;
}
}

if(trans.to().authenticate) {
if(!auth.isAuth()) {
e.preventDefault();
$state.go('landing');
$state.go('layout.login');
}
}

Expand All @@ -53,7 +54,7 @@

Restangular.addFullRequestInterceptor(function (element, operation, what, url, headers, params, httpConfig) {
if (auth.isAuth()) {
var token = auth.getCurrentUser().token;
var token = auth.getToken();
headers.Authorization = 'Bearer ' + token;
}
return {
Expand Down
15 changes: 11 additions & 4 deletions src/app/app.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@
abstract: true,
templateUrl: 'app/components/layout/layout.html',
controller: 'LayoutController',
controllerAs: 'vm'
controllerAs: 'vm',
resolve:{
isLogged: function(auth){
auth.setCurrentUser();
}
}
})
.state('layout.styleguide',{
url: '/styleguide',
Expand Down Expand Up @@ -354,11 +359,13 @@
authenticate: false,
resolve: {
buttonToClick: function($location, auth) {
// TODO: These transitions get rejected (console error)
if(auth.isAuth()) {
return $location.path('/kits');
$location.path('/kits/');
}else{
$location.path('/kits/');
$location.search('login', 'true');
}
$location.path('/kits/');
$location.search('login', 'true');
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/login/loginModal.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
.then(function(data) {
/*jshint camelcase: false */
var token = data.access_token;
auth.saveData(token);
auth.saveToken(token);
$mdDialog.hide();
})
.catch(function(err) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/login/loginModal.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ <h2>Log in</h2>

<md-input-container class="md-block">
<label>Password</label>
<input type="password" name="password" ng-model="vm.user.password" ng-required="loginForm.$submitted"/>
<input type="password" name="password" autocomplete="current-password" ng-model="vm.user.password" ng-required="loginForm.$submitted"/>
<div ng-messages="(loginForm.$submitted || loginForm.password.$touched) && loginForm.password.$error" role="alert">
<div ng-message="required">Password is required</div>
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/app/components/myProfile/myProfile.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
//THIS IS TEMPORARY.
// Will grow on to a dynamic API KEY management
// with the new /accounts oAuth mgmt methods
vm.user.token = auth.getCurrentUser().token;

// The auth controller has not populated the `user` at this point, so user.token is undefined
// This controller depends on auth has already been run.
vm.user.token = auth.getToken;
vm.addNewKit = addNewKit;


Expand Down
4 changes: 2 additions & 2 deletions src/app/components/signup/signupModal.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ <h2>Sign up</h2>
<div layout="column">
<md-input-container>
<label>Username</label>
<input type="text" name="username" ng-model="vm.user.username" focus-input name="username" required>
<input type="text" name="username" autocomplete="username" ng-model="vm.user.username" focus-input name="username" required>
<div ng-messages="signupForm.username.$error || !!errors.password.length" role="alert">
<div ng-message="required">Username is required</div>
<div ng-repeat="error in errors.username">
Expand All @@ -28,7 +28,7 @@ <h2>Sign up</h2>
</md-input-container>
<md-input-container flex>
<label>Password</label>
<input name="password" type="password" ng-model="vm.user.password"
<input name="password" type="password" autocomplete="new-password" ng-model="vm.user.password"
required>
<div ng-messages="signupForm.password.$error || !!errors.password.length" role="alert">
<div ng-message="required">Password is required</div>
Expand Down
71 changes: 49 additions & 22 deletions src/app/core/api/auth.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
.factory('auth', auth);

auth.$inject = ['$location', '$window', '$state', 'Restangular',
'$rootScope', 'AuthUser', '$timeout', 'alert'];
'$rootScope', 'AuthUser', '$timeout', 'alert', '$cookies'];
function auth($location, $window, $state, Restangular, $rootScope, AuthUser,
$timeout, alert) {
$timeout, alert, $cookies) {

var user = {};

Expand All @@ -21,7 +21,8 @@
setCurrentUser: setCurrentUser,
getCurrentUser: getCurrentUser,
updateUser: updateUser,
saveData: saveData,
saveToken: saveToken,
getToken: getToken,
login: login,
logout: logout,
recoverPassword: recoverPassword,
Expand All @@ -34,21 +35,27 @@
//////////////////////////

function initialize() {
//console.log('---- AUTH INIT -----');
setCurrentUser('appLoad');
}

//run on app initialization so that we can keep auth across different sessions
// 1. Check if token in cookie exists. Return if it doesn't, user needs to login (and save a token to the cookie)
// 2. Populate user.data with the response from the API.
// 3. Broadcast logged in
function setCurrentUser(time) {
user.token = $window.localStorage.getItem('smartcitizen.token') &&
JSON.parse( $window.localStorage.getItem('smartcitizen.token') );
user.data = $window.localStorage.getItem('smartcitizen.data') &&
new AuthUser(JSON.parse(
$window.localStorage.getItem('smartcitizen.data')
));
if(!user.token) {
// TODO later: Should we check if token is expired here?
if (getToken()) {
user.token = getToken();
}else{
//console.log('token not found in cookie, returning');
return;
}
return getCurrentUserInfo()

return getCurrentUserFromAPI()
.then(function(data) {
// Save user.data also in localStorage. It is beeing used across the app.
// Should it instead just be saved in the user object? Or is it OK to also have it in localStorage?
$window.localStorage.setItem('smartcitizen.data', JSON.stringify(data.plain()) );

var newUser = new AuthUser(data);
Expand All @@ -59,6 +66,11 @@
}
user.data = newUser;

//console.log('-- User populated with data: ', user)
// Broadcast happens 2x, so the user wont think he is not logged in.
// The 2nd broadcast waits 3sec, because f.x. on the /kits/ page, the layout has not loaded when the broadcast is sent
$rootScope.$broadcast('loggedIn');

// used for app initialization
if(time && time === 'appLoad') {
//wait until navbar is loaded to emit event
Expand All @@ -67,7 +79,7 @@
}, 3000);
} else {
// used for login
$state.reload();
//$state.reload();
$timeout(function() {
alert.success('Login was successful');
$rootScope.$broadcast('loggedIn', {});
Expand All @@ -76,38 +88,53 @@
});
}

// Called from device.service.js updateContext(), which is called from multiple /kit/ pages
function updateUser() {
return getCurrentUserInfo()
return getCurrentUserFromAPI()
.then(function(data) {
$window.localStorage.setItem('smartcitizen.data', JSON.stringify(data.plain()) );
// TODO: Should this update the token or user.data? Then it could instead call setCurrentUser?
//$window.localStorage.setItem('smartcitizen.data', JSON.stringify(data.plain()) );
});
}

function getCurrentUser() {
user.token = $window.localStorage.getItem('smartcitizen.token') && JSON.parse( $window.localStorage.getItem('smartcitizen.token') ),
// TODO: remove next line. Saving tokenCookie into user.token should ONLY BE DONE IN ONE PLACE.
// Now this is also done in 'setCurrentUser'
user.token = getToken();
user.data = $window.localStorage.getItem('smartcitizen.data') && new AuthUser(JSON.parse( $window.localStorage.getItem('smartcitizen.data') ));
return user;
}

// Should check if user.token exists - but now checks if the cookies.token exists.
function isAuth() {
return !!$window.localStorage.getItem('smartcitizen.token');
// TODO: isAuth() is called from many different services BEFORE auth.init has run.
// That means that the user.token is EMPTY, meaning isAuth will be false
// We can cheat and just check the cookie, but we should NOT. Because auth.init should also check if the cookie is valid / expired
// Ideally it should return !!user.token
//return !!user.token;
return !!getToken();
}
//save to localstorage and
function saveData(token) {
$window.localStorage.setItem('smartcitizen.token', JSON.stringify(token) );

// LoginModal calls this after it receives the token from the API, and wants to save it in a cookie.
function saveToken(token) {
//console.log('saving Token to cookie:', token);
$cookies.put('smartcitizen.token', token);
setCurrentUser();
}

function getToken(){
return $cookies.get('smartcitizen.token');
}

function login(loginData) {
return Restangular.all('sessions').post(loginData);
}

function logout() {
$window.localStorage.removeItem('smartcitizen.token');
$window.localStorage.removeItem('smartcitizen.data');
$cookies.remove('smartcitizen.token');
}

function getCurrentUserInfo() {
function getCurrentUserFromAPI() {
return Restangular.all('').customGET('me');
}

Expand Down

0 comments on commit ffc6515

Please sign in to comment.