Laravel, get currently logged-in users - authentication

I want to display a list of currently logged-in users in an app. I want to use Laravel Auth method. I'm looking at the API and I cannot find anything like it.
I would probably need to loop through the sessions store and then match it to a user ID. Am I right?
UPDATE: Forgot to mention, I'm storing sessions in the DB.

"Currently logged in" is something you can't do with plain old sessions. Let me explain why:
A session is a bunch of data stored at server side which is assigned to an user through a cookie. That cookie remains on user browser and so it keeps the session active. Sessions can stay "alive" months without the user even logging in.
But, it's possible to store sessions on database.
As you can see, Laravel keeps a field called last_activity and, through that field, you should be able to retrieve all sessions that had activity within the last 15 minutes (or something else, you call it).
When your retrieve those records, the data field is a serialized representation of session data. You can unserialize($session_record->data) and retrieve the user id.
Depending on your Auth driver, session's user id may have different names:
For eloquent driver, it should be eloquent_login.
For fluent driver fluent_login.
For your Custom\AuthClass, it should be called custom_authclass_login.

Assume that all http requests from logged in users are passing auth middleware, we can override terminate function like following:
public function terminate($request, $response)
{
Auth::user()->save();
}
Then a query like User::where('updated_at', '>', Carbon::now()->subMinutes(12))->get(); will bring all logged in user, where 12 is the lifetime of session.
Of course, for real time, we should use ajax calls every 5 seconds or websockets via pusher or other.

