Security Tip: Be Careful of Auth Helpers!
[Tip#20] Laravel's helpers are great, but make sure you know everything they do before you use them.
đ¤ Learn to Think Like a Hacker with my hands-on practical security course: Practical Laravel Security! đľď¸
â ď¸ Need a security audit but don't have the budget for a full penetration test? Book in a Laravel Security Review! đľď¸
Be Careful of Auth Helpers
(There is a TL;DR at the bottom - I donât want to ruin the suspense, but scroll down if youâre busy.)
Laravelâs Authentication system is incredibly powerful and coupled with the Auth
Facade, it makes it trivial to access the logged in user where you need to. However, you also need to be careful - this power and ease also opens up some huge risks you need to be aware of.
Within the normal login request flow, youâll authenticate the user once and theyâll still be logged in to each subsequent request, allowing you to access the user model easily via the Auth
Facade. But what if you have a special public or private URL that provides access to something within the user context for a single request, but isnât accessed by the user? You still need to access the user model easily but you donât want their session persisted into the subsequent requests.
Consider a draft post URL1 that the author can provide for unauthenticated users to view the draft. Itâs tempting to reuse code which calls the Auth
Facade, but then youâll need to effectively log the user to load the Auth Facade. So you may find yourself doing something like this:
public function view(Post $post)
{
Auth::loginUsingId($post->user_id);
return view('posts.preview', [
'post' => (new PostEditor($post))->readOnly(),
]);
}
It seems simple enough - youâre temporarily logging the user in so the post can be loaded in the user context, so you can reuse the same code.
Makes sense, right?
Nope!
The problem is `Auth::loginUsingId()`
logs the user in and initiates a session. The visitor is now logged in and will have full access to the user account on subsequent requests.
You never want to do this. Donât even consider doing it and then immediately logging out2! Just donât do it! Please!
I would highly recommend not using the Auth
Facade in this situation at all, instead, you should pass the User
model around where you need it. Itâs much safer as youâll know there is no chance of anything from the user persisting.
public function view(Post $post)
{
$user = $post->user;
return view('posts.preview', [
'user' => $user,
'post' => (new PostEditor($post, $user))->readOnly(),
]);
}
If you do need to use the
Auth
Facade to load the user within these special requests, you can safely use the`Auth::onceUsingId($userId)`
function. It loads the specified model as the current user for the current request only.
TL;DR â Donât use `Auth::loginUsingId()`
on guest URLs, it sets up a full authentication session and youâll be logging everyone in as that user.
For example, the draft post URL for this post is: https://larasec.substack.com/p/7652881d-0ca7-47a8-8253-f275837ab1ed
Session info and cookies may somehow be persisted, so this is a terrible idea.