I have a problem with cors origin in my laravel project, I created cors.php in middwares folder and I declare it in Kernel.php and app/Providers/RouteServiceProvider.php as well... I did everything to solve it in my Laravel project, even in folder config I added a file Cors.php
I'm now wondering if I have to add something in Nginx configuration or Apache configuration ?
I'm hosting my project in hostinger VPS, The version of linux is ubuntu 22.04.5 LTS
Thank you in advance.
Regards
Middlewares/Cors.php
<?php
namespace App\Http\Middleware;
use Closure;
class Cors
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', '*')
}
}
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/*','web/*', 'sanctum/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => ['*'],
'allowed_headers' => ['*'],
'exposed_headers' => ['*'],
'max_age' => 0,
'supports_credentials' => true
];
I added also this lines to Http/kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::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,
'cors' => \App\Http\Middleware\Cors::class, // added
];
I in console I have this message ( see pictures ):
and I have this message in console : Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
post.js:42559 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
scrollspy.js:224 Uncaught TypeError: Cannot read properties of null (reading 'classList')
at An._activate (scrollspy.js:224:10)
at An._process (scrollspy.js:191:14)
at new An (scrollspy.js:80:10)
at bg_scripts.js:35:9
sb-forms-latest.js:5 Uncaught Error: GET_ELEMENTS: -> form[data-sb-form-api-token]
at e (sb-forms-latest.js:5:415)
at sb-forms-latest.js:5:3777
profile.js:32882 Error: Network Error
at createError (profile.js:872:15)
at XMLHttpRequest.handleError (profile.js:754:14)
127.0.0.1:8000/getMessages:1 Failed to load resource: net::ERR_CONNECTION_REFUSED
boxicons.min.css:1 Failed to load resource: the server responded with a status of 404 ()
[enter image description here][1]
[enter image description here][2]
[1]: https://i.stack.imgur.com/T9DhM.png
[2]: https://i.stack.imgur.com/7zXtW.png
are you Building an API with a SPA ?
and he will be better if you have some error just provide us.
No Problem, Create a new Middleware and put this line in it:
$response = $next($request);
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', '*');
$response->headers->set('Access-Control-Allow-Credentials', true);
$response->headers->set('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,X-Token-Auth,Authorization');
return $response;
and your problem will be solved
You Can check this repo for more details
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');
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
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"
I'm using Laravel 5.7 for some api. I'm also using package https://github.com/tymondesigns/jwt-auth to generate JWT tokens to authenticate users. I have configured everything long time ago and it works well.
I register Route group in RouteServiceProvider.php under routes/api_v1.php :
Route::prefix('api/v1')
->middleware('api')
->namespace($this->namespace.'\API\V1')
->group(base_path('routes/api_v1.php'));
In config.auth.php I have api_v1 guard with driver jwt :
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api_v1' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
I have made App/User.php implemented Tymon\JWTAuth\Contracts\JWTSubject and implemented the 2 methods.
But when in app/Http/Kernel.php I added in middlewares array :
protected $routeMiddleware = [
// previous middlewares,
'jwt.auth' => \App\Http\Middleware\JWTAuthenticate::class
];
The Routes in routes/api_v1.php under the group jwt.auth:
Route::middleware(['jwt.auth'])->group(function() {
// Keep auto resource route at bottom to prevent route conflict with Show parameter route
foreach(Controller::$resourceModels as $key => $model) {
//Route::post($key.'/{id}/patch', $model.'Controller#patchUpdate');
Route::resource($key, $model.'Controller');
}
});
never reach middleware App\Http\Middleware\JWTAuthenticate::class but always go to the original tymon package middleware Tymon\JWTAuth\Http\Middleware\Authenticate::class.
Even if I don't put api driver to jwt in auth.php config, and I don't put any jwt.auth class in Middleware it's working normally with original middleware.
What I need is for the Routes group to go to my own middleware class App/Http/Middlewares/JWTAuthenticate :
<?php
namespace App\Http\Middleware;
use Tymon\JWTAuth\Http\Middleware\Authenticate;
use Closure;
class JWTAuthenticate extends Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* #return mixed
*/
public function handle($request, Closure $next)
{
// My own logics here
// ...
$this->authenticate($request);
return $next($request);
}
}
and this way I can override handle method and check for my own things first.
I can tell you why it happens.
The file app\Http\Kernel.php with the middleware config, gets called earlier than registering the service providers.
The Tymon JWT service provider gets therefore called afterwards and sets middleware aliases for:
'jwt.auth' => Tymon\JWTAuth\Http\Middleware\Authenticate::class,
'jwt.check' => Tymon\JWTAuth\Http\Middleware\Check::class,
'jwt.refresh' => Tymon\JWTAuth\Http\Middleware\RefreshToken::class,
'jwt.renew' => Tymon\JWTAuth\Http\Middleware\AuthenticateAndRenew::class,
thus overriding your key.
So using another middleware key is therefore the right way to use your own implementation.
I renamed the middleware route group and changed
Route::middleware(['jwt.auth'])->group(function() {
to
Route::middleware(['jwt.authenticate'])->group(function() {
and
'jwt.auth' => \App\Http\Middleware\JWTAuthenticate::class
to
'jwt.authenticate' => \App\Http\Middleware\JWTAuthenticate::class
And the original jwt.auth was not called anymore. I don't know why but I can control it now in my Middleware.