Laravel Sanctum - sanctum/csrf-cookie (204 "No content") - laravel

Laravel sanctum has been a bit of a headache for me as i have spent hours trying to figure out why sanctum/csrf-cookie route returns no content. initially the same route return 404 not found but after adding 'prefix' => 'api/sanctum' config/sanctum.php it seems to work except that it outputs nothing and no cookie is set in my browser.
Here are some of my codes
.env
SANCTUM_STATEFUL_DOMAINS=localhost:8080
SPA_URL=http://localhost:8080
SESSION_DOMAIN=localhost
--config/cors.php
'paths' => [
'api/*',
'login',
'logout',
'register',
'user/password',
'forgot-password',
'reset-password',
'sanctum/csrf-cookie',
'user/profile-information',
'email/verification-notification',
],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
axios
export const authClient = axios.create({
baseURL: process.env.VUE_APP_API_URL,
withCredentials: true, // required to handle the CSRF token
});
and having done all of that, if i tried to generate a token using
axios.get('/sanctum/csrf-cookie').then(response => {
// Login...
});
i get 204 no content response
i have also added the api middleware in kernel.php as instructed in the doucmentation but still wont set the cookie. and when i try to make request to another route protected by sanctum i 419 token mismatch.
i have also run a fresh installation of laravel, php artisan optimize, cleared my brower history, checked the endpoints in postman but still thesame 204 and 419 exceptions

I was struggling with the same issue for days and then founded a way that worked.
so :
The '/sanctum/csrf-cookie' route return a 204 response when successfull, the then you have to send your post request with credentials. i used to get a 419 reponse status.
so after followed laravel docs here is what i added :
SPA
make sure you set the withCredentials header to true
API
.env
SESSION_DRIVER=cookie
SESSION_DOMAIN='.localhost'
SANCTUM_STATEFUL_DOMAINS='localhost,127.0.0.1'
.kernel.php
add in your middleware array : \Illuminate\Session\Middleware\StartSession::class

Hey I don't know whether you've found the answer or not but that request meant to have empty response body. Your CSRF token is available in the header of the response ;D

From HTTP Specification:
The HTTP 204 No Content success status response code indicates that a request has succeeded, but that the client doesn't need to navigate away from its current page. This might be used, for example, when implementing "save and continue editing" functionality for a wiki site.
According to specification 204 is the exptected response from server.

You can insert in bootstrap.js file
import axios from 'axios';
window._ = _;
window.axios = axios;
window.axios.defaults.baseURL = "/api/";
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Related

How to solve the CORS error in Laravel + Nuxt.js

I am installing the old project, which is made by Nuxt.js (frontend) and Laravel (backend) on my local.
Access to XMLHttpRequest at 'http://localhost:8000/api/user' from origin 'http://127.0.0.1:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
This is the issue that I faced to run the project.
Frontend configuration for the request(nuxt nuxt.config.js).
user: {
url: '/api/user',
method: 'get',
propertyName: false,
withCredentials: true,
headers: {
X-Requested-With': 'XMLHttpRequest',
Content-Type': 'application/json'
}
}
Backend configuration (Laravel config/cors.php)
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
I tried to find the solution by googling but I didn't find the correct solution.
withCredetials is true
CORS: credentials mode is 'include'
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'
So, I want someone to help me in this field.
Try this way in your laravel app:
php artisan serve --host YOUR_LOCAL_IP
YOUR_LOCAL_IP is your ip that can access with ifconfig command in linux and ipconfig in windows.
Finally you should request to YOUR_LOCAL_IP:PORT/api

CORS Access to XMLHttpRequest at X from origin has been blocked by CORS policy

