检查 Laravel Sanctum 的 CSRF 令牌在 Nuxt 3 中的可组合性。

huangapple go评论47阅读模式
英文:

Composable for checking Laravel Sanctum's CSRF token in Nuxt 3

问题

I'm working on a Nuxt 3 app with Laravel 9 as API with Sanctum and Fortify.

I wrote a composable to check the response to the Laravel Sanctum's CSRF token HTTP route '(/sanctum/csrf-cookie)' and I'm trying to check if it's working by logging via 'console.log()' the composable's state, but it always shows an empty Proxy received as error.

Please help, what am I doing wrong?

Here is what I've done so far:

The composable: 'auth.ts' :

export function useCsrfToken() {
  const baseURL = useRuntimeConfig().public.LARAVEL_BASE_URL
  const options = {
    baseURL,
    credentials: 'include',
    headers: {
      Accept: 'application/json',
    } as HeadersInit,
    method: 'GET',
  }

  const state = ref({
    status: '',
    error: {},
  })

  async function getCsrfToken() {
    state.value.error = {}
    state.value.status = '';
    await $fetch('/sanctum/csrf-cookie', options)
      .then(() => (state.value.status = 'ok'))
      .catch((error) => {
        console.log('error from useCsrfToken', error)
        state.value.error = { error }
      })
  }

  getCsrfToken()

  return { state }
}

The login Nuxt page, where I'm using the above composable :

<script setup>
definePageMeta({
  layout: false,
})

const submit = () => {
  form.processing = true
  const { state } = useCsrfToken()

  console.log('error from login', state.value.error)
}

const form = reactive({
  email: '',
  password: '',
  remember: false,
  processing: false,
  errors: {},
})
</script>

<template>
  <div>
    <!-- <TheTwoFactorChallenge v-if="verification" @2fapassed="submit" /> -->
    <NuxtLayout name="auth">
      <template #title>
        <p class="card-header-title">Inicie Sesión</p>
      </template>

      <form novalidate @submit.prevent="submit">
        <div class="field">
          <label class="label" for="email">Usuario</label>
          <div class="control has-icons-left has-icons-right">
            <AppInput
              type="email"
              id="email"
              v-model="form.email"
              :error="form.errors?.email"
              autocomplete="email"
              required
            />
            <AppIconLeft icon="fa-solid fa-envelope" />
            <AppIconError v-if="form.errors?.email" class="is-right" />
          </div>
          <AppHelpError :errors="form.errors?.email" />
        </div>

        <div class="field">
          <label class="label" for="password">Contraseña</label>
          <div class="control has-icons-left has-icons-right">
            <AppInput
              type="password"
              id="password"
              v-model="form.password"
              :error="form.errors?.password"
              autocomplete="new-password"
              required
            />
            <AppIconLeft icon="fa-solid fa-lock" />
            <AppIconError v-if="form.errors?.password" class="is-right" />
          </div>
          <AppHelpError :errors="form.errors?.password" />
        </div>

        <div class="field">
          <div class="control">
            <AppSwitch
              id="remember"
              v-model:checked="form.remember"
              class="is-small is-link"
            />
            <label for="remember">Recuérda me</label>
          </div>
        </div>

        <div class="is-flex is-justify-content-flex-end mb-4">
          <NuxtLink to="#">¿Olvidó su contraseña?</NuxtLink>
        </div>

        <div class="field">
          <div class="control">
            <AppButton
              class="is-link is-fullwidth"
              type="submit"
              :is-loading="form.processing"
            >Entrar</AppButton>
          </div>
        </div>
      </form>
    </NuxtLayout>
  </div>
</template>

And here are the outputs:

检查 Laravel Sanctum 的 CSRF 令牌在 Nuxt 3 中的可组合性。

英文:

I'm working on a Nuxt 3 app with Laravel 9 as API with Sanctum and Fortify.

I wrote a composable to check the response to the Laravel Sanctum's CSRF token HTTP route (&#39;/sanctum/csrf-cookie&#39;) and I'm trying to check if it's working by logging via console.log() the composable's state, but it always shows an empty Proxy received as error.

