Я пытаюсь заставить Nuxt Auth работать с JWT_Sessions Ruby gem, как показано здесь : точка входа /login
отправляет обратно токен доступа в виде файла cookie не-HttpOnly и токен CSRF в ответетело. Когда токен истекает, вы можете отправить оба этих токена на конечную точку /refresh
, чтобы получить новую пару.
nuxt.config.js
auth: {
plugins: [ '~/plugins/auth.js', '~/plugins/axios' ],
strategies: {
jwtSessions: {
_scheme: '~/plugins/auth-jwt-sessions.js',
endpoints: {
login: { url: '/login', method: 'post', propertyName: false },
logout: { url: '/logout', method: 'post' },
user: { url: '/me', method: 'get', propertyName: false }
},
tokenRequired: false,
tokenType: false
}
},
~ / plugins / auth-jwt-sessions.js
...
async login (endpoint) {
// Ditch any leftover local tokens before attempting to log in
await this._logoutLocally()
const result = await this.$auth.request(
endpoint,
this.options.endpoints.login
)
if (result.csrf){
this.$auth.$storage.setUniversal("csrf_token", result.csrf)
console.log("sucessfully set up CSRF token " + this.$auth.$storage.getUniversal("csrf_token"));
}
return this.fetchUser()
}
...
~ / plugins / axios.js
export default function ({$auth, $axios, redirect}) {
$axios.onRequest(config => {
var csrf = $auth.$storage.getUniversal('csrf_token')
if ($auth.$state.loggedIn && csrf){
config.headers['X-CSRF-TOKEN'] = csrf
}
})
$axios.onResponseError(async error => {
var response = error.response
if($auth.$state.loggedIn && response.status === 401 && response.request._retry != true) {
const originalRequest = response.config
originalRequest._retry = true
const newToken = await $axios.post('/refresh').then(response => {
console.log(response);
return response.data.csrf
}).catch(response => {
console.log(response);
})
if(newToken) {
$auth.$storage.setUniversal('csrf_token', newToken)
originalRequest.headers['X-CSRF-TOKEN'] = newToken
return $axios(originalRequest)
} else {
redirect(301, '/login')
}
} else {
return Promise.reject(error)
}
});
}
Приведенный выше код работаетдо тех пор, пока вам не понадобится перезагрузить / открыть страницу после истечения срока действия маркера доступа.
Поскольку по какой-то причине мои перехватчики $ axios не работают во время инициализации стратегии (кстати, почему?), мне пришлось добавитьОбновление подпрограммы для функции стратегии mounted
на клиенте, как показано ниже.
~ / plugins / auth-jwt-sessions.js
...
mounted () {
if (this.options.tokenRequired) {
const token = this.$auth.syncToken(this.name)
this._setToken(token)
}
this.$auth.$storage.syncUniversal('csrf_token')
if (process.client) {
let csrf = this.$auth.$storage.getUniversal('csrf_token')
if (csrf) {
console.log("recovering CSRF token from Universal Storage");
this.$auth.ctx.app.$axios.setHeader('X-CSRF-TOKEN', csrf)
var newToken = null
this.$auth.ctx.app.$axios.post('/refresh').then(response => {
console.log(response.data);
newToken = response.data
this.$auth.$storage.setUniversal('csrf_token', newToken.csrf)
this.$auth.ctx.app.$axios.get('/me', {}, {
headers: {'X-CSRF-TOKEN': newToken.csrf},
withCredentials: false
}).then(response => {
console.log(this.$auth.$state);
this.$auth.setUser(response.data)
}).catch(response => {
console.log(response);
})
})
}
}
return this.$auth.fetchUserOnce()
}
...
async fetchUser (endpoint) {
// Token is required but not available
if (this.options.tokenRequired && !this.$auth.getToken(this.name)) {
return
}
// the headers need to be configured here once again, the axios config doesn't get persisted
this.$auth.ctx.app.$axios.setHeader('X-CSRF-TOKEN', this.$auth.$storage.getUniversal("csrf_token"))
// User endpoint is disabled.
if (!this.options.endpoints.user) {
this.$auth.setUser({})
return
}
// Try to fetch user and then set
const user = await this.$auth.requestWith(
this.name,
endpoint,
this.options.endpoints.user
)
this.$auth.setUser(user)
}
...
Кажетсячтобы работать, но когда я позволяю своему токену доступа истечь, а затем перезагружаю приложение, я на несколько секунд перенаправляюсь на /login
, а затем сеанс восстанавливается, и меня перенаправляют на начальный маршрут.
1) Является ли это правильным способом для создания потока обновления на основе файлов cookie в Nuxt?
2) Как избежать многократного повторного использования? восстанавливает время восстановления сеанса во время mounted()
?