Razvan Zamfir
Razvan Zamfir

Reputation: 4616

What causes the "route not defined" error in this Laravel 8 API?

I am working on a registration form with Laravel 8 and Angular 13. The back-end is an API (link to Github repo). In the UserController I have a signin() and a signout() method

UserController

public function signin(Request $request)
{
    $fields = $request->validate([
        'email' => 'required|string',
        'password' => 'required|string'
    ]);

    // Check email
    $user = User::where('email', $fields['email'])->first();

    // Check password
    if (!$user || !Hash::check($fields['password'], $user->password)) {
        return response(['message' => 'Incorrect email and/or password'], 401);
    }

    $token = $user->createToken('secret-token')->plainTextToken;

    $response = [
        'user' => $user,
        'token' => $token
    ];

    return response($response, 201);
}

public function signout(Request $request)
{
    auth()->user()->tokens->each(function ($token) {
        $token->delete();
    });

    return [
        'message' => 'You have been signed out.'
    ];
}

routes\api.php

Route::post('/signup', [UserController::class, 'signup']);
Route::post('/signin', [UserController::class, 'signin']);

Route::group(['middleware' => ['auth:sanctum']], function () {
    Route::post('/signout', [UserController::class, 'signout']);
});

The problem

I get the error when I access https://mysite.test/api/signout in Postman.

Route [login] not defined.

Where is my mistake?

Upvotes: 2

Views: 2046

Answers (4)

MmrDev
MmrDev

Reputation: 31

in laravel 8 after modify route file (or config files) you must use php artisan optimize command

Upvotes: 0

Mostafa Bahri
Mostafa Bahri

Reputation: 2644

In your App\Http\Kernel.php

Replace

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
...

with

    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
...

But that alone is not gonna cut it.

In your App\Exceptions\Handler.php

add this method to the class

    protected function unauthenticated($request, \Illuminate\Auth\AuthenticationException $exception)
    {
        return response()->json(['message' => $exception->getMessage()], 401);
    }

The reasoning is behind how Laravel detects if the request shouldReturnJson when handling an AuthenticationException.

You indicate you want json response by sending
Accept: application/json (not Accept */*) request header.

Here's your scenario:

Your signout route is behind auth middleware. You're detected as guest (probably you're not sending the auth headers correctly?) and you don't want json response (the missing json Accept header). At this point Laravel redirects you to login by default.

Upvotes: 3

Muhammed Suhail
Muhammed Suhail

Reputation: 289

In headers(postman), add following key value

Accept : application/json

Upvotes: 2

dz0nika
dz0nika

Reputation: 1021

Its hitting the Authenticate Middleware where by default it redirects you to route('login'). This is because when you delete the token the user doesn't have access through auth:sanctum so it redirects the Unauthenticated user to the login route that doesn't exists. Just change the redirect in Middleware/Authenticate to signin/signout route.

Change the singout() in your Controller to this

Auth::guard($this->guard())->logout();

Request::session()->invalidate();

Request::session()->regenerateToken();

This will logout the user without hitting the Authenticate Middleware, it will return a json response of 204 or No Content. NOTE: just change your set guard instead of $this->guard() I recommend adding a private function inside of your UserController so you can get the correct guard every time and that would look like this

if(isset($this->guard) && $this->guard) {
    return $this->guard;
}

return config('auth.defaults.guard');

Upvotes: 1

Related Questions