manchenkoff / nuxt-auth-sanctum

Nuxt module for Laravel Sanctum authentication
https://manchenkoff.gitbook.io/nuxt-auth-sanctum/
MIT License
169 stars 21 forks source link

[Help needed] After login, user does not persist. What I'm doing wrong? #122

Closed rafailml closed 3 months ago

rafailml commented 4 months ago

I'm using "nuxt-auth-sanctum": "^0.4.2", with Laravel 11.08 and Sanctum 4.02. I have two docker containers, one for Nuxt 8.3.1 and one for Laravel.

I'm able to log in user with:

await login(credentials)

Then I'm redirected to index page which is behind auth middleware:

middleware: ['sanctum:auth']

I'm able to see logged in user in index page:

const { user } = useSanctumAuth<User>()
console.log(user)

Also I can see matching requests in Laravel Telescope. I can see authenticated user in Laravel. But, after I hit refresh, when I'm on my index page, I'm redirected back to login page. Which means that user is not authenticated. Reading src/runtime/middleware/sanctum.auth.ts there are:

if (isAuthenticated.value === true) {
        return;
}

So, somehow user is not authenticated ?!?!?

Returning back to index page, I'm redirected to login. In Docker logs I see:

[nuxt-auth-sanctum:ssr]  ERROR  Unable to load user identity from API [GET] "http://localhost:8004/api/user": <no response> fetch failed

Digging deeper, I found that this comes from src/runtime/plugin.ts:

try {
            logger.debug('Fetching user identity on plugin initialization');
            user.value = await client(options.endpoints.user);
        } catch (error) {
            handleIdentityLoadError(error as Error, logger);
        }

But there is nothing in Teleport. So it seams that this does not hit Laravel at all. I found similar problem here: #57 but It does not help. But when I turn SSR off it works.

What I'm doing wrong?

My nuxt.config.ts:

const sanctumConfig = {
  baseUrl: 'http://localhost:8004', 
  origin: 'http://localhost:3004', 
  mode: 'cookie',
  endpoints: {
    login: '/api/login',
    logout: '/api/logout',
    user: '/api/user',
  },
  redirect: {
    onAuthOnly: '/auth/login',
    onGuestOnly: '/',
    onLogout: '/auth/login',
    onLogin: '/',
    keepRequestedRoute: true,
  },
  logLevel: 5,
}

export default defineNuxtConfig({
  // ssr: false,
  devtools: { enabled: true },
  modules: [
    '@nuxt/test-utils/module',
    'nuxt-auth-sanctum',
  ],
  sanctum: sanctumConfig,
}
manchenkoff commented 4 months ago

Hey @rafailml, I assume you have SSR mode enabled according to what you posted in the description. So, once you hit refresh, Nuxt tries to send a request to your Laravel application, which is not available from the Docker container on localhost:8004, but it is available under the container name (usually laravel.test when you use Sail).

In your case, you should use actual domain instead of localhost referring, I also posted more details about here

rafailml commented 3 months ago

Ok, here is my docker-compose.yaml for Laravel side:

name: site_api

services:
    site_app:
        build:
            context: .
            dockerfile: docker/Dockerfile
            target: dev
        entrypoint: php artisan octane:frankenphp --max-requests=1 --port=8000
        ports:
            - 8004:8000
        volumes:
            - .:/app
        networks:
            - dockernet
networks:
    dockernet:

Here is my Nuxt docker-compose.yaml:

name: site_front

services:
  site_node:
    container_name: site_front
    ports:
      - '3004:3000'
    build:
      context: .
      target: dev
      dockerfile: docker/Dockerfile
    environment:
      HOST: 0.0.0.0
    stdin_open: true
    tty: true
    volumes:
      - ./:/app
      - node_modules:/app/node_modules
    networks:
      - dockernet
volumes:
  node_modules:
networks:
  dockernet:

Now my nuxt.config.ts looks like:

const sanctumConfig = {
  baseUrl: 'http://site_app', // Laravel base URL
  origin: 'http://localhost:3004', // Nuxt base URL
  mode: 'cookie',
  endpoints: {
    login: '/api/login',
    logout: '/api/logout',
    user: '/api/user',
  },
  redirect: {
    onAuthOnly: '/auth/login',
    onGuestOnly: '/',
    onLogout: '/auth/login',
    onLogin: '/',
    keepRequestedRoute: true,
  },
  logLevel: 5,
}

In my /etc/hosts file I have:

127.0.0.1       site_api-site_app
::1             site_api-site_app
127.0.0.1       site_app
::1             site_app

but I'm getting same result:

[nuxt-auth-sanctum:ssr]  ERROR  Unable to load user identity from API [GET] "http://site_app/api/user": <no response> fetch failed

setting

baseUrl: 'http://site_app:8004',

gives the same result. Also:

baseUrl: 'http://site_api-site_app',
or
baseUrl: 'http://site_api-site_app:8004',
manchenkoff commented 3 months ago

Hey @rafailml, the error message you got means that there is no server running on this address or it is not available in the docker network

Unable to load user identity from API [GET] "http://site_app/api/user": fetch failed

Can you check that both containers are visible to each other? For example, you can ping them from the inner bash/sh

rafailml commented 3 months ago

Yes, I can ping both:

node@b8acbfe782bb:/app$ ping site_app
PING site_app(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from localhost (::1): icmp_seq=2 ttl=64 time=0.096 ms

also

laravel@683c7625fabd:/app$ ping site_node
PING site_node(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.361 ms
64 bytes from localhost (::1): icmp_seq=2 ttl=64 time=0.188 ms
64 bytes from localhost (::1): icmp_seq=3 ttl=64 time=0.265 ms

but still getting that error

manchenkoff commented 3 months ago

Hey @rafailml, I see, that's weird. Looks like the Nuxt docker image still cannot access the other container during SSR requests, you can try to write some basic useFetch('http://site_app') request to debug this on SSR side, for example during page load or any middleware.

I believe that the problem is not related to the module itself, but feel free to create a minimal repro with your docker setup, then I will be able to help.

rafailml commented 3 months ago

Hey @manchenkoff, you are right, the problem was not related to nuxt-auth-sanctum, but to my docker configuration. What I changed to work? I put both containers in same network. More information here. There is no need to edit /etc/hosts in this case. Then changed:

baseUrl: 'http://site_app:8000'

8000 is my internal port! Not 8004 which is external.
And now it works. Thanks for your time and sorry for the question that is not related to this wonderful module. I'm closing this ticket.

rafailml commented 3 months ago

Fixed