CORS Access to XMLHttpRequest at X from origin has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Hi, I am struggling to resolve my problems with CORS denying interaction of my Vue component with an external API with axios since it returns this error. I've tried both using Barryvdh's Cors header support and making a middleware and custom route. It simply won't work. Everything that has been mentioned in README.md in Barryvdh's repo has been done and unfortunately, this problem won't get resolved by any means necessary.
Here is the code, even though I don't think there's need to show since it's exactly the same as mentioned in the repo;
inside Kernel.php:
protected $middleware = [
\Barryvdh\Cors\HandleCors::class,
inside app.php (providers array):
Barryvdh\Cors\ServiceProvider::class,
config/cors.php:
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
Here's the axios get call (I've replaced my token with 'TOKEN')
methods: {
loadWeatherData: function() {
axios.get( 'http://api.openweathermap.org/data/2.5/weather?q=London&mode=json&units=metric&appid=TOKEN' )
.then( function( response ) {
console.log( 'radi' );
}).catch( errors => {
console.log( errors+' ne radi');
});
}
},
I've composer dump-ed, nothing affected resolving the problem.
Is there something I am doing wrong and are there any solutions for this problem? Thanks in advance!
The problem here seems to be that axios likes to send its own default headers, and these don't pass the preflight check for your external request. To fix this, you will need to remove the offending headers.
I was able to recreate your error, and also to bypass the CORS issue using the code below.
let url = 'https://api.openweathermap.org/data/2.5/weather?q=London&mode=json&units=metric&appid=TOKEN';
// create a new instance so we don't delete the headers for other requests
let instance = axios.create();
// delete headers if existing
delete instance.defaults.headers.common['Accept'];
delete instance.defaults.headers.common['X-Requested-With'];
delete instance.defaults.headers.common['X-CSRF-TOKEN'];
// use the new axios instance to make your get request
instance.get(url)
.then(function(response) {
console.log(response);
}).catch( errors => {
console.log(errors + ' ne radi');
});
Hope this helps and good luck!
You can add into TrustHosts.php Middleware without doing anything extra. Read more from here https://stackoverflow.com/a/70361284/2612926

CORS Laravel VueJS

I'm trying to do a get with axios from VueJS to Laravel which is my API.
I got this error :
Access to XMLHttpRequest at 'http://api.test/api/events/1/' from origin >'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control->Allow-Origin' header is present on the requested resource.
Uncaught (in promise) Error: Network Error
at createError (createError.js?2d83:16)
at XMLHttpRequest.handleError (xhr.js?b50d:87)
I've tried to create a middleware named 'cors' like here but it's not working for me or maybe I'm doing it badly ?
Strange thing ? is that's working with Postman.
Thank for the help ! :)
Servers are used to host web pages, applications, images, fonts, and
much more. When you use a web browser, you are likely attempting to
access a distinct website (hosted on a server). Websites often request
these hosted resources from different locations (servers) on the
Internet. Security policies on servers mitigate the risks associated
with requesting assets hosted on different server. Let's take a look
at an example of a security policy: same-origin.
The same-origin policy is very restrictive. Under this policy, a
document (i.e., like a web page) hosted on server A can only interact
with other documents that are also on server A. In short, the
same-origin policy enforces that documents that interact with each
other have the same origin.
Check this CORS library made for Laravel usage.
Installation is easy:
$ composer require barryvdh/laravel-cors
$ php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
The defaults are set in config/cors.php
return [
/*
|--------------------------------------------------------------------------
| Laravel CORS
|--------------------------------------------------------------------------
|
| allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
| to accept any value.
|
*/
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['Content-Type', 'X-Requested-With'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,
];
allowedOrigins, allowedHeaders and allowedMethods can be set to array('*') to accept any value.
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,
];
If you want to allow CORS on a specific middleware group or route, add the HandleCors middleware to your group:
protected $middlewareGroups = [
'web' => [
// ...
],
'api' => [
// ...
\Barryvdh\Cors\HandleCors::class,
],
];
https://www.codecademy.com/articles/what-is-cors
Tried sending Axios request from Vue app to Laravel backend.
I had CORS Error and I couldn't find the solution.
After following request execution in vendor files I found out that I was simply testing it wrong.
I was testing on url: http://localhost/api, but in config/cors.php there is:
'paths' => ['api/*', 'sanctum/csrf-cookie'],
So all I had to do was to change request to http://localhost/api/... and it started working.
Another solution is adding 'api' to paths array in config/cors.php if you want to use http://localhost/api
The problem you are facing is with the same origin policy. you can read about it on the Mozilla site (https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control).
it is basally to proven un authorized access to web servers. you can change the way your web server reacts and i also in that link i have included.

Laravel Passport: CreateFreshApiToken in App: Authorization Failed

