Laravel Sanctum Vue SPA CORS issue - laravel

I've setup a VUE frontend which connects and authenticates perfectly well with a Laravel backend, using sanctum. I'm able to login and successfully retrieve the logged in user by visiting /api/user. I believe I've followed all the config steps stated in the documentation.
Here is sanctum.php config for stateful domains:
'stateful' => explode(
',',
env(
'SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:3000,localhost:8080,127.0.0.1,127.0.0.1:8080,::1'
)
), //this is what is in my env SANCTUM_STATEFUL_DOMAINS=app.foo-bar.test:8080
//my laravel backend is running on foo-bar.test
Here is my session.php config:
'domain' => env('SESSION_DOMAIN', null), //in my .env I have: SESSION_DOMAIN=.foo-bar.test
I have the sanctum middleware setup in http/kernel.php, and I'm using auth:sanctum in my routes
Here is my cors.php config:
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
and in my vue frontend, I've configured axios to use the following
axios.defaults.baseURL = 'http://foo-bar.test';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
axios.defaults.withCredentials = true;
As I mentioned, I'm able to successfully login, and even visit /api/user. All works fine,
But when I make a post request to: api/users/multiple,
I get the CORS error: Access to XMLHttpRequest at 'http://foo-bar.test/api/users/multiple' from origin 'http://app.foo-bar.test:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I'm out of ideas, as it seems I've done all the necessary config. Perhaps I'm missing something ? Any help is appreciated.
Kind regards

