Reputation: 1848
I'm trying to use the laravel passport to authenticate users. I followed every step in laravel passport documentation. But it shows error when I access a route that is protected by 'auth:api' middleware. I've searched over the internet but any of the answers are not working so far. Please see the code, and what I've tried so far below.
Tech used
Tried so far:
Passport::routes();
to Passport::routes(null, ['prefix' => 'api/oauth', 'middleware' => ['auth:api', 'web', 'auth']]);
in AuthServiceProvider
. Also tried Passport::routes(null, ['prefix' => 'api/oauth');
php artisan cache:clear
routes/api.php
Route::middleware('auth:api')->group(function() {
Route::get('user', function() {
return request()->user();
});
Route::get('posts', 'PostController@index')->name('posts');
Route::post('posts/store', 'PostController@store')->name('posts.store');
Route::get('posts/{id}/show')->name('posts.show');
Route::get('users/{id}/show')->name('users.show');
});
Axios
mounted() {
axios.get('/api/posts')
.then(res => this.posts = res.data).catch(error => console.log('Unable to fetch posts.'))
}
Error
Headers:
Please let me know if you need some details that is not indicated on my post yet.
Setup
composer require laravel/passport:9
for the installation.php artisan migrate
for the tables.php artisan passport:install
to generate the encryption keys.Laravel\Passport\HasApiTokens
trait in User
model.Passport::routes();
in AuthServiceProvider
.guard
's api
driver to passport
in config/auth.php
.Full source code:
Upvotes: 3
Views: 3485
Reputation: 3220
I think you should review your code with the following steps.
Step 1: User
model has to use HasApiTokens
...
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
Step 2: Passport::routes
method within the boot method of your AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
...
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
Step 3: In your config/auth.php
configuration file, you should set the driver option of the api authentication guard to passport
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Step 4 (Optional):
If you want to consume your API from your JavaScript application, you need to manually send an access token to the application and pass it with each request to your application. However, Passport
includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken
middleware to your web middleware group in your app/Http/Kernel.php
file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
! You should ensure that the CreateFreshApiToken
middleware is the last middleware listed in your middleware stack.
Edit (2021/10/17):
You should try to add the auth middleware to $middlewareGroups
of your Kernel.php
protected $middlewareGroups = [
...
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'auth:api', //Need to add
],
];
Edit (2021/10/25):
I downloaded your code and debug it. When you debug it, you will get the following result:
Header JWT is not valid for JSON structure. There seems to be an incompatibility between the Laravel Passport
library and your system. You should check your system version (PHP, Laravel, etc). I will continue to investigate. If you have any new information, please let me know
Edit (2021/11/02):
Update your laravel/framework dependency to ^6.0 in your composer.json file. If installed, update your laravel/passport dependency to ^9.3.2 in your composer.json file.
https://laravel.com/docs/6.x/upgrade#updating-dependencies
According to Laravel 6.x
documentation, the version of Laravel Passport is from 9.3.2. Please try this version.
Upvotes: 4
Reputation: 76679
You've forgotten to run php artisan passport:keys
...so there may be no RSA key-pair available, which is crucial. Clients usually can be added with: php artisan passport:client
. And generally speaking, there is no default recipe for debugging Laravel middleware ...there only is xdebug
.
Upvotes: 0
Reputation: 737
You should add token bearer into your ajax requests. You can get it after successful login.
// laravel
use Illuminate\Support\Facades\Auth;
use App\Models\User;
public function login()
{
$credentials = request(['email', 'password']);
$user = User::where('email', $credentials['email'])->first();
if (!$user || !$token = Auth::attempt($credentials)) {
return response()->json(['success'=> false, 'error' => 'неверный логин или пароль', 'cr' => $credentials], 422);
}
return $this->respondWithToken($token);
}
// vue login
async function login(email, password) {
try {
const response = await axios.post('/auth/login', {email, password});
const token = response.data.token;
// some func to store token, I am using vuex mutations for this
storeToken(token);
}
catch(error) {
console.error(error);
}
};
// vue regular function
async function changePassword(newPassword) {
// get token from global storage, with vuex it will be like store.state.auth.token
const token = getToken();
await axios.post('/user/changePassword', {newPassword}, headers: { Authorization: `Bearer ${token}`});
}
Upvotes: 0
Reputation: 309
If you are using Api/oauth prefix AND add the auth:api middleware than you need to authenticate via Bearer tokens.
So it may be you have csrf token related issue so try below to disable it.
Passport::ignoreCsrfToken(true);
Upvotes: 0