I'm attempting to install Laravel Passport on Laravel 5.7.18 using PHP 7.2.13.
My application consumes the API within itself using JavaScript (Axios with Vue)
I'm getting a 401 Unauthorized error within the JavaScript web application. I've read the documentation and added CreateFreshApiToken to the web Kernel. The laravel_token cookie is in fact setting itself. However, the oauth tables are clean in the database.
Http/Kernel:
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,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
JavaScript:
axios.get("api/users/" + id).then(({ data }) => {
this.user = data;
});
Auth.php:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Routes (Api.php):
Route::middleware('auth:api')->group(function () {
Route::resource('users', 'UserController');
Route::resource('groups', 'GroupController');
// .. plus more resources
});
Axios Config:
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
var token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
Headers in Browser that returns 401:
Working Request with Postman:
If you are using a username and password for initial login then the assumption is you are building a First Party application that has the right to make a user/pass login attempt.
It is highly recommended that if you are building a Reactive app using
Angular, React.js or Vue.js then an SPA (Single Page Application)
approach will yield a much more robust product.
https://en.wikipedia.org/wiki/Single-page_application
You should note that with this particular method, if your application
makes a static (none ajax request) and thus reloads in the browser,
you will loose the auth token. In this case you are not playing host
to an app that is by it's very definition an SPA, so if you need to retain the token between
static request reloads then you need to store the token in a cookie, I
suggest using a cookie rather than localStorage because the availability of
localStorage is not 100% guaranteed to be at your disposal in all web browsers.
If your application is on the same domain, you do not need to use
Passport. Instead native session cookie auth is perfectly fine, all
you have to do is make sure you are passing the CSRF Token for post
requests.
For user/pass token grants you should follow this guideline:
https://laravel.com/docs/5.7/passport#password-grant-tokens
From that guide, when you make a successful request to /oauth/token, the returned token should be set in your application as an Authorization header with Bearer token.
The token request response looks like this:
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKVJhb...nheKL-fuTlM",
"refresh_token": "def502008d6313e...94508f1cb"
}
You should request and handle that JSON object as follows:
axios.post('/oauth/token', {
grant_type: "password",
client_id: "1",
client_secret: "zkI40Y.......KvPNH8",
username:"email#address.com",
password:"my-password"
}).then( response => {
axios.defaults.headers.common['Authorization'] = `Bearer ${response.data.access_token}`
} );
The values for client_id (id) and client_secret come from oauth_clients table, there should already be an entry in there.
If not then run php artisan passport:client --password
Don't forget that you will have to configure some headers, look to this post has some relevant information for the Oauth Authorization header:
How to send authorization header with axios
If you say your tables are clean in the database, try to run this command again:
php artisan passport:install
This command will create the encryption keys needed to generate secure access tokens. In addition, the command will create "personal access" and "password grant" clients which will be used to generate access tokens:
Laravel 5.7 Passport docs

Laravel issue No 'Access-Control-Allow-Origin'

I'm writing a very common topic, but I am desperate, wasted two days trying to make this work.
I'm on Chrome, trying to make my first Login/Register app and at the time of sending the data to the backend, i get the following error:
XMLHttpRequest cannot load http://192.168.1.133:8100/api/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access. The response had HTTP status code 500.
I am making a POST request from AngularJS like follows:
$scope.data = "UserName"; // for example
$scope.register = function() {
var withAjax = $http.post('http://192.168.1.133/api/register', $scope.data);
withAjax
.success(function(answer){
console.log(answer.message);
})
.error(function(answer) {
console.log("error");
});
}
])
And the Laravel API backend is simple, just return 'Correct'.
public function login (Request $request) {
$inputArray = $request->all();
return response()->json(["message" => "Login: All Correct"]);
}
In my front-end app I alowed all kind connections with:
<allow-navigation href="http://*/*" />
<allow-navigation href="*" />
<access origin="*"/>
In PHP I tried all. Disabled CSFR token for API, and installed properly "barryvdh/laravel-cors" and configured cors file like follows:
return [
'supportsCredentials' => false,
'allowedOrigins' => ['*'],
'allowedHeaders' => ['*'],
'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT', 'DELETE']
'exposedHeaders' => [],
];
When I can make, sending data back and forth easy process, I will care about protection. Now I decided to open 'all' to make it straightforward.
I'm crazy about this, lost two days just trying to solve this.
Any clue would be of help.
Thank you!
Try this plugin for Chrome, might help you. CORS

Resources