I have developed this in laravel vuejs, used laravel sanctum for authentication. The app works fine in localhost, But getting this error while I did this in the live domain. I am sharing the error where I was trying to get user info :
The screenshot of header :
I am sharing the .env:
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
SESSION_DOMAIN=localhost
SESSION_SECURE_COOKIE=false
SANCTUM_STATEFUL_DOMAIN=localhost,localhost:8080
From sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS',
'localhost,localhost:8080')),
From kernel :
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
from bootstrap.js
axios.defaults.withCredentials = true;
And from component :
created() {
axios.defaults.headers.common['Authorization'] = `Bearer ${this.token}`
axios.get('/api/user').then(response => {
localStorage.setItem('userInfo', JSON.stringify(response.data))
let getUser = localStorage.getItem('userInfo')
this.currentUser = JSON.parse(getUser)
}).catch(errors => {
console.log(errors)
})
}
Your POST request to /api/user-login is returning a server error(500). Maybe that's why its not returning the auth token or cookie
You need to fix the server error first
my problem is that I can't send data via post to my api -> cors.
I am struggling with this issue for days now.. My attempt to find a solution failed so far - threads with the same issue had solutions I have already tried.
Here is the error from the console:
header ‘content-type’ is not allowed according to header ‘Access-Control-Allow-Headers’ from CORS preflight response
here is my config/cors.php:
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false
Kernel.php:
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\Fruitcake\Cors\HandleCors::class, <----- Cors Middleware
\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,
];
Sometimes it was suggested to move \Fruitcake\Cors\HandleCors::class to a different position within the array -> no result
Here is my axios request from the nuxt component:
async register() {
let config = {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}
await this.$axios
.$post(
'/api/v1/register',
{
...this.form,
password_confirmation: this.form.password,
},
config
)
.then(() => {}
}
I quite the beginner with API's and don't truly understand with point is causing the CORS error.
If it is a problem with Laravel or Nuxt.
I already tried to add the required headers (as suggested in various posts) to the routes/api.php and index.php in the public folder and external in the .htaccess without success. Of course not at the same time...
Hope anyone can help me with this.
If you pass a JSON object as the second argument to the axios.post method, axios will automatically serialise it to JSON for you. It will also set the Content-Type header.
Try removing your explicit header declaration.
async register() {
await this.$axios
.$post(
'/api/v1/register',
{
...this.form,
password_confirmation: this.form.password,
})
.then(() => {})
}
I've a backend app working with Laravel 7 and a frontend which works with VueJs. My Laravel app is running on laradock (nginx, postgres etc...) Using Postman the API (Laravel 7) works properly.
This API replies by dns or by ip. http://192.168.0.3:80/api/mobile or http://laraapi.com/api/mobile
Once I'm still developing the VueJs app I'm running it with "npm run serve" which provides two ways to access my app, first by localhost and the second one by IP address. Both of them running on port 8081.
When Axios consume the API which uses the GET verb, everything works fine. When Axios consumes a POST verb than a get error.
Access to XMLHttpRequest at 'http://larapi.com/api/mobile/startorder/' from origin 'http://192.168.0.3:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
By default laravel 7 already have a pre-done configuration for CORS which is provided by "Fruitcake"
So my kernel.php is like that:
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
Fruitcake was moved in to be the first one, the tip from another StackOverflow which didn't help anyway.
My cors configuration:
'paths' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => false,
'max_age' => false,
'supports_credentials' => true,
See that supports_credentials and allowed_origins were changed. Anyway, changing allowed_origins to "*" does not work.
I've created another route file named "mobile" and I'm using this one instead of "api.php", the content is:
Route::group(['middleware' => 'auth:api'], function(){
Route::namespace('Mobile')->group(function () {
Route::post('startorder',
['as' => 'startorder', 'uses' => 'PRC\PurchaseController#startOrder']);
});
});
This new file was created because the idea is use api.php for another purpose.
I've tried already to set a proxy on VueJs side but unfortunately, the result was the same one.
Axios call
import { http } from "./config";
startOrder: (order, user, token) => {
var data = {
"order": order,
"user": user,
}
return http.post("startorder/",data, {
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
withCredentials: true,
});
}
my config.js
import axios from "axios";
export const http = axios.create({
baseURL: "http://192.168.0.3:80/api/mobile/",
withCredentials: true
});
vue.config.js
module.exports = {
devServer: {
proxy: "http://192.168.0.3:80/api/mobile/",
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8081,
https: false,
hotOnly: false,
},
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = 'LaraAPi'
return args
})
}
}
For sure something is missing but actually I don't know which side is wrong anymore after a lot of tries.
I would appreciate it a lot if someone would help with that issue.
if you use axios withCredentials = true you need to enable laravel cros.php file supports_credentials = true
for axios code example:
axios.get('/user?ID=12345', { withCredentials: true })
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
for cros.php code example
[
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true
]
I don't know about this '*' stuff. Remember, this is very bad practice in production!
Access to XMLHttpRequest at 'http://larapi.com/api/mobile/startorder/'
from origin 'http://192.168.0.3:8081' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource.
Try to put the failed origin inside cors.php:
'paths' => ['api/*'],
'allowed_origins' => ['http://192.168.0.3:8081', 'http://192.168.0.3:80', 'http://laraapi.com'],
All three origins above are allowed to make requests to this endpoint.
It's always recommended to create an environment variable to better control this type of configurations. If you make it work in development, it will automatically work in production too!
'paths' => ['api/*'],
'allowed_origins' => env('CORS_ALLOWED_ORIGINS'),
.env
CORS_ALLOWED_ORIGINS=http://192.168.0.3:8081,http://192.168.0.3:80,http://laraapi.com
Update your production .env file accordingly.
cors.php I strongly suggest you change paths
<?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' => ['*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => false,
'max_age' => false,
'supports_credentials' => false,
];
Kernel.php
<?php
namespace App\Http;
use App\Http\Middleware\cors;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* #var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* #var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}
mobile.php (similar to api.php)
<?php
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length');
header('Access-Control-Allow-Origin: http://192.168.0.4:8081');
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::post('login', 'Mobile\Login\UserController#login');
Route::post('register', 'Mobile\Login\UserController#register');
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
VueJs Side
//const configureAPI = require('./src/server/configure')
module.exports = {
devServer: {
proxy: "http://192.168.0.4:80/api/mobile/",
open: process.platform === 'darwin',
host: '0.0.0.0',
port: 8081, // CHANGE YOUR PORT HERE!
https: false,
hotOnly: false,
}
}
config.js
import axios from "axios";
export const http = axios.create({
baseURL: "http://192.168.0.4:80/api/mobile/",
withCredentials: false
});
service.js (consumes the API)
start: (parameter, token) => {
var data = {
parameter: parameter,
user: user,
};
return http.post("start/", data, {
headers: {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
},
withCredentials: false,
});
},
#Keith Gulbro I hope this helps you to fix that nightmare. Let me know if you need something else.
Folks, seems the issue has been solved at least for now.
I will keep looking for a better solution.
Below, the details how this was solved.
1- remove the \Fruitcake\Cors\HandleCors::class from protected middleware on kernel.php
2 - On the header of api routes file you must set those lines below:
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length');
header('Access-Control-Allow-Origin: http://192.168.0.3:8081');
In my case, I removed the wildcard * and put my valid origin. The wildcard is insecure.
3 - I've changed my Axios post method to send withCredentials as false.
export default {
login: data => {
return http.post("login",data, {
headers: {
"Content-Type": "application/json",
},
withCredentials: false,
});
},
4 - Config and cache were cleared.
php artisan config:clear
php artisan cache:clear
Now the response header is fulfilled correctly and the Access-Control-Allow-Origin' error disappeared.
Anyway, might have a better solution using FruitCake, otherwise would make no sense at all to provide an inefficient package.
If someone has a better solution, please share it!
Thank's
This is my my vue component
export default {
data(){
return{
form:new Form({
district: '',
province: '',
name: '',
})
}
},
methods: {
createHousehold(){
this.form.post('api/household');
}
},
mounted() {
console.log('Component mounted.')
}
}
This is the api route.
Route::apiResource('household','APIController/HouseholdController');
When I check the route list 'api/household' has get for index and post for storing, but I get this error and not able to figure out where do I specify the post method other than in the vue method. Also I tried adding csrf in the head section of my master blade
Explanation
You will need to set the Access-Control-Allow-Methods header the specifies the method or methods allowed when accessing the resource in response to a preflight request.
Ref URL - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
you can add cors package in server-side by using the following package(in laravel or PHP)
URL - https://packagist.org/packages/barryvdh/laravel-cors
composer require barryvdh/laravel-cors
Add in the middleware group under the app/Http/Kernel.php file.
protected $middlewareGroups = [
...
'api' => [
'throttle:60,1',
'bindings',
\Barryvdh\Cors\HandleCors::class,
],
...
]
and run the following command.
php artisan vendor:publish --tag="cors"
update the config with the following content(config/cors.php)
return [
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedOriginsPatterns' => [],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'], // this is the solution of your problem
'exposedHeaders' => [],
'maxAge' => 0,
]
I'm trying to pull data from a weather API on my localhost environment and I'm getting a 405 Error(Method not allowed) as well as "has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status." I've config'd my headers and can't figure out what i'm doing wrong. It works fine on live but obviously that's not a convenient way doing it.
I've tried using axios.get as well as axios.post.
var config = {
headers: {'Access-Control-Allow-Origin': '*'}
};
getWeather: function (){
axios.get('http://api.openweathermap.org/data/2.5/forecast?id='+ city + '&appid='+ apiKey, config).then((res) => {this.weather = res.data});
}
Hope adding below package will help
use this https://github.com/barryvdh/laravel-cors
Installation :
composer require barryvdh/laravel-cors
Service provider :
Add this Barryvdh\Cors\ServiceProvider::class, in config/app.php
To allow CORS for all your routes, add the HandleCors middleware in the $middleware property of app/Http/Kernel.php class:
protected $middleware = [
\Barryvdh\Cors\HandleCors::class,
// ...
];
NOTE: make sure to place it before all middlewares
If it's for specific middleware, on our case, it will be api
protected $middlewareGroups = [
'web' => [
// ...
],
'api' => [
\Barryvdh\Cors\HandleCors::class,
'throttle:60,1',
'bindings',
],
];
NOTE: make sure to place it before all middlewares
Publish the config :
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"