Mê Cung config/auth.php: Tại Sao Auth::user() Luôn Trả Về Null?
Nếu bạn mở file config/auth.php của Laravel ra, bạn sẽ thấy nó không chỉ có một biến duy nhất. Laravel thiết kế hệ thống Auth giống như một tòa nhà an ninh với rất nhiều chốt chặn.
Nhiều anh em hay gọi tắt là default_auth_driver, nhưng thực chất trong cấu trúc của Laravel, nó là sự kết hợp của 3 khái niệm: Defaults -> Guards (chứa Driver) -> Providers.
Hãy cùng bóc tách từng lớp một.
1. Nút thắt đầu tiên: The defaults Array
Ở ngay đầu file config/auth.php, bạn sẽ thấy mảng này:
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
Đây chính là "Bộ não mặc định" của hệ thống.
Khi bạn gõ hàm Auth::user() ở bất kỳ đâu trong code mà không chỉ định rõ, Laravel sẽ nhìn vào đây và ngầm hiểu: "À, sếp muốn dùng Guard tên là web để xác thực, và nếu có reset password thì dùng cấu hình users".
Và đây chính là nguồn cơn của bug! Guard web được thiết kế mặc định để dùng Session/Cookie (dành cho website có giao diện). Nhưng Frontend lại đang gọi API của bạn bằng JWT/Bearer Token. Do "lệch pha" hệ tư tưởng, Guard web không tìm thấy Session, nên nó kết luận bạn chưa đăng nhập (dù token bạn gửi lên đúng 100%).
2. Guard & Driver: Anh bảo vệ và Công cụ kiểm tra
Kéo xuống một chút, bạn sẽ thấy mảng guards. Đây là nơi bạn định nghĩa các chốt kiểm tra an ninh.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token', // Hoặc 'sanctum', 'jwt'
'provider' => 'users',
],
],
- Guard (Cảnh vệ): Là tên gọi của cái chốt (ví dụ: chốt web, chốt api, chốt admin).
- Driver (Công cụ): Đây chính là cái auth_driver mà anh em hay nhắc tới. Nó quy định CÁCH anh bảo vệ kiểm tra bạn:
- driver => 'session': Anh bảo vệ sẽ lục tìm trong RAM/Redis xem có Session ID của bạn không.
- driver => 'token' (hoặc sanctum/jwt): Anh bảo vệ sẽ bóc cái Header Authorization: Bearer <token> ra để soi chữ ký (như bài JWT chúng ta đã học).
3. Provider: Người giữ sổ hộ khẩu
Dù anh bảo vệ có dùng Session hay Token, khi xác thực xong cái thẻ, anh ta vẫn phải tra cứu xem bạn tên gì, có bị khóa tài khoản không. Trách nhiệm đó thuộc về Provider.
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// Bạn có thể tạo thêm provider cho Admin
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
- Driver của Provider: Quy định CÁCH query Database. Thường là eloquent (Dùng Model) hoặc database (Dùng Query Builder trực tiếp cho nhẹ).
- Model: Trỏ đích danh bảng nào chứa thông tin (Ví dụ: bảng users hay bảng admins).
4. Vibe Coder "Độ" Config Như Thế Nào?
Khi bạn xây dựng một hệ thống Backend thuần API (Frontend dùng React/Vue hoặc Mobile App), việc để mặc định guard => 'web' là một sự cồng kềnh không đáng có.
Nếu không đổi, mỗi lần muốn lấy thông tin user, bạn phải code rất dài:
$user = Auth::guard('api')->user(); (Phải gọi đích danh tên guard).
Tuyệt chiêu nhàn hạ: Đổi luôn Default Guard!
Mở config/auth.php (hoặc sửa file .env nếu Laravel bản mới hỗ trợ):
'defaults' => [
'guard' => 'api', // Chuyển từ 'web' sang 'api' hoặc 'sanctum'
'passwords' => 'users',
],
Sau khi cấu hình như vậy, toàn bộ app của bạn sẽ tự động lấy Token làm chuẩn mực. Ở bất kỳ Controller nào, bạn chỉ cần gõ nhẹ nhàng:
$user = auth()->user();
$userId = auth()->id();
Code ngắn gọn, sạch sẽ, chuẩn "vibe" và không bao giờ bị dính cái lỗi 302 Redirect ngớ ngẩn nữa!
Lời kết
Framework sinh ra là để làm hộ bạn những công việc lặp đi lặp lại. Nhưng nếu bạn coi nó như một "hộp đen" ma thuật và cứ nhắm mắt dùng, nó sẽ sớm trừng phạt bạn. Việc hiểu rõ ranh giới và cách móc nối giữa Guard (Cách kiểm tra) và Provider (Nguồn dữ liệu) sẽ giúp bạn tự tin bẻ lái, thiết lập hệ thống Auth cho bất kỳ bài toán phức tạp nào (như App có 3 loại user khác nhau hoàn toàn: Admin, Merchant, Customer).
Chủ đề tiếp theo: Sanctum vs Passport - Đừng Mang Dao Mổ Trâu Đi Giết Gà
Nhắc đến API Auth trong Laravel, chúng ta không thể bỏ qua 2 cái tên đình đám do chính chủ Laravel tạo ra: Laravel Passport và Laravel Sanctum.
Nhiều anh em cứ thấy dự án API là auto cài Passport vì nghe tên nó "ngầu" và chuyên nghiệp. Nhưng thực tế cài xong, bạn bị ngộp thở bởi hàng tá các bảng Database rác sinh ra (OAuth2 clients, personal access tokens, auth codes...) trong khi App của bạn chỉ cần mỗi tính năng Login cấp 1 cái Token đơn giản!
Khi nào thì nên xài Sanctum (gọn nhẹ, nhanh chóng), và khi nào hệ thống của bạn mới thực sự cần đến quyền năng của Passport (OAuth2 chuẩn Enterprise)? Ở bài viết tới, chúng ta sẽ đặt 2 món vũ khí này lên bàn cân nhé! Anh em đón đọc!
All rights reserved