symfony2/fos-user-bundle: Login User by Entity - session

I have a user entity in a symfony2 controller and i need to log that user in.
Apparently i do not understand how the process works with the Csrf Token and loging in a user.
What do i have to do to log in the user?

Having an user object you can login/authenticate a user programmatically
$token = new UsernamePasswordToken($user, $user->getPassword(),
"public", $user->getRoles());
$this->get("security.context")->setToken($token);
// Trigger login event
$event = new InteractiveLoginEvent($request, $token);
$this->get("event_dispatcher")
->dispatch("security.interactive_login", $event);
You need to have this classes included
use Symfony\Component\EventDispatcher\EventDispatcher,
Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken,
Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

Related

How to authenticate a user by its user id in Laravel in a custom middleware

How would you guys go about implementing something like this? I use Laravel as an API only. We have other framework where the login was implemented where it saves an httpOnly cookie (sessionId) after the user logs in. That's the main framework. We're migrating away from that old framework (Zend).
With the sessionId sent to Laravel from, say, a JS frontend, I'm able to lookup the current user based on the sessionId. That sessionId is then used to query the session database. I've created a middleware called "CheckForCurrentUser.php":
[..]
public function handle(Request $request, Closure $next)
{
// The reason for this is that the OPTIONS (request) does not include the cookie in the request.
$method = $request->method();
// SESSIONID is the name of the cookie created from the main framework
// once a user is logged in.
// SESSIONID is an exception in EncryptCookies.php
$sessionId = request()->cookie('SESSIONID');
if ($method === 'POST' && $sessionId !== '') {
// This function is only to get the logged in user id from the session database
$userId = $this->notImportantFunction($sessionId);
if ($userId) {
// User id found so make current user for this Laravel API
Auth::loginUsingId($userId);
} else {
// Instructs the frontend to let user log back in.
return abort(401);
}
}
return $next($request);
}
To recap, a user cannot authenticate from this Laravel application nor can I send an authentication token. They logged in from another framework. Laravel has access to the main framework databases.
This setup works. Using use Illuminate\Support\Facades\Auth; I use that as the "current user" in any controller/model.
Kernel.php looks something like:
[..]
protected $middleware = [
[..]
\App\Http\Middleware\CheckCurrentUser::class,
[..]
];
Before I go any further, is that how you'd implement something like this? It does work (ish) but I do not get the SESSIONID unless I check for a POST request.
I do not like this setup. I'm now using lighthouse and having issues using both the #auth and #inject directives. This is due to how I authenticate a use with Laravel so sorting how I authenticate a user should sort Lighthouse. Any tips on how to refactor this the right way? My routes are with /api/some-string
Lighthouse is not the issue. Should I send a authentication header, Lighthouse works. I believe Laravel does something behind the scenes with it sees a token in the header. I cannot send an authentication. I can only rely on the cookie. It's httpOnly so I have no access to that from JavaScript.

Laravel 7 loginUsingId not persisting / causing log out

I am trying to create a "Shadow" user feature, it's basically just to allow admins to log in as another user to use the system as the "shadowed user" would.
I've used Auth::loginUsingId before but i can't figure out why the below isn't working.
public function shadowUser($id, Request $request){
$user = User::query()->find($id);
$previousUserId = $request->user()->id;
Session()->flush();
Session()->put('shadow.user.id', $previousUserId);
$shadowedUser = Auth::loginUsingId($user->id);
dump(Auth::check());
return redirect()->route('home');
}
If I dump out the $shadowedUser it shows the correct user and the Auth::check() returns true.
I have also tried these but they made no difference: Auth::loginUsingId(1, true);, Auth::guard($guard)->loginUsingId($user->ID); and Auth::login($user, true);
There's no crazy middleware just laravel's defaults.
I've tried a few things like removing the session flush but it always just logs me out.
I found that Laravel sessions are a bit funky in this scenario, it looks like you're trying to log someone in when the session is already active, log the current user out, flush the session then log in the new user, this way it will tell Laravel that this is a new user signing in and reset the session.
In your script, once you've logged the user out, flushed the session and logged the new user in, add the previous users id to the new session otherwise it will get deleted then you'll be able to see the previous user who was logged in, or the person shadowing you in this case.
public function shadowUser($id, Request $request){
$user = User::query()->find($id);
$previousUserId = $request->user()->id;
Auth::logout($guard);
Session()->flush();
Auth::loginUsingId($user->id);
Session()->put('shadow.user.id', $previousUserId);
dump(Auth::check());
return redirect()->route('home');
}

