Аутентификация и авторизация

Auth, guards, Gates и Policies, Sanctum, токены.

Junior Как хранятся пароли и как правильно их проверять?

Пароли хешируются bcrypt (по умолчанию) или argon2 через фасад Hash:

use Illuminate\Support\Facades\Hash;

$user->password = Hash::make('secret');         // bcrypt с salt
Hash::check('secret', $user->password);          // проверка — НЕ сравнение строк!
Hash::needsRehash($user->password);              // пора ли перехешировать (смена cost)

В модели User из коробки:

protected $casts = ['password' => 'hashed'];   // автохеш при присвоении

Важные правила:

  • пароль никогда не хранится в открытом виде и не логируется;
  • сравнивать только через Hash::check() (timing-safe);
  • Auth::attempt() сам хеширует и сверяет — вручную Hash::check обычно не нужен;
  • password должен быть в $hidden модели.

Политика паролей при регистрации: правило Password::min(8)->mixedCase()->numbers()->uncompromised() (проверка по haveibeenpwned).

Junior Что произойдёт, если не защитить маршрут? Как организовать роли?

Маршрут без middleware auth доступен всем — типичная ошибка новичков. Проверка в самом контроллере (if (!Auth::check())) дублируется и забывается — используют middleware:

Route::middleware('auth')->group(function () {
    Route::get('/dashboard', ...);
});

Роли — простой вариант (колонка role):

Route::middleware('can:view-admin')->group(...);
Gate::define('view-admin', fn (User $u) => $u->role === 'admin');

RBAC (роли + разрешения в БД) — обычно пакет spatie/laravel-permission:

$user->assignRole('editor');
$user->givePermissionTo('publish posts');
$user->hasRole('editor'); $user->can('publish posts');
Route::middleware('role:admin|editor')->group(...);
@role('admin') ... @endrole

Граница ответственности: аутентификация — кто ты (логин), авторизация — что тебе можно (gates/policies). Не путать на собеседовании.

Junior Как работают подтверждение email, сброс пароля и remember me?

Email verification: модель реализует MustVerifyEmail, маршруты — middleware verified:

class User extends Authenticatable implements MustVerifyEmail { ... }
Route::get('/profile', ...)->middleware(['auth', 'verified']);

Laravel шлёт письмо с подписанной ссылкой (signed URL), обработчик помечает email_verified_at. Событие — можно слушать Registered / Verified.

Password reset: встроенный flow «забыл пароль»: генерируется токен (таблица password_reset_tokens), письмо со ссылкой, форма смены. Всё из коробки у Breeze/Fortify.

Remember me: Auth::attempt($credentials, remember: true) — отдельная долгоживущая cookie с токеном (колонка remember_token). При истёкшей сессии пользователь автоматически перелогинивается. Токен ротируется при каждом использовании — защита от кражи cookie.

Все три механизма не нужно писать руками — важно знать, как они устроены и как кастомизируются (уведомления toMailUsing, брокеры паролей).

Middle Как устроена аутентификация в Laravel: guards и providers?

Конфиг — config/auth.php. Две концепции:

  • Guard — как пользователь аутентифицируется в запросе: session (куки + сессия) или token/sanctum (API-токен);
  • Provider — откуда берутся пользователи: eloquent (модель User) или database (Query Builder).
'guards' => [
    'web' => ['driver' => 'session', 'provider' => 'users'],
    'api' => ['driver' => 'sanctum', 'provider' => 'users'],
],

Основные операции:

Auth::attempt(['email' => $email, 'password' => $pass]);        // логин
Auth::attempt($credentials, remember: true);
Auth::user(); Auth::id(); Auth::check();
Auth::logout();
Auth::login($user);                      // вручную
Auth::guard('admin')->user();            // конкретный guard

Middleware auth (редирект гостей), guest. Rate limit логина — throttle / RateLimiter в Fortify/Breeze.

Стартер-киты: Breeze (Blade/Inertia/Livewire/API), Jetstream (команды, 2FA), Fortify (headless-бэкенд аутентификации).

Middle Gates и Policies: в чём разница и как применять?

Gate — простая проверка «может ли пользователь выполнить действие», обычно не привязанная к модели:

Gate::define('view-dashboard', fn (User $user) => $user->isAdmin());

Gate::allows('view-dashboard');
Gate::authorize('view-dashboard');        // или 403

Policy — набор правил для конкретной модели:

php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
    public function viewAny(User $user): bool { ... }
    public function view(User $user, Post $post): bool { ... }
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }
    // before() — супер-правило: return true для админа
}

Применение:

$this->authorize('update', $post);            // в контроллере
Gate::authorize('update', $post);
$post->user->can('update', $post);
Route::put('/posts/{post}', ...)->middleware('can:update,post');
@can('update', $post) <a href="...">Редактировать</a> @endcan

Ресурсные контроллеры: authorizeResource(Post::class, 'post') связывает методы контроллера с методами policy автоматически.

Middle Laravel Sanctum: что это и когда использовать вместо Passport?

Sanctum — лёгкая аутентификация для API и SPA:

  1. API-токены (для мобильных приложений, сторонних клиентов):
$token = $user->createToken('mobile', ['posts:read'])->plainTextToken;
// клиент: Authorization: Bearer <token>
$request->user()->tokenCan('posts:read');
  1. SPA-режим — stateful-аутентификация по cookie для фронта на своём домене: Sanctum выпускает CSRF-cookie (/sanctum/csrf-cookie), дальше работает обычная сессия.

Sanctum vs Passport:

Sanctum Passport
Сложность минимальная полноценный OAuth2-сервер
Токены простые Bearer OAuth2 access/refresh
Сценарий свои SPA/мобильные приложения сторонние клиенты, authorization code flow, гранты

Правило: если не нужен полный OAuth2 (чужие приложения получают доступ к данным ваших пользователей) — берите Sanctum. Passport — когда вы сами OAuth-провайдер.