web UI: Add a credentials renew modal
Check every second for an authenticated user's token expiration. If the token has expired, display a modal providing a link to log in again. Closing the modal properly logs the user out. Change-Id: I0baa4f415bdc61735fc42f9fd80a58309976096f
This commit is contained in:
parent
41d6008a3d
commit
84ab85a306
|
@ -143,14 +143,6 @@ class ZuulAuthProvider extends React.Component {
|
|||
}
|
||||
})
|
||||
|
||||
// This is called when a token is expired
|
||||
userManager.events.addAccessTokenExpired(() => {
|
||||
console.log('Auth token expired')
|
||||
userManager.removeUser()
|
||||
this.props.dispatch(userLoggedOut())
|
||||
this.props.channel.postMessage({ 'type': 'signOut' })
|
||||
})
|
||||
|
||||
// This is called about 1 minute before a token is expired. We will try
|
||||
// to renew the token. We use a leader election so that only one tab
|
||||
// makes the attempt; the others will receive the token via a broadcast
|
||||
|
|
|
@ -52,6 +52,7 @@ class AuthContainer extends React.Component {
|
|||
info: PropTypes.object,
|
||||
auth: PropTypes.object,
|
||||
// Props coming from withAuth
|
||||
userManager: PropTypes.object,
|
||||
signIn: PropTypes.func,
|
||||
signOut: PropTypes.func,
|
||||
}
|
||||
|
@ -61,17 +62,55 @@ class AuthContainer extends React.Component {
|
|||
this.state = {
|
||||
isModalOpen: false,
|
||||
showZuulClientConfig: false,
|
||||
isSessionExpiredModalOpen: false,
|
||||
}
|
||||
this.handleModalToggle = () => {
|
||||
this.setState(({ isModalOpen }) => ({
|
||||
isModalOpen: !isModalOpen
|
||||
}))
|
||||
}
|
||||
this.handleSessionExpiredModalToggle = () => {
|
||||
this.setState(({ isSessionExpiredModalOpen }) => ({
|
||||
isSessionExpiredModalOpen: !isSessionExpiredModalOpen
|
||||
}))
|
||||
}
|
||||
this.handleConfigToggle = () => {
|
||||
this.setState(({ showZuulClientConfig }) => ({
|
||||
showZuulClientConfig: !showZuulClientConfig
|
||||
}))
|
||||
}
|
||||
this.onAccessTokenExpired = () => {
|
||||
// If the token has expired, show the modal
|
||||
console.debug('Token expired')
|
||||
this.setState(() => ({
|
||||
isSessionExpiredModalOpen: true,
|
||||
isModalOpen: false,
|
||||
}))
|
||||
}
|
||||
this.onUserLoaded = () => {
|
||||
// If another tab logged in while our expired modal is shown, go
|
||||
// ahead and clear it.
|
||||
console.debug('User signed in')
|
||||
this.setState(() => ({
|
||||
isSessionExpiredModalOpen: false,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
clickOnSignIn() {
|
||||
const redirect_target = window.location.href.slice(getHomepageUrl().length)
|
||||
localStorage.setItem('zuul_auth_redirect', redirect_target)
|
||||
this.props.signIn()
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.userManager.events.addAccessTokenExpired(this.onAccessTokenExpired)
|
||||
this.props.userManager.events.addUserLoaded(this.onUserLoaded)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.userManager.events.removeAccessTokenExpired(this.onAccessTokenExpired)
|
||||
this.props.userManager.events.removeUserLoaded(this.onUserLoaded)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
|
@ -96,6 +135,30 @@ class AuthContainer extends React.Component {
|
|||
return ZCconfig
|
||||
}
|
||||
|
||||
renderCredentialsExpiredModal() {
|
||||
const { isSessionExpiredModalOpen } = this.state
|
||||
return <React.Fragment>
|
||||
<Modal
|
||||
position='top'
|
||||
title='You are being logged out'
|
||||
isOpen={isSessionExpiredModalOpen}
|
||||
variant={ModalVariant.small}
|
||||
onClose={() => {
|
||||
this.handleSessionExpiredModalToggle()
|
||||
this.props.signOut()
|
||||
}}>
|
||||
Your session has expired.
|
||||
<Button
|
||||
key="SignIn"
|
||||
isInline
|
||||
variant={ButtonVariant.link}
|
||||
onClick={() => { this.clickOnSignIn() }}>
|
||||
Please renew your credentials.
|
||||
</Button>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
renderModal() {
|
||||
const { user, tenant, timezone } = this.props
|
||||
const { isModalOpen, showZuulClientConfig } = this.state
|
||||
|
@ -164,11 +227,7 @@ class AuthContainer extends React.Component {
|
|||
<Button
|
||||
key="SignIn"
|
||||
variant={ButtonVariant.plain}
|
||||
onClick={() => {
|
||||
const redirect_target = window.location.href.slice(getHomepageUrl().length)
|
||||
localStorage.setItem('zuul_auth_redirect', redirect_target)
|
||||
this.props.signIn()
|
||||
}}>
|
||||
onClick={() => { this.clickOnSignIn() }}>
|
||||
Sign in
|
||||
<SignInAltIcon title='Sign In' />
|
||||
</Button>
|
||||
|
@ -185,6 +244,7 @@ class AuthContainer extends React.Component {
|
|||
<UserIcon title='User details' />
|
||||
{user.data.profile.preferred_username}
|
||||
</Button>
|
||||
{this.renderCredentialsExpiredModal()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue