Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Add interval to check session expiration (#157)
Browse files Browse the repository at this point in the history
* Add interval to check session expiration
  • Loading branch information
sdford authored May 16, 2018
1 parent e4161d1 commit 3bc2f37
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 36 deletions.
68 changes: 44 additions & 24 deletions dashboard/app/actions/authenticationActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ApiError from '../components/ApiError/ApiError'
import ConfirmationBox from '../components/ConfirmationBox/ConfirmationBox'
import * as modalActions from '../actions/modalActions'
import * as manageSDBActions from '../actions/manageSafetyDepositBoxActions'
import * as workerTimers from 'worker-timers'
import { getLogger } from 'logger'

var log = getLogger('authentication-actions')
Expand All @@ -25,15 +26,15 @@ const AUTH_ACTION_TIMEOUT = 60000 // 60 seconds in milliseconds
/**
* This action is dispatched when we have a valid response object from the CMS Auth endpoint
* @param response The json response object from the ldap auth cms endpoint
* @param authTokenTimeoutId ID of the timeout that expires the user session
* @param sessionExpirationCheckIntervalId ID of the interval that checks to see if the user's session has expired
* @returns {{type: string, payload: {tokenData: *}}} The object to dispatch to trigger the reducer to update the auth state
*/
export function loginUserSuccess(response, authTokenTimeoutId) {
export function loginUserSuccess(response, sessionExpirationCheckIntervalId) {
return {
type: constants.LOGIN_USER_SUCCESS,
payload: {
tokenData: response.data.client_token,
authTokenTimeoutId: authTokenTimeoutId
sessionExpirationCheckIntervalId: sessionExpirationCheckIntervalId
}
}
}
Expand Down Expand Up @@ -80,21 +81,26 @@ function handleUserLogin(response, dispatch, redirectToWelcome=true) {

let timeToExpireTokenInMillis = tokenExpiresDate.getTime() - now.getTime()

let sessionWarningTimeoutId = setTimeout(() => {
let sessionExpirationCheckIntervalInMillis = 2000
let sessionExpirationCheckIntervalId = workerTimers.setInterval(() => {
let currentTimeInMillis = new Date().getTime()
let sessionExpirationTimeInMillis = tokenExpiresDate.getTime()
if (currentTimeInMillis >= sessionExpirationTimeInMillis) {
dispatch(handleSessionExpiration())
}
}, sessionExpirationCheckIntervalInMillis)

let sessionWarningTimeoutId = workerTimers.setTimeout(() => {
dispatch(warnSessionExpiresSoon(token))
}, timeToExpireTokenInMillis - 120000) // warn two minutes before expiration

dispatch(setSessionWarningTimeoutId(sessionWarningTimeoutId))

let authTokenTimeoutId = setTimeout(() => {
dispatch(handleSessionExpiration())
}, timeToExpireTokenInMillis)

sessionStorage.setItem('token', JSON.stringify(response.data))
sessionStorage.setItem('tokenExpiresDate', tokenExpiresDate)
sessionStorage.setItem('userRespondedToSessionWarning', false)
dispatch(messengerActions.clearAllMessages())
dispatch(loginUserSuccess(response.data, authTokenTimeoutId))
dispatch(loginUserSuccess(response.data, sessionExpirationCheckIntervalId))
dispatch(appActions.fetchSideBarData(token))
if (redirectToWelcome) {
hashHistory.push("/")
Expand Down Expand Up @@ -196,9 +202,9 @@ export function refreshAuth(token, redirectPath='/', redirect=true) {
timeout: AUTH_ACTION_TIMEOUT
})
.then(function (response) {
dispatch(handleRemoveAuthTokenTimeout())
dispatch(handleRemoveSessionWarningTimeout())
setTimeout(function(){
dispatch(handleRemoveSessionExpirationCheck())
dispatch(removeSessionWarningTimeout())
workerTimers.setTimeout(function(){
handleUserLogin(response, dispatch, false)
if (redirect) {
hashHistory.push(redirectPath)
Expand Down Expand Up @@ -232,8 +238,8 @@ export function logoutUser(token) {
sessionStorage.removeItem('token')
sessionStorage.removeItem('tokenExpiresDate')
sessionStorage.removeItem('userRespondedToSessionWarning')
dispatch(handleRemoveAuthTokenTimeout())
dispatch(handleRemoveSessionWarningTimeout())
dispatch(handleRemoveSessionExpirationCheck())
dispatch(removeSessionWarningTimeout())
dispatch(resetAuthState())
dispatch(headerActions.mouseOutUsername())
hashHistory.push('/login')
Expand All @@ -253,8 +259,8 @@ export function handleSessionExpiration() {
sessionStorage.removeItem('token')
sessionStorage.removeItem('tokenExpiresDate')
sessionStorage.removeItem('userRespondedToSessionWarning')
dispatch(handleRemoveAuthTokenTimeout())
dispatch(handleRemoveSessionWarningTimeout())
dispatch(handleRemoveSessionExpirationCheck())
dispatch(removeSessionWarningTimeout())
dispatch(expireSession())
dispatch(modalActions.clearAllModals())
dispatch(manageSDBActions.resetToInitialState())
Expand All @@ -274,9 +280,9 @@ export function expireSession() {
}
}

export function removeAuthTokenTimeoutId() {
export function removeSessionExpirationCheck() {
return {
type: constants.REMOVE_AUTH_TOKEN_TIMEOUT
type: constants.REMOVE_SESSION_EXPIRATION_CHECK_INTERVAL
}
}

Expand All @@ -295,16 +301,30 @@ export function setSessionWarningTimeoutId(id) {
}
}

export function handleRemoveAuthTokenTimeout() {
export function handleRemoveSessionExpirationCheck() {
return function(dispatch, getState) {
clearTimeout(getState().auth.authTokenTimeoutId)
dispatch(removeAuthTokenTimeoutId())
let sessionExpirationCheckIntervalId = getState().auth.sessionExpirationCheckIntervalId
log.debug(`Removing session expiration check interval, id: ${sessionExpirationCheckIntervalId}`)
try {
workerTimers.clearInterval(sessionExpirationCheckIntervalId)
} catch(err) {
console.log(`Failed to clear auth token timeout, id=${sessionExpirationCheckIntervalId}`)
console.log(err)
}
dispatch(removeSessionExpirationCheck())
}
}

export function handleRemoveSessionWarningTimeout() {
export function removeSessionWarningTimeout() {
return function(dispatch, getState) {
clearTimeout(getState().auth.sessionWarningTimeoutId)
let sessionWarningTimeoutId = getState().auth.sessionWarningTimeoutId
log.debug(`Removing warning timeout, id: ${sessionWarningTimeoutId}`)
try {
workerTimers.clearTimeout(getState().auth.sessionWarningTimeoutId)
} catch(err) {
console.log(`Failed to clear session warning timeout, id=${sessionWarningTimeoutId}`)
console.log(err)
}
dispatch(removeSessionWarningTimeoutId())
}
}
Expand All @@ -325,7 +345,7 @@ export function setSessionWarningTimeout(timeToWarnInMillis, tokenStr) {
let userHasRespondedToSessionWarning = sessionStorage.getItem('userRespondedToSessionWarning') === "true";

if (! userHasRespondedToSessionWarning) {
let sessionWarningTimeoutId = setTimeout(() => {
let sessionWarningTimeoutId = workerTimers.setTimeout(() => {
dispatch(warnSessionExpiresSoon(tokenStr))
}, timeToWarnInMillis)

Expand Down
2 changes: 1 addition & 1 deletion dashboard/app/constants/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const RESET_USER_AUTH_STATE = 'RESET_USER_AUTH_STATE'
export const SESSION_EXPIRED = 'SESSION_EXPIRED'
export const LOGIN_MFA_REQUIRED = 'LOGIN_MFA_REQUIRED'
export const SET_SESSION_WARNING_TIMEOUT_ID = "SET_SESSION_WARNING_TIMEOUT_ID"
export const REMOVE_AUTH_TOKEN_TIMEOUT = "REMOVE_AUTH_TOKEN_TIMEOUT"
export const REMOVE_SESSION_EXPIRATION_CHECK_INTERVAL = "REMOVE_SESSION_EXPIRATION_CHECK_INTERVAL"
export const REMOVE_SESSION_WARNING_TIMEOUT = "REMOVE_SESSION_WARNING_TIMEOUT"

// HEADER ACTIONS
Expand Down
14 changes: 10 additions & 4 deletions dashboard/app/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ManageSafeDepositBox from './components/ManageSafeDepositBox/ManageSafeDe
import NotFound from './components/NotFound/NotFound'
import configureStore from './store/configureStore'
import { loginUserSuccess, handleSessionExpiration, setSessionWarningTimeout } from './actions/authenticationActions'
import * as workerTimers from 'worker-timers'
import { getLogger } from 'logger'
import './assets/styles/reactSelect.scss'

Expand Down Expand Up @@ -40,11 +41,16 @@ if (token != null && token != "") {
// warn two minutes before token expiration
store.dispatch(setSessionWarningTimeout(dateTokenExpiresInMillis - 120000, token.data.client_token.client_token))

let authTokenTimeoutId = setTimeout(() => {
store.dispatch(handleSessionExpiration())
}, dateTokenExpiresInMillis)
let sessionExpirationCheckIntervalInMillis = 2000
let sessionExpirationCheckIntervalId = workerTimers.setInterval(() => {
let currentTimeInMillis = new Date().getTime()
let sessionExpirationTimeInMillis = tokenExpiresDate.getTime()
if (currentTimeInMillis >= sessionExpirationTimeInMillis) {
store.dispatch(handleSessionExpiration())
}
}, sessionExpirationCheckIntervalInMillis)

store.dispatch(loginUserSuccess(token, authTokenTimeoutId))
store.dispatch(loginUserSuccess(token, sessionExpirationCheckIntervalId))
}

// Create an enhanced history that syncs navigation events with the store
Expand Down
10 changes: 5 additions & 5 deletions dashboard/app/reducers/authenticationReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const initialState = {
isAdmin: false,
groups: [],
policies: null,
authTokenTimeoutId: null,
sessionExpirationCheckIntervalId: null,
sessionWarningTimeoutId: null
}

Expand All @@ -36,7 +36,7 @@ export default createReducer(initialState, {
userName: payload.tokenData.metadata.username,
groups: payload.tokenData.metadata.groups.split(/,/),
policies: payload.tokenData.policies,
authTokenTimeoutId: payload.authTokenTimeoutId,
sessionExpirationCheckIntervalId: payload.sessionExpirationCheckIntervalId,
})
},
// logs the user out and resets user data
Expand Down Expand Up @@ -65,11 +65,11 @@ export default createReducer(initialState, {
sessionWarningTimeoutId: payload.sessionWarningTimeoutId,
})
},
// removes the timeout id of the auth token expire
[constants.REMOVE_AUTH_TOKEN_TIMEOUT]: (state) => {
// removes the interval id of the session expiration check
[constants.REMOVE_SESSION_EXPIRATION_CHECK_INTERVAL]: (state) => {

return Object.assign({}, state, {
authTokenTimeoutId: null
sessionExpirationCheckIntervalId: null
})
},
// removes the timeout id of the session warning
Expand Down
3 changes: 2 additions & 1 deletion dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"redux": "3.5.2",
"redux-form": "5.3.4",
"redux-logger": "2.6.1",
"redux-thunk": "2.1.0"
"redux-thunk": "2.1.0",
"worker-timers": "4.0.30"
},
"devDependencies": {
"babel-core": "6.10.4",
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
# limitations under the License.
#

version=3.15.2
version=3.15.3
groupId=com.nike.cerberus
artifactId=cms

0 comments on commit 3bc2f37

Please sign in to comment.