Search code examples
phplaravelapiauthenticationlaravel-sanctum

Laravel - API login authentication check


As part of learning Laravel API, login and authentification I've created API login route which which works fine, user is loged-in and JSON response returns token that needs to be put into Bearer Token field and API resource movies route which allows CRUD operations.

I'm using Postman for testing and when I go directly to GET /api/movies route without login or pasting token into Bearer Token I cannot access this route which is desired outcome if user is not authenticated and got this message:

Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined. in file /home/****/Projects/movie-api/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 444

What I'm trying to do, instead of this message to return JSON response that user is not authenticated but don't know how or where to put that code.

I've tried with Auth:check() in api.php and in my AuthController, but could not make it work and could not find anything in Laravel documentation regarding this.

This is my api.php and AuthController.php:

api.php

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\MovieController;
use App\Http\Controllers\API\AuthController;

/*
|--------------------------------------------------------------------------
| 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('register', [AuthController::class, 'signup']);
Route::post('login', [AuthController::class, 'login']);


Route::middleware('auth:sanctum')->group(function() {
    Route::resource('movies', MovieController::class);
});

AuthController.php

<?php declare(strict_types=1);
   
namespace App\Http\Controllers\API;
   
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Validator;
use App\Models\User;
use App\Providers\MovieApiProvider\ApiResponseServiceProvider as ApiResponseService;
   
class AuthController extends Controller
{
    private ApiResponseService $apiResponseService;

    public function __construct()
    {
        $this->apiResponseService = new ApiResponseService;
    }

    public function signup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'email' => 'required|email',
            'password' => 'required',
            'confirm_password' => 'required|same:password',
        ]);
   
        if ($validator->fails()) {
            return $this->apiResponseService->responseError('Error validation', ['error' => $validator->errors()]);
        }
   
        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        $user = User::create($input);
        $success['token'] =  $user->createToken('MyAuthApp')->plainTextToken;
        $success['name'] =  $user->name;
   
        return $this->apiResponseService->responseSuccess($success, 'User created successfully.');
    }

    public function login(Request $request)
    {
        if (Auth::attempt([
                'email' => $request->email, 
                'password' => $request->password
            ])) { 
            $authUser = Auth::user(); 
            $success['token'] =  $authUser->createToken('MyAuthApp')->plainTextToken; 
            $success['name'] =  $authUser->name;
            
            return $this->apiResponseService->responseSuccess($success, 'User signed in');
        } else { 
            return $this->apiResponseService->responseError('Unauthorised.', ['error' => 'Unauthorised'], 401);
        } 
    }
}

Can someone help with this?


Solution

  • Laravel assumes you are using a browser, so when checking authentication, you are redirected to a login page. All you need is:

    Accept: application/json