Вы можете сделать следующее:
- Создать некоторую функцию-наблюдатель, которая проверяет время истечения токена доступа. Если срок действия токена истекает, пришло время его обновить.
- Для рендеринга тега iframe sr c должен быть тем же URL-адресом, который вы используете для перенаправления на сервер аутентификации, с одним отличием : измените URL возврата на файл * stati c, назовем его
redirect.html
. Сервер должен знать о пользователе, вызывающем этот URL, из сохраненного файла cook ie, поэтому он должен просто перенаправить вас в файл redirect.html
, теперь с токеном fre sh. - In
redirect.html
напишите короткий сценарий, который извлекает токен из URL-адреса и заменяет его на уже имеющийся в локальном хранилище. - Уничтожьте iframe.
This об этом, токен обновлен. Поддерживайте работу наблюдателя и обновляйте его каждый раз, когда истекает срок его действия (делайте это за 5 минут до истечения срока его действия).
В качестве примера реализации компонента AccessToken в React большинство частей кода на самом деле будет работать, но вы нужно заменить константы на ваши вещи. Кроме того, некоторые функции, такие как extractTokenFromUrl
, отсутствуют, но сделать это достаточно легко:
import React, { Component } from 'react'
export class SilentTokenRenew extends Component {
constructor(props) {
super(props)
this.state = { renewing: false }
this.currentAttempt = 0
this.maxNumberOfAttempts = 20
}
shouldComponentUpdate(nextProps, nextState) {
return this.state.renewing !== nextState.renewing
}
componentDidMount() {
this.timeInterval = setInterval(this.handleCheckToken, 20000)
}
componentWillUnmount() {
clearInterval(this.timeInterval)
}
willTokenExpire = () => {
const token = YOUR_ACCESS_TOKEN_OBJECT // { accessToken, expirationTime }
const threshold = 300 // 300s = 5 minute threshold for token expiration
const hasToken = token && token.accessToken
const now = (Date.now() / 1000) + threshold
return !hasToken || (now > token.accessToken.expirationTime)
}
handleCheckToken = () => {
if (this.willTokenExpire()) {
this.setState({ renewing: true })
clearInterval(this.timeInterval)
}
}
silentRenew = () => {
return new Promise((resolve, reject) => {
const checkRedirect = () => {
// This can be e
const redirectUrl = localStorage[YOUR_REDIRECT_URL_FROM_THE_REDIRECT_HTML_FILE] // /redirect.html#access_token=......
if (!redirectUrl) {
this.currentAttempt += 1
if (this.currentAttempt > this.maxNumberOfAttempts) {
reject({
message: 'Silent renew failed after maximum number of attempts.',
short: 'max_number_of_attempts_reached',
})
return
}
setTimeout(() => checkRedirect(), 500)
return
}
// Clean up your localStorage for the next silent renewal
localStorage.removeItem(YOUR_REDIRECT_URL_FROM_THE_REDIRECT_HTML_FILE)
// Put some more error handlers here
// Silent renew worked as expected, lets update the access token
const session = extractTokenFromUrl(redirectUrl) // write some function to get out the access token from the URL
// Following your code you provided, here is the time to set
// the extracted access token back to your localStorage under a key Credentials.stateKey
localStorage.setItem(Credentials.stateKey, JSON.stringify(session))
resolve(session)
}
checkRedirect()
})
}
handleOnLoad = () => {
this.silentRenew()
.then(() => {
this.setState({ renewing: false })
this.currentAttempt = 0
this.timeInterval = setInterval(this.handleCheckToken, 60000)
// Access token renewed silently.
})
.catch(error => {
this.setState({ renewing: false })
// handle the errors
})
}
renderIframe = () => {
const url = new URL(YOUR_AUTHORIZE_URL_TO_TH_AUTH_SERVER)
url.searchParams.set('redirect_uri', 'http://localhost:3000/redirect.html') // the redirect.html file location
url.searchParams.set('prompt', 'none')
return (
<iframe
style={{ width: 0, height: 0, position: 'absolute', left: 0, top: 0, display: 'none', visibility: 'hidden' }}
width={0}
height={0}
title="silent-token-renew"
src={url.href}
onLoad={this.handleOnLoad}
/>
)
}
render() {
const { renewing } = this.state
return renewing ? this.renderIframe() : null
}
}
Пример кода для файла redirect.html
:
<!DOCTYPE html>
<html>
<head>
<title>OAuth - Redirect</title>
</head>
<body>
<p>Renewing...</p>
<script>
// Get name of window which was set by the parent to be the unique request key
// or if no parameter was specified, we have a silent renew from iframe
const requestKey = YOUR_REDIRECT_URL_FROM_THE_REDIRECT_HTML_FILE;
// Update corresponding entry with the redirected url which should contain either access token or failure reason in the query parameter / hash
window.localStorage.setItem(requestKey, window.location.href);
window.close();
</script>
</body>
</html>