Please help, what am I doing wrong?

Here is what I've done so far:

The composable: auth.ts :

export function useCsrfToken() {
  const baseURL = useRuntimeConfig().public.LARAVEL_BASE_URL
  const options = {
    baseURL,
    credentials: &#39;include&#39;,
    headers: {
      Accept: &#39;application/json&#39;,
    } as HeadersInit,
    method: &#39;GET&#39;,
  }

  const state = ref({
    status: &#39;&#39;,
    error: {},
  })

  async function getCsrfToken() {
    state.value.error = {}
    state.value.status = &#39;&#39;
    await $fetch(&#39;/sanctum/csrf-cookie&#39;, options)
      .then(() =&gt; (state.value.status = &#39;ok&#39;))
      .catch((error) =&gt; {
        console.log(&#39;error from useCsrfToken&#39;, error)

        state.value.error = { error }
      })
  }

  getCsrfToken()

  return { state }
}

The login Nuxt page, where I'm using the above composable :

&lt;script setup&gt;
definePageMeta({
  layout: false,
})

const submit = () =&gt; {
  form.processing = true
  const { state } = useCsrfToken()

  console.log(&#39;error from login&#39;, state.value.error)
  // console.log(&#39;status from login&#39;, status)
}

const form = reactive({
  email: &#39;&#39;,
  password: &#39;&#39;,
  remember: false,
  processing: false,
  errors: {},
})
&lt;/script&gt;

&lt;template&gt;
  &lt;div&gt;
    &lt;!-- &lt;TheTwoFactorChallenge v-if=&quot;verification&quot; @2fapassed=&quot;submit&quot; /&gt; --&gt;
    &lt;NuxtLayout name=&quot;auth&quot;&gt;
      &lt;template #title&gt;
        &lt;p class=&quot;card-header-title&quot;&gt;Inicie Sesi&#243;n&lt;/p&gt;
      &lt;/template&gt;

      &lt;form novalidate @submit.prevent=&quot;submit&quot;&gt;
        &lt;div class=&quot;field&quot;&gt;
          &lt;label class=&quot;label&quot; for=&quot;email&quot;&gt;Usuario&lt;/label&gt;
          &lt;div class=&quot;control has-icons-left has-icons-right&quot;&gt;
            &lt;AppInput
              type=&quot;email&quot;
              id=&quot;email&quot;
              v-model=&quot;form.email&quot;
              :error=&quot;form.errors?.email&quot;
              autocomplete=&quot;email&quot;
              required
            /&gt;
            &lt;AppIconLeft icon=&quot;fa-solid fa-envelope&quot; /&gt;
            &lt;AppIconError v-if=&quot;form.errors?.email&quot; class=&quot;is-right&quot; /&gt;
          &lt;/div&gt;
          &lt;AppHelpError :errors=&quot;form.errors?.email&quot; /&gt;
        &lt;/div&gt;

        &lt;div class=&quot;field&quot;&gt;
          &lt;label class=&quot;label&quot; for=&quot;password&quot;&gt;Contrase&#241;a&lt;/label&gt;
          &lt;div class=&quot;control has-icons-left has-icons-right&quot;&gt;
            &lt;AppInput
              type=&quot;password&quot;
              id=&quot;password&quot;
              v-model=&quot;form.password&quot;
              :error=&quot;form.errors?.password&quot;
              autocomplete=&quot;new-password&quot;
              required
            /&gt;
            &lt;AppIconLeft icon=&quot;fa-solid fa-lock&quot; /&gt;
            &lt;AppIconError v-if=&quot;form.errors?.password&quot; class=&quot;is-right&quot; /&gt;
          &lt;/div&gt;
          &lt;AppHelpError :errors=&quot;form.errors?.password&quot; /&gt;
        &lt;/div&gt;

        &lt;div class=&quot;field&quot;&gt;
          &lt;div class=&quot;control&quot;&gt;
            &lt;AppSwitch
              id=&quot;remember&quot;
              v-model:checked=&quot;form.remember&quot;
              class=&quot;is-small is-link&quot;
            /&gt;
            &lt;label for=&quot;remember&quot;&gt;Recu&#233;rdame&lt;/label&gt;
          &lt;/div&gt;
        &lt;/div&gt;

        &lt;div class=&quot;is-flex is-justify-content-flex-end mb-4&quot;&gt;
          &lt;NuxtLink to=&quot;#&quot; class=&quot;has-text-link&quot;&gt;
            &#191;Olvid&#243; su contrase&#241;a?
          &lt;/NuxtLink&gt;
        &lt;/div&gt;

        &lt;div class=&quot;field&quot;&gt;
          &lt;div class=&quot;control&quot;&gt;
            &lt;AppButton
              class=&quot;is-link is-fullwidth&quot;
              type=&quot;submit&quot;
              :is-loading=&quot;form.processing&quot;
              &gt;Entrar&lt;/AppButton
            &gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    &lt;/NuxtLayout&gt;
  &lt;/div&gt;
&lt;/template&gt;

And here are the outputs :
检查 Laravel Sanctum 的 CSRF 令牌在 Nuxt 3 中的可组合性。

答案1

得分: 1

自Nuxt3提供了一个Server函数,可以用作API,因此很容易与Laravel混淆。

你可能需要添加一个proxy_pass(如果你使用Nginx)来区分Nuxt和Laravel的请求,以便在Nuxt和Laravel之间共享相同的来源(以避免在Same-Origin-Policy上浪费时间)。

例如:

http://example.com/ // -&gt; nuxt
http://example.com/api/ // -&gt; laravel

(由于你说你在使用Docker,我将假设你正在使用laravel sail)

  • 首先,为您的站点添加一个域名(例如http://example.test),而不是http://localhost
  • 自定义/sanctum/csrf-cookie路由为/api/sanctum/csrf-cookie(您可以在这里看到如何更改laravel sanctum csrf cookie路由
  • 在Nginx配置中为http://example.test/api/*添加一个proxy_pass
location ~* ^/(api|broadcasting|storage)/ {
    proxy_pass http://localhost:8080; // 您的laravel运行的地方
}

但是,在我的观点中,SSR Nuxt应该被视为一个客户端,与Android应用程序或iOS应用程序一样,因为前端和后端与以前将前端代码和后端代码放在同一个项目中相比是完全不同的项目。

因此,你可以像对待Android应用一样对待web,而不是启用CRSF保护。

这是一个Nuxt3 + Laravel的完整示例,使用了Laravel Sanctum并且具有授权功能。 👉 Laravel + SSR Nuxt3 with authorizations

英文:

Since Nuxt3 provides a Server function which could use as an API, it could be easily confused with Laravel.

You may need to add a proxy_pass (if you use Nginx) to distinguish between Nuxt and Laravel requests in order to share the same origin between Nuxt and Laravel (to avoid wasting a second on Same-Origin-Policy )

For example:

http://example.com/ // -&gt; nuxt
http://example.com/api/ // -&gt; laravel

(Since you said you are using Docker, I'm going to assume you're using laravel sail)

  • First, add a domain (for example http://example.test) for your site instead of http://localhost.
  • Custom the /sanctum/csrf-cookie route to /api/sanctum/csrf-cookie (here you can see how to change laravel sanctum csrf cookie route)
  • Add a proxy_pass for http://example.test/api/* in Nginx configs:
location ~* ^/(api|broadcasting|storage)/ {
    proxy_pass http://localhost:8080; // where your laravel running
}

But, in my view, the SSR Nuxt should be considered as a client just equal to an Android app or IOS app, because the frontend and the backend are entire two different projects compared with the previous time when putting your frontend code and backend code in the same project.

So, you may auth the web just like auth the Android app, instead of booting the CRSF protection.

And here is a full example of Nuxt3 + Laravel, which is using Laravel Sanctum and also SSR with authorizations. 👉 Laravel + SSR Nuxt3 with authorizations

huangapple
  • 本文由 发表于 2023年2月10日 02:40:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75403061.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定