Laravel вход в систему для социальных сетей работает в Quasar SPA, но не в режиме SSR - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь реализовать вход в Google в моем веб-приложении. Я использую Laravel пакет Socialite в бэкэнде. Проблема в том, что он работает в режиме SPA, но не работает в режиме SSR.

Поток моего входа в Google:

  1. Метод "googleLoginRedirect" вызывается на q- btn click.
  2. В ответ я получаю URL-адрес перенаправления Google от API, который я затем просто посещаю с помощью "window.location.href"
  3. Браузер переводит пользователя на страницу входа в Google.
  4. Пользователь входит в систему, используя учетные данные Google.
  5. Затем Google перенаправляет пользователя на URL-адрес обратного вызова. (URL-адрес обратного вызова состоит из уникального кода в параметрах, который может использоваться только один раз для получения сведений о пользователе)
  6. Используя метод "googleLoginCallback", я отправляю код из URL-адреса в качестве параметра бэкэнд-API, используя ax ios.
  7. В серверной части API социальной сети извлекает информацию о пользователе с помощью этого уникального кода и создает нового пользователя, если он еще не существует.
  8. Затем API возвращает токен.
  9. Установить маркер в поваре ie.
  10. Войти пользователя на панель управления.

Наблюдение:

  1. The вышеуказанный поток успешно работает при запуске приложения квазар в режиме SPA.
  2. На шаге 6 топор ios успешно отправляет код в API, НО во время работы в режиме SSR, API Socialite отвечает «400 Неверный запрос: этот код авторизации был использован. "

Я новичок в концепции SSR, поэтому я могу сказать, что это наивно, но запрос ax ios вызывается два раза? Как во второй раз с сервера узла? потому что уникальный код, отправленный Google, может быть использован только один раз. Пожалуйста, любые данные по этому вопросу ценны для меня.

// pages/login.vue
<template>
  <q-btn @click="googleLoginRedirect" icon="lab la-google" />
</template>

<script>
export default {
  methods: {
    googleLoginRedirect () {
      return new Promise((resolve, reject) => {
        this.$axios.get('/api/login/google')
          .then((response) => {
            resolve(response)
            if (response.data.url) {
              window.location.href = response.data.url
            }
          })
          .catch((error) => {
            reject(error)
          })
      })
    }
  }
}
</script>
// pages/please-wait.vue
<template>
  <p> Please wait while we are logging you with google </p>
</template>

<script>
export default {
  methods: {
    googleLoginCallback () {
      return new Promise((resolve, reject) => {
        this.$axios.get('/api/login/google/callback', { params: { code: this.$route.query.code } })
          .then((response) => {
            if (response.data.token) {
              resolve(response)
              this.$q.cookies.set('token', response.data.token)
              this.$store.commit('user/setLoggedIn', true)
              this.$router.push({ name: 'dashboard' })
              this.$q.notify({ type: 'positive', message: 'Login Success' })
            }
          })
          .catch((error) => {
            reject(error)
            this.$router.push({ name: 'login' })
            this.$q.notify({ type: 'negative', message: 'Failed to login for some reason' })
          })
      })
    }

  },
  created () {
    this.googleLoginCallback()
  }
}
</script>

Вот как выглядит мой загрузочный файл ios axe

// boot/axios.js
import Vue from 'vue'
import axios from 'axios'
import { Cookies } from 'quasar'

Vue.mixin({
  beforeCreate () {
    const options = this.$options
    if (options.axios) {
      this.$axios = options.axios
    } else if (options.parent) {
      this.$axios = options.parent.$axios
    }
  }
})

export default function ({ app, store, router, ssrContext }) {
  const axiosInstance = axios.create({
    baseURL: 'http://localhost:8000'
  })

  const cookies = process.env.SERVER
    ? Cookies.parseSSR(ssrContext)
    : Cookies

  axiosInstance.interceptors.request.use(function (config) {
    const token = cookies.get('token')
    if (token) {
      config.headers.common.Authorization = `Bearer ${token}`
    }
    return config
  }, function (error) {
    return Promise.reject(error)
  })

  app.axios = axiosInstance
  store.$axios = axiosInstance
  router.$axios = axiosInstance
}

...