Laravel auth loses session after redirect - laravel

Due to laravel's default auth system not working for my current project I used their manual authentication system. The authenticating works but after I redirect the authentication gets destroyed or it simply isn't getting stored properly.
My authController:
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
class manualAuthController extends Controller {
public function authenticate(){
if (Auth::attempt(['email' => $_POST['email'], 'password' => $_POST['password']])) {
// Authentication passed...
$user = Auth::user();
//return '$user';
return redirect("test2");
}
return 'Auth failed!';
}
}
My route to test if the authenticated user is still stored:
Route::get('test2', function(){
echo 'test2<br>';
$user = Auth::user();
echo $user;
return '.';
});
If I uncomment "return '$user';" then the authenticated user gets returned properly.
I know that this question has been asked before but I couldn't find anybody with a working/ reliable solution to this problem so can someone here please help me with this problem(or finding the exact problem)?
Side note: I previously used the Socialite system which we had to switch for the laravel auth due to hosting problems. After this switch it worked in development for a while with my current session and db settings. Due to some other bugs I switched to manual authentication.

Related

Create session on consuming login with api on laravel

I have an api that has a method to start and I am calling it from a frontend project.
In the front end project I use Guzzle to make the call via post to the api and login, from which I get back a json with the user data and a jwt token.
But when I receive the token as I manage the session, I must create a session and save the token, since the laravel to authenticate I need a model user and have a database, which of course I do not have in this backend because I call the api to log in, which brings a token and user data, then as I manage it from the backend, I'm a little lost there.
$api = new Api();
$response = $api->loginapi(['user'=>'wings#test.com','password'=>'123']);
Because here I could not do Auth::login($user) to generate the session.
Because I don't have here the database because the login is done from the api.
There I call the api, of which the answer is the token, but how do I manage it from here, creating a session? saving the token?
thanks for your help.
With api, you don't usually manage a session. usually, you'd call something like
Auth::attempt([
'email' => 'me#example.com',
'password' => 'myPassword'
]);
If the credentials are correct, laravel will include a Set-Cookie header in response, and, that is how you authenticate with api. Via an auth cookie. You don't need to do anything else.
Let's show you how:
//AuthController.php
public function login(Request $request) {
$validatedData = $request->validate([
'email' => 'required|email',
'password' => 'required'
]);
if(Auth::attempt($validatedData)){
return ['success' => 'true'];
}
else{
return ['success' => false, 'message' => 'Email or password Invalid'];
}
}
public function currentUser (){
return Auth::user();
}
Now, the APi file
Route::post('/login', ['App\Http\Controllers\AuthController', 'login']);
Route::get('/current_user', ['App\Http\Controllers\AuthController', 'currentUser']);
Now if you make a call to /api/current_user initially, you'll get null response since you're not currently logged in. But once you make request to /api/login and you get a successful response, you are now logged in. Now if you go to /api/current_user, you should see that you're already logged in.
Important ::
If you are using fetch, you need to include credentials if you're using something other than fetch, check out how to use credentials with that library or api
You want to use the API to authenticate and then use the SessionGuard to create session including the remember_me handling.
This is the default login controller endpoint for logging in. You don't want to change this, as it makes sure that user's do not have endless login attempts (protects for brut-force attacks) and redirects to your current location.
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
if ($request->hasSession()) {
$request->session()->put('auth.password_confirmed_at', time());
}
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
The core happens when we try to "attemptLogin" at
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->boolean('remember')
);
}
When using the SessioGurad (which is default) the method attemptLogin fires a couple of events, checks if the user has valid credentials (by hashing the password and matching it with db) and then logs the user in, including the remember me functionality.
Now, if you don't care about events, you can just check from your API if the credentials match and then use the login method from the guard. This will also handle the remember me functionality. Something like this:
protected function attemptLogin(Request $request)
{
$username = $request->input($this->username());
$password = $request->input('password');
$result = \Illuminate\Support\Facades\Http::post(env('YOUR_API_DOMAIN') . '/api/v0/login' , [
'username' => $username,
'password' => $password
])->json();
if(empty($result['success'])){
return false;
}
// Maybe you need to create the user here if the login is for the first time?
$user = User::where('username', '=', $username)->first();
$this->guard()->login(
$user, $request->boolean('remember')
);
return true;
}

Laravel - Pusher Authentication - Server Side