Add a middleware
php artisan make:middleware Cors
In app/Http/kernel.php paste this in $middleware
protected $middleware = [
\App\Http\Middleware\Cors::class,
....
];
In Middleware/Cors.php now add
public function handle(Request $request, Closure $next)
{
return $next($request)->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods','GET, POST, PUT, PATCH, DELETE,
OPTIONS')
->header('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-
Type, Accept, Authorization');
}

What I came to realise was that this was not actually a CORS issue. If it was a CORS issue, I would not have been able to login, or visit the API that returns the currently logged in user.
What actually happens is that, chrome sometimes fails to report 500 errors on the API and rather returns CORS errors. When I tried making the API call on Firefox, I was able to actually see the 500 error.
Once I resolved the 500 error, the CORS error also stopped appearing in chrome.
What I've seen from this is that the network request error reporting on Firefox is more reliable than that on chrome

Related

Subdomain routing not working in Laravel 9 and Inertia

I'm working on a Larave, Inertiajs and Vue project where I want every product to open on a route like this https://{user:username}.example.test/{product:slug}
So basically I need my website to run on example.test and any product to show on username.example.test/productSlug
I had an issue where I'm getting CORS errors and I wrote a thread here Laravel Inertia apps doesn't support subdomain redirects - No 'Access-Control-Allow-Origin'
Unfortunately I didn't get the help I needed here but after hours of searching I found this on stackoverflow which have helped me to finally succeed on making the redirect to the correct URL works but the problem is that It doesn't really work.
To explain this:
The controller store action finishes what It's supposed to do and then redirects me to a working page of my product without cors errors, the only problem is that it shows in the browser as example.test/productSlug while it's supposed to be username.example.test/productSlug. When I refresh the page when I'm on that incorrect url It gets me page not found error which make sense because the actual correct route contains my desired page.
When I tracked the request on firefox I could see that the host is correct (username.example.test) but the url I'm reaching is 'example.test', also when I'm redirected to that incorrect route I could see my product and everything works just fine but it's not a working url because when I refresh It gives me page not found and when I manually write the correct url username.example.test/productSlug It directs me to a working page of my product.
I hope you're not confused.
This is the redirect line in my ProductsController#store:
public function store(StoreProductRequest $request)
{
// Code
return redirect()->route('products.show', [$user, $product]);
}
This is how my route looks like:
Route::domain('{user:username}.' . env('APP_URL'))->group(function () {
Route::get('{product:slug}', [ProductController::class, 'show'])->name('products.show');
});
And this is how I show the product:
public function show(User $user, Product $product)
{
return Inertia::render('Products/Show', [
'user' => $user,
'product' => $product,
'thumbnails' => $product->productimages
]);
}
I made those changes to cors.php:
'paths' => ['api/*', '*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => ['x-inertia'],
'max_age' => 0,
'supports_credentials' => false,
After days of research I'm sure now that it is impossible to route redirect to a subdomain route from root domain without full page refresh. Any change to the host will require the page to reload which is out of Laravel and JetStream scope and out of InertiaJS hands. As far as I understand that this is for security purposes. See more here https://github.com/inertiajs/inertia-laravel/issues/431

Laravel 8 back end and Vue 3 Frontend cors error on deployment (heroku)

My laravel backend and Vue js front end applciations are running on seperate servers. locally it's working very fine, but on deployment i keep getting this error
Access to XMLHttpRequest at 'https://akademiaapi.herokuapp.com/api/country/' from origin 'https://akademiaadmin.herokuapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
this is my Laravel configuration for cors and middleware
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
for middleware
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
My vue js configuration
import axios from 'axios'
let Api = axios.create({
baseURL: "https://akademiaapi.herokuapp.com/api"
})
Api.defaults.withCredentials = true
export default Api
i've tried every possible solution shown online, please i really need assistance as this has eating lots of time into my deadline already
i've even added to my route file, but still didn't work
header("Cache-Control: no-cache, must-revalidate");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type, X-Auth-Token, Origin, Authorization');

CORS in Laravel when using fetch to download a file on storage on localhost

Sorry if it looks like I again ask for CORS-configuration in Laravel. But my scenario is alittle bit different and I couldn't find anything helpful yet.
I'm serving my Laravel-Application via php artisan serve --port 80
CORS is configured like this in config/cors.php:
return [
'paths' => ["*"],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
And enabled in middleware in Kernel.php:
protected $middleware = [
// ...
\Fruitcake\Cors\HandleCors::class,
// ...
];
In my frontend (localhost:8080) I do a simple
const content = await fetch("http://localhost/storage/plans/46718040-5c72-4999-865f-5174a7c59313.png")
but I'm getting the following error:
Access to fetch at 'http://localhost/storage/plans/46718040-5c72-4999-865f-5174a7c59313.png'
from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Do I have to setup Nginx locally to configure cors for the storage? Or are there any other ideas?
Do I have to setup Nginx locally to configure cors for the storage?
Yes. Your request isn't invoking Laravel at all, the file is being served statically.
Do you need to use fetch to get the content, or can you just set an image source to the file path instead?

react native application returns 404 error

I am creating app in react native with laravel backend.So as I want to get api from laravel server so i run laravel with that command
php artisan serve --host=some-domain.test --port=anyPort
I create api like that way
Route::get('users','PostController#get_users');
function get_users()
{
return Response()->json(User::get(),200);
}
In react native I call that api in that way
constructor()
{
super();
this.state={
data :[]
}
}
componentDidMount()
{
this.callApi();
}
async callApi()
{
let data=await fetch(' http://192.168.1.1:8081/api/users') //same as where laravel server is running
let adata= await data.text();
this.setState({data:adata})
console.warn(data)
}
It returns me 404 error:development server returned response error code:404
but when i stop laravel server and refresh my app then start laravel server it return me that error
Possible unhandled promise rejection(id:0):
what should I do now ?
You are not handling your Promise right hence you get the Error. The way that Fetch should be used is something like this:
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
You can read more about it on the official Docs:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
If you want to set the State you would have to do it in the second .then() Call.
Also remeber to add a .catch(err => console.log(err)) to filter your errors.
I think you need to handle cors request
You can install this package
https://github.com/fruitcake/laravel-cors
To generate config file run following command
php artisan vendor:publish --tag="cors"
and then update in config/cors.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
To allow CORS for all your routes, add the HandleCors middleware at the top of the $middleware property of app/Http/Kernel.php class:
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
// ...
];

API login from android app using laravel 5.3 passport

For two days I am digging google but could not find the starting thread for my problem, now I am out of option. Please help me with some direction/howTo
I have a web application running built with laravel 5.3, I have installed passport as described here . if I go /home its showing perfectly.
Now I have to make an android app from which
An already existing user of web app can login
get all the task list of that user TaskModel (ons_tasks(id, title, description))
routes related only
in web.php
Auth::routes();
in api.php
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
Route::group(['middleware' => ['auth:api']], function () {
Route::get('/test', function (Request $request) {
return response()->json(['name' => 'test']);
});
Route::get('/task/list', function (Request $request) {
$list = \App\Model\TaskModel::all();
return response()->json($list);
});
});
To login : if I send post request /login with email & password get the TokenMismatchException error but Where do I obtain a token for
android app in mobile? Do I need the Auth::routes() in the api too?
if then what else Do I need to just login and get a token so later I
can send it for getting the task lists.
Secondly,
If I go to /api/test it redirects me to /home page without
showing any error !!!
Thanks in advance.
To authenticate with your Passport-enabled API
You'll need to use the Password Grant Client in this situation, see this section of Passport's documentation.
Once you've generated a Password Grant Client, using:
php artisan passport:client --password
You will need to request an access token from your application, and send it with your subsequent requests, in order to access the protected auth:api middleware routes.
To get an access token, send a request to your app's /oauth/token route (this is a PHP implementation obviously, ensure you are correctly formatting below request in your Java implementation):
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '<client id returned from the artisan command above>',
' client_secret' => '<secret returned from artisan command above>',
'username' => 'taylor#laravel.com',
'password' => 'my-password',
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
Ensure you add the client_secret and client_id that was returned from the artisan call above, and ensure username and password references a valid user in your database.
If everything is fine here, you should receive an access_token and refresh_token in the response. The access_token is what you need to authenticate using the auth:api guard. To correctly pass this back to your api, you will need to send your subsequent requests with the headers Authorization: Bearer <your accessToken> and Accept: application/json
For example, to access your "test" route:
$response = $client->request('GET', '/api/test', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '. <accessToken from /oauth/token call>,
],
]);
If you've set these correctly, you should see a JSON response with the array you have specified.
Why is /api/test redirecting me with no error?
You are requesting a route with the auth:api middleware. This will redirect you as you have not specified the correct headers as described above, this is expected behavior.
Hope this helps.

Resources