问题
I am trying to allow my users, once they are logged in, to consume my own API through Javasscript as described there https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript
I have installed Passport. My web middleware is defined as
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Barryvdh\Cors\HandleCors::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SetLocale::class,
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
I see that a "laravel_token" cookie seems indeed to be created after login.
I've then tried sending a simple get request to an API route
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
The only response I manage to get is
{"message":"Unauthenticated."}
What can I have missed?
Update
The request is performed from a subdomain, client.mywebsite.test, and after investigation that's what seems to be the issue. Authentication works well when performing the ajax call from mywebsite.test. How can I fix that for the subdomain?
Request headers when requesting from subdomain:
OPTIONS /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: https://client.mywebsite.test
Access-Control-Request-Headers: x-csrf-token,x-requested-with
Accept: */*
Referer: https://client.mywebsite.test/home
Request headers when requesting from domain:
GET /api/testApi HTTP/1.1
Host: mywebsite.test
Connection: keep-alive
X-CSRF-TOKEN: fLTkaq9p62FROutzch2iE9IF864al8adFnxptbve
X-Requested-With: XMLHttpRequest
Cookie: laravel_token=[...]; XSRF-TOKEN=[...]; mywebsite_session=[...];
回答1:
This works for me in a Laravel 5.6 project:
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected static $serialize = true;
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}
Set the property $serialize
to true
on EncryptCookies
middleware.
Source: https://laravel.com/docs/5.6/upgrade#upgrade-5.6.30
Source: Laravel passport consuming api with js not working
回答2:
After browsing and browsing and browsing..
Turns out the problem comes, indeed, from the cookies not being sent with the request for CORS. I fixed it by adding "withCredentials" to my Ajax call:
window.$.ajax({
headers: {
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
xhrFields: {
withCredentials: true
},
type: 'GET',
url: 'https://mywebsite.test/api/testApi',
success: function (response) {
console.log(response);
},
error: function (xhr) {
console.error(xhr.responseText);
}
});
You also need to ensure the headers for your response specify that credentials are accepted:
header('Access-Control-Allow-Credentials: true');
来源:https://stackoverflow.com/questions/54307909/laravel-passport-auth-through-createfreshapitoken-always-returns-messageuna