I'm working on an chat application with 2 components: a client side that is a mobile app and a server side that is developed with Laravel. Currently I can't seem to figure out how to do the pusher authentication side on the server for a user on a specific channel. After figuring the documentation I found that the authentication is done via js call from the frontend with the socket-id but for my application I need to do the authentication from the server because I'm keeping a history of the messages in a local DB. What I don't find is how can I do this on the server.
The code I use for authentication is just authenticating the client on db based on a key I created in the channel enrol:
public function authorizeUser(Request $request, $groupId, $conversationId) {
/*
$socket_id = $request->get('socket_id');
*/
$user = Auth::user();
$conversation = Conversation::find($conversationId)->where('group_id', $groupId)->first();
$user_conversation = DB::table('user_conversation')
->where('conversation_id', $conversation->id)
->where('user_id', $user->id)
->first();
if($user_conversation->authorized) {
return response()->json(['response' => 'You are authorized!'], 201);
}
$accessToken = Crypt::decryptString($request->get('key'));
//dd($conversation->access_token.' '.$accessToken);
if(Hash::check($accessToken, $conversation->access_token)) {
$conversation->users()
->wherePivot('authorized', false)
->updateExistingPivot($user->id,[
'authorized' => true
]);
// Some how, here I should authorize the user for pusher
return response()->json(['response' => 'You have been authorized!'], 201);
}
}
The documentation states that I should use the routes/channels.php file to authenticate the users but from the server side I can't use Laravel Echo for creating a connection. This is done automatically from the broadcast.php file where I have set the env for the pusher.
Thank you,
Armand

Login by code seems to not work in laravel

Basically i'm trying to send by email a link that lets you login with a specific account and then redirects you to a page.
I can seccessfully generate link and send them via email using URL functionalities in laravel using this code:
Generating the link:
$url = "some/page/".$travel_id;
$link = URL::temporarySignedRoute(
'autologin', now()->addDay(), [
'user_id' => 3,
'url_redirect' => $url,
]
);
And sending the mail:
Mail::send('emails.travel', $data, function ($message) use ($data) {
$message->from('mail#mail.com', 'blablabla');
$message->to('reciever#mail.com', 'blablabla')->subject('test');
});
There is a route that catches the link sent by mail that is supposed to log you in with the user (in this case, the one with the id '3') and redirect you to some page but when it redirects, it prompts you to the login page, as if you are not logged.
Here is the route:
Route::get('/autologin', function (Request $request) {
$user = User::findOrFail($request->user_id);
if (! $request->hasValidSignature()) {
abort(403);
}
Auth::login($user);
return redirect($request->input('url_redirect'));
})->name('autologin');
When i try to do a Auth::check() after the Auth::login($user); it returns true, so is the user logged in?
I also tried to use Auth::loginUsingId($request->user_id); with no different results.
Any idea of what's happening?
So i found the problem,
I was logging in with a backpack user but i was using the default auth feature of laravel.
Turns out i need to use: backpack_auth()->login($user); instead of Auth::login($user); if i want to login using a backpack user.
Also use backpack_auth()->check() instead of Auth::check().

Laravel 5.4 show activation pending message on login form

I am working on Laravel 5.4 project. I love the login provided by Laravel and it works fine with both login or register.
I add below code to Auth/LoginController.php. It allows only activated users (status=1) to successfully login, but not pending users or blocked users (status =0 or something else).
protected function credentials(\Illuminate\Http\Request $request)
{
return ['email' => $request->{$this->username()}, 'password' => $request->password, 'status' => 1];
}
Anyway, to protect spam I would like to allow only activated users to login. For those whose account are not activated, I would like to show the pending message on the login form. Also, I would like to do the same thing for blocked users.
Could you please advise me how to achieve this?
This way Laravel would only pick only users by the credentials you specify, if you want to check status the user has and what view to show you can overwrite the authenticated() method of the login controller. It will have access to the already logged in user so note that you have to logout it the status is invalid.
protected function authenticated(Request $request, $user)
{
if ( $user->status == 0 ) {
auth()->logout();
return back()->withErrors(['email' => 'You are blocked or not activated.']);
}
return redirect()->intended($this->redirectPath());
}

What is the difference between "login" and "attempt" method in Auth

I'm learning Laravel 5.4 and customizing and making my original Auth functionalities.
The below is my "authenticate" method.
public function authenticate(Request $request)
{
$remember_me = (Input::has('remember')) ? true : false;
Auth::guard('web');
$this->validateLogin($request);
$credentials = array(
'username' => trim($request->input('username')),
'password' => trim($request->input('password'))
);
if(Auth::attempt($credentials, $remember_me)){
$user = Auth::guard('web')->user();
Auth::guard('web')->login($user, $remember_me);
return redirect()->route('mypage');
}
return redirect()->back();
}
I have a question about the part of $remember_me argument about both attempt and login methods noted above.
What is the difference between them?
When I saw the documentation, it said similar to, if you want to make "remember me" token, you can set the second boolean argument about both of them.
attempt($credentials, $remember_me) will attempt to log the user in if the login credentials are correct. If they are not, then the user is not logged in. This method returns a boolean so you can check success.
login($user_id, $remember_me) will log the user in, without checking any credentials.
The remember me specifys if the user login should persist across browser sessions without needing to re-auth.
In your example I see your calling login(...) within your attempt(...). This shouldn't be needed. You can remove the login(...) line.
Example:
if(Auth::attempt($credentials, $remember_me)){
return redirect()->route('mypage');
}

Resources