how to check if user is authenticated with passport (get user from token using laravel-passport)

I am using Passport to log in users to a Laravel API endpoint, users get authenticated using their social accounts (google, facebook) using laravel-socialite package.
the workflow of logging users in and out works perfectly (generating tokens...Etc). The problem is I have a controller that should return data based on whether there is a user logged in or not.
I do intercept the Bearer token from the HTTP request but I couldn't get the user using the token (I would use DB facade to select the user based on the token but I am actually looking whether there is a more clean way already implemented in Passport)
I also don't want to use auth:api middleware as the controller should work and return data even if no user is logged in.
this is the api route:
Route::get("/articles/{tag?}", "ArticleController#get_tagged");
this is the logic I want the controller to have
public function get_tagged($tag = "", Request $request)
{
if ($request->header("Authorization"))
// return data related to the user
else
// return general data
}
Assuming that you set your api guard to passport, you can simply call if (Auth::guard('api')->check()) to check for an authenticated user:
public function get_tagged($tag = "", Request $request)
{
if (Auth::guard('api')->check()) {
// Here you have access to $request->user() method that
// contains the model of the currently authenticated user.
//
// Note that this method should only work if you call it
// after an Auth::check(), because the user is set in the
// request object by the auth component after a successful
// authentication check/retrival
return response()->json($request->user());
}
// alternative method
if (($user = Auth::user()) !== null) {
// Here you have your authenticated user model
return response()->json($user);
}
// return general data
return response('Unauthenticated user');
}
This would trigger the Laravel authentication checks in the same way as auth:api guard, but won't redirect the user away. In fact, the redirection is done by the Authenticate middleware (stored in vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php) upon the failure of the authentication checking.
Beware that if you don't specify the guard to use, Laravel will use the default guard setting in the config/auth.php file (usually set to web on a fresh Laravel installation).
If you prefer to stick with the Auth facade/class you can as well use Auth::guard('api')->user() instead or the request object.
thanks to #mdexp answer
In my case I can resolve my problem with using
if (Auth::guard('api')->check()) {
$user = Auth::guard('api')->user();
}
In my controller.

Symfony keep user logged after manual authentication

To authenticate manually a user I used the following code:
$user = new User($token, null, array("ROLE_USER"));
$token = new UsernamePasswordToken($user, null, 'secured_area', array("ROLE_USER"));
$this->get("security.context")->setToken($token);
$event = new InteractiveLoginEvent($request, $token);
$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
The problem is that when I change page (also same controller) I lost the token/session.
Sometimes I get this: There is no user provider for user "Acme\MyBundle\Security\User".
How I should configure the secured area with pattern: ^/?
secured_area:
pattern: ^/
Thanks
In FosUserBundle you can see an example of how to do Manual login correctly.

CakePHP 2.0 Automatic Login after Account Activation

I'm just working on the user management-component of our new project.
The plan is:
User registers on the page with minimal amount of account data (username, pass, email)
User gets an email with an activation link to activate the account
User clicks on the link and activates his account
The system logs in the user after automatically after activation and redirects him to kind of a dashboard with account information (last login, hi "username", etc.)
But there are some problems with the auto login. this is the part of the code i use:
<?php
...
// set userstatus to "active" and delete meta information "activation_key"
// then automatically login
$this->User->id = $id;
$this->User->saveField('modified', date('Y-m-d H:i:s') );
$this->User->saveField('status', 1 );
// $this->User->deleteActivationKey ....
$this->Auth->login($this->User->read());
$this->Session->setFlash(__('Successfully activated account. You are now logged in.'));
$this->User->saveField('last_login', date('Y-m-d H:i:s') );
$this->redirect(array('controller' => 'pages'));
...
This works so far, until you want to get information about the logged in user with the user() function of the Auth Component.
We're using this in AppController->beforeRender, to have user information application wide:
$this->set('auth', $this->Auth->user());
but after that auto login action, i'm getting undefined index notices. (e.g. by accessing $auth['id'] in a view). print_r() shows me only the username and hashed password of the current user.
If you login manually, everything works fine. it must be something with the automatic login after the account activation.
Seems to be a problem with the session? What am i doing wrong?
Found a solution after testing many variations.
Works now with:
$user = $this->User->findById($id);
$user = $user['User'];
$this->Auth->login($user);
Don't know why, i thought i tried this way already and that did not work.
Have you tried this? (CakePHP 2.x)
public function signup() {
if (!empty($this->request->data)) {
// Registration stuff
// Auto login
if ($this->Auth->login()) {
$this->redirect('/');
}
}
}
That simple!

Resources