Урок 12

Аутентификация: Sanctum

Что такое Sanctum

Sanctum — официальный пакет Laravel для аутентификации API. Он выдаёт токены, которые клиент отправляет в заголовке Authorization. В отличие от сессий, токены подходят для SPA, мобильных приложений и сторонних клиентов.

Установка

php artisan install:api
php artisan migrate

Команда install:api создаёт routes/api.php, устанавливает Sanctum и создаёт таблицу personal_access_tokens.

Настройка модели User

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens;
}

Трейт HasApiTokens добавляет методы для создания и управления токенами.

Регистрация

namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $data = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => ['required', 'confirmed', Password::min(8)],
        ]);

        $user = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);

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

        return response()->json([
            'user' => $user,
            'token' => $token,
        ], 201);
    }
}

Метод createToken возвращает объект, у которого свойство plainTextToken — сам токен. Он показывается один раз.

Логин

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

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

    if (!$user || !Hash::check($data['password'], $user->password)) {
        return response()->json(['message' => 'Неверные данные'], 401);
    }

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

    return response()->json([
        'user' => $user,
        'token' => $token,
    ]);
}

Пароль хранится в виде хеша. Проверка — через Hash::check.

Логаут

public function logout(Request $request)
{
    $request->user()->currentAccessToken()->delete();

    return response()->noContent();
}

Удаляется только текущий токен.

Защита роутов

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', fn (Request $r) => $r->user());
    Route::post('/logout', [AuthController::class, 'logout']);
});

Middleware auth:sanctum проверяет токен. Если его нет или он неверный — возвращает 401.

Отправка токена с клиента

Клиент добавляет заголовок:

Authorization: Bearer <token>

Пример на JavaScript:

fetch('/api/user', {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: 'application/json',
  },
});