Как сохранить сеансы на основе файлов cookie с помощью @ nuxtjs / auth-module? - PullRequest
0 голосов
/ 19 октября 2019

Я пытаюсь заставить 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()?

...