Skip to content

Commit

Permalink
(web) bug fix - redirect to login if not signed-in
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-kovoy committed Jan 13, 2017
1 parent 36a2d48 commit e0e163b
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 40 deletions.
Expand Up @@ -991,10 +991,10 @@ webpackJsonp([0],{
var cfg = __webpack_require__(217);
var $ = __webpack_require__(219);
var logger = __webpack_require__(230).create('services/auth');

__webpack_require__(231); // This puts it in window.u2f

var AUTH_IS_RENEWING = 'GRV_AUTH_IS_RENEWING';

var PROVIDER_GOOGLE = 'google';
var SECOND_FACTOR_TYPE_HOTP = 'hotp';
var SECOND_FACTOR_TYPE_OIDC = 'oidc';
Expand Down Expand Up @@ -1030,6 +1030,7 @@ webpackJsonp([0],{
u2f_register_response: res,
invite_token: inviteToken
};

api.post(cfg.api.u2fCreateUserPath, response, false).then(function (data) {
session.setUserData(data);
auth._startTokenRefresher();
Expand Down Expand Up @@ -1100,6 +1101,9 @@ webpackJsonp([0],{

var userData = session.getUserData();

// ping the server to check if user signed out from another tab
this._checkStatus();

if (!userData.token) {
return $.Deferred().reject();
}
Expand Down Expand Up @@ -1134,36 +1138,38 @@ webpackJsonp([0],{

var delta = created + expires_in - new Date().getTime();

// give some extra time for slow connection */
// give some extra time for slow connection
return delta < CHECK_TOKEN_REFRESH_RATE * 3;
},
_startTokenRefresher: function _startTokenRefresher() {
refreshTokenTimerId = setInterval(auth._fetchStatus.bind(auth), CHECK_TOKEN_REFRESH_RATE);
refreshTokenTimerId = setInterval(auth.ensureUser.bind(auth), CHECK_TOKEN_REFRESH_RATE);
},
_stopTokenRefresher: function _stopTokenRefresher() {
clearInterval(refreshTokenTimerId);
refreshTokenTimerId = null;
},
_fetchStatus: function _fetchStatus() {
_checkStatus: function _checkStatus() {
// do not attemp to fetch the status with potentially invalid token
// as it will trigger logout action.
if (localStorage.getItem(AUTH_IS_RENEWING) !== null) {
return;
}

api.get(cfg.api.userStatus).done(auth.ensureUser.bind(this)).fail(function (err) {
api.get(cfg.api.userStatus).fail(function (err) {
// indicates that user session is no longer valid
if (err.status == 403) {
auth.logout();
}
});
},
_refreshToken: function _refreshToken() {
localStorage.setItem(AUTH_IS_RENEWING, true);
return api.post(cfg.api.renewTokenPath).then(function (data) {
session.setUserData(data);
return data;
}).fail(function () {
auth.logout();
}).always(function () {
localStorage.removeItem(AUTH_IS_RENEWING);
});
},
_getU2fErr: function _getU2fErr(errorCode) {
Expand Down
File renamed without changes.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion web/dist/index.html
Expand Up @@ -10,5 +10,5 @@
<body class="grv">
<div id="app"></div>
<div id="bearer_token" style="display: none;">{{.Session}}</div>
<script type="text/javascript" src="/web/app/vendor.413147faa79807fc46a9.js"></script><script type="text/javascript" src="/web/app/styles.413147faa79807fc46a9.js"></script><script type="text/javascript" src="/web/app/app.413147faa79807fc46a9.js"></script></body>
<script type="text/javascript" src="/web/app/vendor.f04179d72ade36111d9e.js"></script><script type="text/javascript" src="/web/app/styles.f04179d72ade36111d9e.js"></script><script type="text/javascript" src="/web/app/app.f04179d72ade36111d9e.js"></script></body>
</html>
11 changes: 8 additions & 3 deletions web/src/app/__tests__/authTest.js
Expand Up @@ -20,6 +20,7 @@ var api = require('app/services/api');
var session = require('app/services/session');
var spyOn = expect.spyOn;
var auth = require('app/services/auth');
var cfg = require('app/config');

describe('auth', function () {
var sample = { token: 'token', expires_in: 599, created: new Date().getTime() };
Expand All @@ -29,6 +30,7 @@ describe('auth', function () {
spyOn(session, 'getUserData');
spyOn(session, 'clear');
spyOn(api, 'post');
spyOn(api, 'get');
spyOn(api, 'delete').andReturn($.Deferred().resolve());
spyOn(auth, '_startTokenRefresher');
spyOn(auth, '_stopTokenRefresher');
Expand Down Expand Up @@ -107,7 +109,8 @@ describe('auth', function () {
session.getUserData.andReturn(sample);
auth.ensureUser('user', 'password').done(()=> { wasCalled = true });

expect(wasCalled).toEqual(true);
expect(wasCalled).toEqual(true);
expect(api.get).toHaveBeenCalledWith(cfg.api.userStatus);
expect(auth._startTokenRefresher).toHaveBeenCalled();
expect(auth._shouldRefreshToken).toHaveBeenCalled();
});
Expand All @@ -125,16 +128,18 @@ describe('auth', function () {
auth.ensureUser('user', 'password').done(()=> { wasCalled = true });

expect(wasCalled).toEqual(true);
expect(api.get).toHaveBeenCalledWith(cfg.api.userStatus);
expect(auth._startTokenRefresher).toHaveBeenCalled();
expect(auth._shouldRefreshToken).toHaveBeenCalled();
});
});

describe('when token is missing', function () {
it('should reject', function () {
var wasCalled = false;
session.getUserData.andReturn({});
auth.ensureUser('user', 'password').fail(()=> { wasCalled = true });
auth.ensureUser('user', 'password').fail(() => { wasCalled = true });
expect(api.get).toHaveBeenCalledWith(cfg.api.userStatus);
expect(wasCalled).toEqual(true);
});
});
Expand Down
68 changes: 39 additions & 29 deletions web/src/app/services/auth.js
Expand Up @@ -19,20 +19,20 @@ var session = require('./session');
var cfg = require('app/config');
var $ = require('jQuery');
var logger = require('app/common/logger').create('services/auth');

require('u2f-api-polyfill'); // This puts it in window.u2f

const AUTH_IS_RENEWING = 'GRV_AUTH_IS_RENEWING';

const PROVIDER_GOOGLE = 'google';
const SECOND_FACTOR_TYPE_HOTP = 'hotp';
const SECOND_FACTOR_TYPE_OIDC = 'oidc';
const SECOND_FACTOR_TYPE_U2F = 'u2f';

const CHECK_TOKEN_REFRESH_RATE = 10 * 1000; // 10 sec

var refreshTokenTimerId = null;
let refreshTokenTimerId = null;

var auth = {
const auth = {

signUp(name, password, token, inviteToken){
var data = {user: name, pass: password, second_factor_token: token, invite_token: inviteToken};
Expand All @@ -56,18 +56,21 @@ var auth = {
}

var response = {
user: name,
pass: password,
user: name,
pass: password,
u2f_register_response: res,
invite_token: inviteToken
invite_token: inviteToken
};
api.post(cfg.api.u2fCreateUserPath, response, false).then(data=>{
session.setUserData(data);
auth._startTokenRefresher();
deferred.resolve(data);
}).fail(data=>{
deferred.reject(data);
})

api.post(cfg.api.u2fCreateUserPath, response, false)
.then(data => {
session.setUserData(data);
auth._startTokenRefresher();
deferred.resolve(data);
})
.fail(data => {
deferred.reject(data);
})
});

return deferred.promise();
Expand Down Expand Up @@ -130,18 +133,21 @@ var auth = {
ensureUser(){
this._stopTokenRefresher();

var userData = session.getUserData();
let userData = session.getUserData();

// ping the server to check if user signed out from another tab
this._checkStatus();

if(!userData.token){
return $.Deferred().reject();
}

if(this._shouldRefreshToken(userData)){
return this._refreshToken().done(this._startTokenRefresher);
}

this._startTokenRefresher();
return $.Deferred().resolve(userData);
return $.Deferred().resolve(userData);
},

logout(){
Expand All @@ -166,43 +172,47 @@ var auth = {

var delta = created + expires_in - new Date().getTime();

// give some extra time for slow connection */
// give some extra time for slow connection
return delta < CHECK_TOKEN_REFRESH_RATE * 3;
},

_startTokenRefresher(){
refreshTokenTimerId = setInterval(auth._fetchStatus.bind(auth), CHECK_TOKEN_REFRESH_RATE);
refreshTokenTimerId = setInterval(auth.ensureUser.bind(auth), CHECK_TOKEN_REFRESH_RATE);
},

_stopTokenRefresher(){
clearInterval(refreshTokenTimerId);
refreshTokenTimerId = null;
},

_fetchStatus(){
_checkStatus(){
// do not attemp to fetch the status with potentially invalid token
// as it will trigger logout action.
if(localStorage.getItem(AUTH_IS_RENEWING) !== null){
return;
}

api.get(cfg.api.userStatus)
.done(auth.ensureUser.bind(this))
.fail( err => {
api.get(cfg.api.userStatus)
.fail(err => {
// indicates that user session is no longer valid
if(err.status == 403){
auth.logout();
}
});
},

_refreshToken(){
return api.post(cfg.api.renewTokenPath).then(data=>{
session.setUserData(data);
return data;
}).fail(()=>{
auth.logout();
});
_refreshToken() {
localStorage.setItem(AUTH_IS_RENEWING, true);
return api.post(cfg.api.renewTokenPath)
.then(data => {
session.setUserData(data);
})
.fail(() => {
auth.logout();
})
.always(() => {
localStorage.removeItem(AUTH_IS_RENEWING);
});
},

_getU2fErr(errorCode){
Expand Down

0 comments on commit e0e163b

Please sign in to comment.