Laravel sanctum with Vue 3 API calls - laravel

I'm building an app, with Laravel backend and Vue3. Both apps are on different domains. I'm doing axios API calls from Vue. On Laravel I have Sanctum installed to handle my authorisation, login, etc... I tried a lot of stuff, from storing token to localStorage (not a good practice as it is not secured). So I read more, found out that I have to just send - withCredentials: true and it will handle everything with a cookie, out of the box. It does not work. Then I read that it does not work if they are on different domains. I'm not sure how to handle this anymore.
Is this all true? Is sanctum way to go?If not, what is the best way for secured auth? Will it work on same domains and is there a way to work with different domains?
Does anyone have an idea how to handle this?
Thank you!!!

having 2 domains doesn't change anything. The logic is very simple. basically you have a token (key) and you will communicate with this key. you will send the token to the client when the conditions are met. than after, client say "if this your token, give my credentials."
just use sanctum token:
$user->createToken($request->name)->plainTextToken;
than you return Bearer token if the conditions are met:
Authorization: Bearer <token>
and protect your route with sanctum middleware:
Route::middleware('auth:sanctum')->get('/user', function (Request $request)
finally if the key is correct:
return response($user, 200);

Related

How Laravel middleware auth:api detect token from cookie?

I just trying to makes my auth flow more secure using a cookie on Laravel 5.7
Here my code
/**
* auth logic
*/
return response()->json(["status" => "logged in"], 200)->cookie('token', $token, $lifetime);
Then the cookie will be saved on the browser and will be used on every request.
On header with Axios
"cookie":"token={token}"
And I validate the auth using default middleware
Route::group(['middleware' => ['auth:api']])
But the auth:api did not recognize it, I can make custom middleware by manually detect the cookie, but I can't use the auth()->user() function on it.
Is there any solution for this?
From your sample code I believe your app is built on a stateless architecture where you have your JavaScript client and laravel api.
Now I am a bit confused as to why you do not want the client storing the token, if you just want to escape cross site scripting vulnerability (XSS) then you have to prepare to deal with cross site request forgery (CSRF) if you store the token in the browsers cookie.
Regarding the middleware not being able to find the token, by default the middleware is configured to lookup tokens in the request header (specifically the Authorization header) so if you decide to store it in the cookie, you have to find a way to change the token lookup in the api middleware which unfortunately I have not done before in laravel.
APIs don't generally store and send cookies. Therefore the api token authentication guard will not look for the token in a cookie. There are multiple options you can send it as though the easiest one in axios:
{
headers: {
Authorization: `Bearer ${token}`
}
}

Laravel Sanctum auth:sanctum route allows access without bearer token

I am trying to protect API routes with a bearer token using Laravel Sanctum.
I have added the middleware correctly for the route as follows in api.php. The api/me route is set to return auth()->user();
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('/me', 'App\Http\Controllers\APIController#me');
});
To test this, I first login successfully and generate a bearer token, so that is working fine.
However, when I try to access the api/me route without the bearer token, it still displays the full user. It is not supposed to be allowing access to the route without a bearer token, why is it doing that?
I've searched for hours but no joy - does anyone have any insight?
I'm just guessing here.. Did you "EnsureFrontendRequestAreStateful" in kernel.php?
Because then Sanctum will use Session-Cookie based authentication. Sanctum will only use the bearer token if you authenticate third party apps, that don't run on your domain or subdomain.
If you don't want to use session-cookie based authentication for your SPA remove the "EnsureFrontendRequestsAreStateful" class from kernel.php.
Now Sanctum will always use the bearer token for authentication.

Sanctum SPA Authentication - web.php vs api.php

I am using Sanctum for SPA authentication. In several examples I have seen, people are creating auth routes (login, logout, register) in their web.php routes file as opposed to the api.php routes file. Is there a reason for this? In the documentation I do see a mention here...
You may be wondering why we suggest that you authenticate the routes
within your application's routes/web.php file using the sanctum guard.
Remember, Sanctum will first attempt to authenticate incoming requests
using Laravel's typical session authentication cookie. If that cookie
is not present then Sanctum will attempt to authenticate the request
using a token in the request's Authorization header. In addition,
authenticating all requests using Sanctum ensures that we may always
call the tokenCan method on the currently authenticated user instance
...but that is for API Token Authentication and not directly under SPA Authentication.
Is there any reason my auth routes would be better handled in web.php?
Well, in a typical Laravel application, your API routes are stateless and do not persist a session; specifically they do not have the start session middleware.
As such, cookie based authentication will not work if you put these routes in your API file.
Having these routes in your web file allows these specific routes to be wrapped in a session, allowing cookie based authentication and then falls back to using the stateless Authorization header if required.
I forget the exact words, but Taylor is quite a fan of SPAs using cookie based authentication when they're the same domain over API tokens.
But this should explain the reasoning. You are, of course, welcome to change this if you like.

Why does one Route fail and the other work?

I am using Laravel to serve both my website and a stateless API. I use Passport with a token set in the cookie to Authenticate the API, this is handled by Passport.
I make calls to the API using axios within vue.js
I was getting an issue with an API call that was returning Unauthorized, all other requests were fine, by playing around I have arrived at the finding that
this.$axios.get('session/'+this.session+'/posts')
.then(response => { console.log(response.data); });
Route::get('/session/{code}/posts' , 'PostController#posts');
works; whereas
this.$axios.get('session/posts')
.then(response => { console.log(response.data); });
Route::get('/session/posts' , 'PostController#posts');
does not (returns 401 Unauthorized).
In the first example the $code value is simply an obfuscated ID and is not related to authentication, it is a string of characters. Also, session refers to an internal Application object and is not related to the php session at all.
This is in my Routes service provider:
Route::prefix('api')
->middleware('auth:api')
->namespace($this->namespace.'\API')
->group(base_path('routes/api.php'));
This sets a token in a cookie (laravel_token by default), and uses that to authenticate.
Other routes are successfully authenticating through this, when I add the variable to the route, it works!
Can anyone explain to me why the second version gives an Unauthorized response?
It appears to be the auth:api guard that makes this distinction, but I don't know where in the Laravel framework the actual check() code is.
Kindly check if your routes where a part of a prefix that has the auth:guard api activated. whereas you need to send api generated token to gain authorization.

Is csrf enough for security when posting data to server via axios?

I use Laravel for a project. It is not a vue SPA, so no route used at all. The register, login and some other form inputs and outputs are made with modals using vue. For posting the form vars axios is used. For server side authentication laravels standard auth is used. But here is no other authentication like jwt. Should I use other auth types or would csrf be enough? Are there other suggestions?
Usually for web routes csrf token is enough secure or it has been so far. And it does:
Check if the request is a reading request (HEAD, GET, OPTIONS).
If so, skip the check. Match the token from the _token input or from the headers.
Add a cookie with the token to each request.
If you are using api routes then you can chose from Laravel passport which you can setup oAuth2 or you could build your own custom auth middleware using jwt tokens.

Resources