Using Laravel sail share (Expose) with Jetstream + Inertia + Sanctum - laravel

I'm running into a problem using sail share with a Laravel 9.x application using Jetstream + Inertia and Sanctum.
I'm able to load my login screen at the XXXXXX.laravel-sail.site/login URL. However, I'm not able to actually login to the application.
I can see the login form post in Expose dashboard, but there is either never a response, or a 419 Page Expired error occurs (depending on which settings I'm trying, more on that below).
My local site APP_URL is set to http://localhost. The information generated by Expose is:
Shared URL: host.docker.internal:80
Dashboard: http://127.0.0.1:4040
Public HTTP: http://XXXXXXXXX.laravel-sail.site:8080
Public HTTPS: https://XXXXXXXXX.laravel-sail.site
I'm using the Public HTTP URL to access the login. The Public HTTPS URL generates ERR_CONNECTION_REFUSED.
Here is what I have tried:
Set SANCTUM_STATEFUL_DOMAINS and SESSION_DOMAIN to the Public URL in .env (This produces the 419 error). I also tried localhost but never received the POST response at login. Also tried with and without the port on SANCTUM_STATEFUL_DOMAINS.
Changed SESSION_DRIVER from database to cookie (same 419 error).
Changed 'supports_credentials' to true in config/cors.php.
Uncommented \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class in Kernel.php
Set $proxies to protected $proxies = '*'; in TrustProxies.php
Does anyone know what I'm missing?
Thanks,
Tim

Related

Laravel basic auth redirects to HTTPS route after login

I added laravel’s built-in authentication to an existing project. This is a local project without certificates.
After login I was redirected to the dashboard page but chrome showed an “ERR_SSL_PROTOCOL_ERROR” message. I looked into it for a couple of hours and I found that the dashboard's page was opening as HTTPS, when I changed the url to HTTP It showed the dashboard page. For some reason the auth’s routes are being redirected to the site as HTTPS.
I'm new to laravel and I don't understand what’s happening.
I did some reverse engineering and found that in my AppServiceProvider were the configurations that redirected my routes to HTTPS.
Load Blade assets with https in Laravel

Chrome not allowing Set-Cookie even from the same (sub)domain

Here is my configuration:
SERVER
Laravel 8 application that uses Sanctum to provide access to REST API. It is configured to run on http://b8/
CLIENT
A separate Vue CLI 3.0 SPA that connects to the API using session-based cookie authentication method. I have configured Vue CLI Serve to run it at http://app.b8/.
PROBLEM
Chrome does not allow Set-Cookie operation even when both server and client are on the same domain. After going through several posts and articles, I have successfully run it in Postman, but the real Vue application that runs in the browser can't set Sanctum cookie and thus cannot login.
Here is my configuration:
.env
SESSION_DRIVER=cookie
SESSION_DOMAIN=.b8
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:8080,127.0.0.1,127.0.0.1:8000,::1,b8,app.b8,app.b8:8080
vue.config.js
...
devServer: {
proxy: "http://b8/api/v1",
host: "app.b8"
},
Login function in Vue application
async login(context, credentials) {
axios.get('http://b8/sanctum/csrf-cookie').then(response => {
axios.post('http://b8/login', credentials).then(response2 => {
//successfully logged in.
});
});
},
Error msg
The outer call for /sanctum/csrf-cookie route returns successfully and brings Sanctum cookie. However, Chrome thinks that the cookie is invalid for the current domain and therefore doesn't set it. Here is the Dev Tools pane's Cookies tab after the Sanctum token call returns (tooltip showing Chrome's complaint):
Since the cookie is not set, the following login call fails with a 419 error.
What am I missing here?
Finally got it working. For any future reader, here are the things:
The first mistake that I was doing was to use a single word host name. It looks like Chrome (or Sanctum, not sure) wants you to have at least one period in the host name. So I changed it from b8 to b8.cod.
You should keep same_site attribute set to lax. none is a rather dangerous value. Chrome now shows none as a potential issue.
SESSION_DOMAIN should be set to .b8.cod with a leading period to support front-end subdomain, as correctly suggested by the documentation.
All other things should be done as suggested in the question. axios must use withCredentials set to true.
I've recently set up the exact same thing (Laravel 8 backend with Sanctum + separate Vue Frontend) and it's working.
Your server side setup looks good. Please double-check that the frontend's IP is actually included in your SANCTUM_STATEFUL_DOMAINS - that caused the 419 error for me sometimes.
On the Vue side, make sure to that you enable the withCredentials in your axios instance, e.g.
const baseDomain = "http://localhost"
const baseURL = `${baseDomain}/api`
export default axios.create({
baseURL,
withCredentials: true,
})
If the provided suggestion does not help, I can further extend my answer by showing you more of my working backend code.

Laravel Sanctum returns 401

I try to access my Laraval API from my Vue SPA but everytime I do a request I get a 401 Unauthorized. I have tried the answers from multiple SO questions but nothing works.
I added the EnsureFrontendRequestsAreStateful to the API middleware.
I set the Valet domain that I use for SANCTUM_STATEFUL_DOMAINS=goya.app.
I set the session envs:
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_DOMAIN=.goya.app
In Vue I have axios.defaults.withCredentials enabled.
In the request headers I see that the XSRF token is sent.
What else can I try to fix this?

Laravel returns unauthorized with second request

I'm trying to create SPA. I use Laravel API for backend and Nuxt.js for frontend. I want to authenticate users via Laravel Sanctum. I run backend on localhost:8000 and frontend on localhost:3000. SANCTUM_STATEFUL_DOMAINS is set to localhost:3000, SESSION_DOMAIN is set to localhost and SESSION_DRIVER is set to cookie.
I created login and logout in my app and everything works great until I make first request after logging in. I just wanted my app to return all users:
Route::middleware('auth:sanctum')->get('/users', function() { return User::all(); });
but it returns 401 unauthenticated. I don't know why is that happening. The route used for returning logged in user uses the same middleware:
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
and works perfectly (Nuxt returns logged in user with every page change). I called users route with axios:
axios.get('http://localhost:8000/api/users')
What can cause this problem? This is very frustrating because I struggled a lot just to get the login and logout working.
I also thought about running API on api.domain.test and frontend on domain.test but is it possible to hook up a domain like that to Nuxt locally?
It returns unauthorized because the call to the endpoint doesn't have access token of the user.
The idea is that when you login auth:sanctum returns access token to the client so that it can use it to access the data in all of it's next calls.
To do that you need to use authentication module in nuxt check this
The problem you are going to face next is that SPA doesn't have middleware so you need to set your app as universal instead of spa to be able to use the middleware in the client side

Deploy Laravel with Sanctum into Heroku - CSRF token mismatch

I developed a Laravel+Vue with Sanctum and deployed. On localhost works fine, I can login with my Vue form or with Laravel UI. In Heroku I get a CSRF Token mismatch error if I try to login with my Vue form; if I login with Laravel UI I get a 419 error page.
What I can note is that on my Heroku's app I haven't got any XSRF_TOKEN in my cookies, but in my localhost I have. I tried changing session driver from file to database driver as I read that in Heroku file driver doesn't work fine because of its storage system, with the same results (CSRF Token mismatch and not XSRF-TOKEN).
I also tried with http and https.
app/Http/Kernel.php in protected $middlewareGroups
// \App\Http\Middleware\VerifyCsrfToken::class,

Resources