First create a table where the logged in user's id will be inserted
Schema::create('active_users', function(Blueprint $table)
{
$table->increments('id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
Then in yourcontroller insert data while logging in
if (Auth::attempt($credentials)) {
DB::table('active_users')->insert(array('user_id' => Auth::id()));
}
and delete the data while logging out
DB::table('active_users')->where('user_id', '=', Auth::id())->delete();
Print the online users list in your view
<ul><strong>Online Users</strong>
<?php $online_users = DB::table('active_users')->where('user_id','!=',Auth::id())->get(); ?>
#foreach($online_users as $online_user)
<li>{{User::find($online_user->user_id)->first_name}}</li>
#endforeach
</ul>

Related

How to implement concurrent session filter in grails to handle multiple login session?

For example: Suppose user "testuser#xyz.com" is login from one browser and performing some works. at the same time someone else login with same user "testuser#xyz.com" from another browser/machine in that scenario, i want to implement following ways
if the first logged-in user is not performing any action(inactive condition) from last 3-4 mins then first user will logged-out and second user will logged-in successfully.
If the first logged-in user is performing some task (active condition) then first user should get notification that, someone trying to logged-in from another browser/machine are you agree to allow ? if first user will allow then only second user will able to login(and first user should logout) otherwise not.
Any help is much appreciated.
This is not exact solution to your problem, but definitely it will give you the clue.
In your /grails-app/conf/spring/resources.groovy
//To enforce/restrict one session per user Starts
sessionRegistry(SessionRegistryImpl)
concurrentSessionFilter(ConcurrentSessionFilter, sessionRegistry)
registerSessionAuthenticationStrategy(RegisterSessionAuthenticationStrategy, ref('sessionRegistry')) {}
concurrentSessionControlAuthenticationStrategy(ConcurrentSessionControlAuthenticationStrategy, ref('sessionRegistry')) {
exceptionIfMaximumExceeded = true //False
maximumSessions = 1
}
sessionFixationProtectionStrategy(SessionFixationProtectionStrategy) {
migrateSessionAttributes = false//true
alwaysCreateSession = true//false
}
sessionAuthenticationStrategy(CompositeSessionAuthenticationStrategy, [concurrentSessionControlAuthenticationStrategy, sessionFixationProtectionStrategy, registerSessionAuthenticationStrategy])
//To enforce/restrict one session per user Ends
Source : searchcode.com

ASP.NET Core clear session issue

I have an application where I save some information on the session that later I assign to the model when I save it to the DB.
For example I have the following model saved by User1:
...
MyModel model = new MyModel();
model.name = mypostedModel.name;
model.type = HttpContext.Session.GetString("UniqueTypeForThisUser");
...
After I save the model in my DB, at the end of the post method, I clear the session with this line:
HttpContext.Session.Clear();
Let's say at the same time there's a User2 creating a new model and I have saved another value in the session with a unique key for User2. Same way as before, at the end of the post method I clear the session with the Clear() method.
Does this clear session method clear the session for all users, or only for one user. If for example User1 saves the model first and clears the session for all users, then the User2 will get his session variable cleared (lost) and will assign a null value to my 'type' column for the model.
For the documentation this was not clear for me. Thanks
You Can remove specific keys
HttpContext.Session.Remove("YourSessionKey");
The session object that you can access for example through HttpContext.Session is specific to a single user. Everything you do there will only affect the user that belongs to this session and there is no mix between sessions of other users.
That also means that you do not need to choose session configuration key names that are somewhat specific to a user. So instead of using GetString("UniqueTypeForThisUser"), you can just refer to the values using a general constant name:
var value1 = HttpContext.Session.GetString("Value1");
var value2 = HttpContext.Session.GetString("Value2");
Each user session will then have these values independently. As a result, calling Session.Clear() will also only clear the session storage for that session that is specific to its user.
If you actually do need different means for storing state, be sure to check out the docs on application state. For example, things that should be stored independently of the user can be stored using an in-memory cache.
Does this clear session method clear the session for all users, or only for one user.
The HttpContext is the one for the current request. Since every user has a different request, it follows that clearing the session on the current request only clears it for that request's user, not all users.

Express REST API with JWT and Routes

I am trying to create an Express API with JWT authentication.
However, I was wondering how to best allow users to only access their own resources.
For example if there is a user with id 1 and each user has a list of books in the database:
The id is already part of the JWT Token but commonly there would be a request to something like /users/1/books to get all of the books belonging to user 1.
Would my routes typically still look like this and I would just check the id in the token is the same the request is made for, or is there any other/simpler way?
Thank you for your help!
You can define, some access rights permissions base on the user role or id.
Example: roles : {root, admin, staff}
Then, in your routes you can have some checking whether this user have the permission to access the functions or you can do in the controller level to check the access rights.
You need to define model relations between User, UserModel. In your case as I understand you need to have the relations between UserModel and BooksModels.
UserModel hasMany BooksModel
When you call findOne() to retrieve specific user's data, you can just define include: 'aliasModelName', to retrieve the users related book data.
With this way, you can only have 1endpoint users/:id to retrieve users data and book data. It depends on what you really want, you can also have an endpoint users/:id/books to get all books that belongs to this user.
Your model definition will then become
BooksModel belongsTo UserModel
If you use hasMany you can get all the results that you need in just one query.
Hope this helps!
When user sends the login credentials, you check database if the email exists, if yes then you check if the password matches. If user successfully signins you create the token.
const token = jwt.sign({ _id: user._id, email: user.email }, "this-is-secret", {
expiresIn: "1h",
});
this token is sent to the browser, whenever user make requests, it manually attachs this token to the req, and sends the request to your server. You check if the token is valid, by using the secret key (in this case "this-is-secret").
const decodedToken = jwt.verify(token, "this-is-secret")
req.userId = decodedToken.userId;
now "userId" is attached to the req object. Now when you fetch the data from database, the items that you are fetching, you write a query that (implementation depends on which database you are using)
book.userId=req.userId

Does Laravel query database each time I call Auth::user()?

In my Laravel application I used Auth::user() in multiple places. I am just worried that Laravel might be doing some queries on each call of Auth::user()
Kindly advice
No the user model is cached. Let's take a look at Illuminate\Auth\Guard#user:
public function user()
{
if ($this->loggedOut) return;
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
As the comment says, after retrieving the user for the first time, it will be stored in $this->user and just returned back on the second call.
For same Request, If you run Auth::user() multiple time, it will only run 1 query and not multiple time.
But , if you go and call for another request with Auth::user() , it will go and run 1 query again.
This cannot be cached for all request after first request has been made due to security point of view.
So, It runs 1 query per request irrespective of number of time you are calling.
I see use of some session here to avoid run multiple query, so you can try these code : http://laravel.usercv.com/post/16/using-session-against-authuser-in-laravel-4-and-5-cache-authuser
Thanks

nhibernate 'save' -> 'get' problem

HEllo,
I'm using nhibernate and have problems regarding user registration on my site.
When user wants to register I create new user record in the database and immidiatelly after that the system is logging the user in.
Well here lies the problem... When creating user record I'm using
NHibernateSession.Save(entity); //does not saves user object immediately to the database. It's kept in the session.
And when I want to log the user in, i load the user by his user name, and then I get null user object.
Why am I getting a null object and how can I make it work?
Thanks
Ok, I just tested this :
ISession session = s.CreateSession();
User user = new User();
user.Number = 122;
user.UserName = "u";
user.Id = 1;
session.Save(user);
User user1 = session.CreateCriteria<User>().Add(Restrictions.Eq("UserName", "u")).UniqueResult<User>();
session.Flush();
First the Select is being executed from the CreateCriteria and then on Flush the insert. So that's why it's not finding anything.
I also tested with Get<User>(1) and it returns the entity passed to the Save method - no query is executed.
Still - why query the database since you have the entity right there ?
Also, you say you use Get and then say you want to load by the UserName - is the UserName the primary key ? Get tries to load by the primary key.
If your Save and Get are done from different sessions then the Get will return null because the object only exists in the other sessions internal cache until it is flushed.
I'm not sure if an L2 cache would make a difference (I don't if L2 cache is written at Save or Flush).