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
|
// 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
|
// 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
|
// makes the attempt; the others will receive the token via a broadcast
|
||||||
|
|
|
@ -52,6 +52,7 @@ class AuthContainer extends React.Component {
|
||||||
info: PropTypes.object,
|
info: PropTypes.object,
|
||||||
auth: PropTypes.object,
|
auth: PropTypes.object,
|
||||||
// Props coming from withAuth
|
// Props coming from withAuth
|
||||||
|
userManager: PropTypes.object,
|
||||||
signIn: PropTypes.func,
|
signIn: PropTypes.func,
|
||||||
signOut: PropTypes.func,
|
signOut: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
@ -61,17 +62,55 @@ class AuthContainer extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
showZuulClientConfig: false,
|
showZuulClientConfig: false,
|
||||||
|
isSessionExpiredModalOpen: false,
|
||||||
}
|
}
|
||||||
this.handleModalToggle = () => {
|
this.handleModalToggle = () => {
|
||||||
this.setState(({ isModalOpen }) => ({
|
this.setState(({ isModalOpen }) => ({
|
||||||
isModalOpen: !isModalOpen
|
isModalOpen: !isModalOpen
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
this.handleSessionExpiredModalToggle = () => {
|
||||||
|
this.setState(({ isSessionExpiredModalOpen }) => ({
|
||||||
|
isSessionExpiredModalOpen: !isSessionExpiredModalOpen
|
||||||
|
}))
|
||||||
|
}
|
||||||
this.handleConfigToggle = () => {
|
this.handleConfigToggle = () => {
|
||||||
this.setState(({ showZuulClientConfig }) => ({
|
this.setState(({ showZuulClientConfig }) => ({
|
||||||
showZuulClientConfig: !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() {
|
componentDidUpdate() {
|
||||||
|
@ -96,6 +135,30 @@ class AuthContainer extends React.Component {
|
||||||
return ZCconfig
|
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() {
|
renderModal() {
|
||||||
const { user, tenant, timezone } = this.props
|
const { user, tenant, timezone } = this.props
|
||||||
const { isModalOpen, showZuulClientConfig } = this.state
|
const { isModalOpen, showZuulClientConfig } = this.state
|
||||||
|
@ -164,11 +227,7 @@ class AuthContainer extends React.Component {
|
||||||
<Button
|
<Button
|
||||||
key="SignIn"
|
key="SignIn"
|
||||||
variant={ButtonVariant.plain}
|
variant={ButtonVariant.plain}
|
||||||
onClick={() => {
|
onClick={() => { this.clickOnSignIn() }}>
|
||||||
const redirect_target = window.location.href.slice(getHomepageUrl().length)
|
|
||||||
localStorage.setItem('zuul_auth_redirect', redirect_target)
|
|
||||||
this.props.signIn()
|
|
||||||
}}>
|
|
||||||
Sign in
|
Sign in
|
||||||
<SignInAltIcon title='Sign In' />
|
<SignInAltIcon title='Sign In' />
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -185,6 +244,7 @@ class AuthContainer extends React.Component {
|
||||||
<UserIcon title='User details' />
|
<UserIcon title='User details' />
|
||||||
{user.data.profile.preferred_username}
|
{user.data.profile.preferred_username}
|
||||||
</Button>
|
</Button>
|
||||||
|
{this.renderCredentialsExpiredModal()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue