У меня есть приложение, которое использует стратегию спа из auth0 для аутентификации пользователей. Аутентификация сохраняется, пока у меня есть подключение к интернету, потому что я могу проверить, есть ли у пользователя isAuthenticated()
, когда он получает доступ к странице, требующей аутентификации. Если он не аутентифицирован, я пытаюсь обновить токен, который работает до тех пор, пока не истек срок действия его предыдущего токена, и я могу перенаправить его на нужную страницу. Если невозможно обновить токен, я прошу пользователя снова войти в систему. Так что это прекрасно работает, когда пользователь онлайн. Но так как я хотел бы также заставить его работать как pwa, обычно это означает, что я хотел бы, чтобы пользователь также мог использовать приложение, когда он находится в автономном режиме, я изо всех сил пытаюсь найти стратегию, чтобы сделать это возможным.
Есть ли у вас какие-либо предложения о том, какую стратегию использовать, если я хотел бы добавить эту автономную функциональность? Я думаю, что одним из способов было бы добавить дату истечения срока действия и затем idtoken в локальное хранилище, и просто решить, вошел ли пользователь в систему, основываясь на том, есть ли у него idtoken и истек ли его токен, но насколько я знаю, это плохая практика, поэтому я бы предпочел избежать этого.
Я использую vue и vue-router и проверяю перед каждым доступом к аутентифицированному маршруту, аутентифицирован ли пользователь следующим образом:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !auth.isAuthenticated()) {
auth.renewTokens()
.then(() => {
if (!auth.isAuthenticated()) {
next({ name: 'Index' })
} else {
next()
}
})
.catch(() => next({ name: 'Index' }))
} else {
next()
}
})
Вот мой текущий код authService.js:
import auth0 from 'auth0-js'
import EventEmitter from 'events'
import authConfig from './authConfig.json'
const webAuth = new auth0.WebAuth({
domain: authConfig.domain,
redirectUri: `${window.location.origin}/callback`,
clientID: authConfig.clientId,
responseType: 'id_token',
scope: 'openid profile email'
})
const localStorageKey = 'loggedIn'
const loginEvent = 'loginEvent'
class AuthService extends EventEmitter {
idToken = null;
profile = null;
tokenExpiry = null;
// Starts the user login flow
login (customState) {
webAuth.authorize({
appState: customState
})
}
// Handles the callback request from Auth0
handleAuthentication () {
return new Promise((resolve, reject) => {
webAuth.parseHash((err, authResult) => {
if (err) {
reject(err)
} else {
this.localLogin(authResult)
resolve(authResult.idToken)
}
})
})
}
localLogin (authResult) {
this.idToken = authResult.idToken
this.profile = authResult.idTokenPayload
// Convert the JWT expiry time from seconds to milliseconds
this.tokenExpiry = new Date(this.profile.exp * 1000)
localStorage.setItem(localStorageKey, 'true')
this.emit(loginEvent, {
loggedIn: true,
profile: authResult.idTokenPayload,
state: authResult.appState || {}
})
}
renewTokens () {
return new Promise((resolve, reject) => {
if (localStorage.getItem(localStorageKey) !== 'true') {
return reject(new Error('Not logged in'))
}
webAuth.checkSession({}, (err, authResult) => {
if (err) {
reject(err)
} else {
this.localLogin(authResult)
resolve(authResult)
}
})
})
}
logout () {
localStorage.removeItem(localStorageKey)
this.idToken = null
this.tokenExpiry = null
this.profile = null
webAuth.logout({
returnTo: window.location.origin
})
this.emit(loginEvent, { loggedIn: false })
}
isAuthenticated () {
return (
Date.now() < this.tokenExpiry &&
localStorage.getItem(localStorageKey) === 'true'
)
}
}
export default new AuthService()