I'm searching for a solution to allow a user to be logged in only once at the same time. I'm new to Laravel and in this case I'm using it nearly out of the box (file session driver and default auth-handling with custom views).
My idea is to 'reset' the auth for a user after he logs in a second time, to automatically make all other active sessions invalid.
So my primary question is: Is there a way to accomplish this with some Laravel magic or do I need to invent this feature myself?
What you also could do is the following:
In your usertable, add one column:
sessionID (varchar or text)
Now what you want to do here is the following:
When a user logs in, store the ID of the session in the sessionID field. Everytime the user loads a page, or makes a request, check if the sessionID value in the DB is the same as the sessionID of the user that is logged in. If it isn't, kill the session and make him login again.
Now, when a user logs in, check the usertable if the sessionID value is already filled. If so, change it to the new sessionID. The result will be that all requests with the old sessionID will be invalid (because of your check) and the user can only access your webapp/website with the new session.
Thus this makes sure that your user is authed uniquely.
Related
I know this is a recursive question, but, I haven't found a new solution, or a solution based on the new frontend frameworks or technologies.
I've a Vue + PHP application that users can olny log once per time. My current solution to block concurrent access is making a call to a PHP page with Ajax from 5 to 5 minutes storing the time. I store a flag in DB too, whether it has been registered or not. So, when the user try to log in, I check if the time is greater than 6 minutes or the flag is set to 0.
I think this is not the best way to do this. When the application has too many users it can cause too much load on the server.
There is a way to do like Netflix? An warn when triyng to connect and was logged in another machine.
If your end goal is to have it so that any given account can only be logged into one machine at a time, generate a unique ID at login and write that ID to the database for that user. Set that ID as a cookie for the user. When you receive traffic from that user, only consider them logged in if their cookie matches the value in the database.
When the user logs in to a new device, a new unique ID is generated and sent as a cookie to that new device. The new device's traffic has a cookie that matches the database, and is therefore considered logged in. When the old device visits your application, the login cookie no longer matches the value in the database, so that user is considered logged out.
When the old device logs in again, a new unique ID is generated in the database and sent as a cookie to that device. They are now logged in, because their cookie matches. The second device, having its cookie no longer match the database, is logged out.
This solution doesn't require you to access the database on every page, reducing database load significantly.
Add a field for sessionID to your user table in the database.
Set the default session handler before calling session_start() (needed for the next line of code to work):
session_set_save_handler(new \SessionHandler());
On every successful login, retrieve the stored $sessionID from the database. Destroy the old session with:
(new \SessionHandler())->destroy($sessionID);
Get the new session ID with:
$sessionID = session_id();
Store the new session ID to the database.
I am looking at the possibilty to set up a option to keep users logged in. Now I understand a session could be used to allow a user to navigate around without re-entering login information on each page only until the browser is closed and the session is lost. A cookie would be stored client side and has a duration until it expires or the user deletes the cookie.
I was thinking that I could use a combination of both
Create a db table (id,user_id,cookie_token,is_active)
User logs in which creates a row in the db table connecting the user to the cookie_token which is stored on the client browser (system) as well.
Each time a token is created, check to see if the user the token is being created for has any active tokens in the system already and set those to inactive before a new one is created.
Only one token can be active per user
So every time the user visits the site, the system looks up that token and checks is_active fields,
If the user_token is found and is_active = 1 or true, the user data is retrieved (id,name,etc) and this then creates the session and the session variables.
I am not able to find any questions or answers that use a combination of both so it could be that this is just overkill or a very bad idea, I just started to read up on sessions and cookies and have been trying to figure out a system that I could implement myself so would be nice to know if this is good or bad.
I can't reply as a comment anymore, because my reply would be too long...
I've implemented something like follows. Unfortunately I can't remember it precisely, but it would give you a pretty good idea:
Visit before manual login:
Start a session.
At successful login, store a user identification into this session and store a token value into the dB and into the cookie.
Next time the browser visits the page:
(re)Start the session.
Check if a user identification is set in this session.
If so, auto-login the user which matches the identification.
If not (session expired due time restriction or browser close), check if a token value is stored in the cookie and if this value matches a token value stored in the dB.
If an (unexpired) match found, auto-login the user and remove old tokens.
If the user identification is invalid and the token value is invalid/expired:
logout the user (which contains all actions to go back to "public" mode like destroying the session, removing tokens, cookies, etc.).
As a admin i want to logout specific user from application.
I tried following code to make user log out from application.
Auth::logout();
But instead of logging out that specific user it makes admin logout.
I am getting session id from server, now I am confuse how can I pass that session id to clear that specific users session so that specific user gets log out.
You can't do that as all Auth:logout do is to delete the session cookie.
Of course you can't access cookies of other users.
Depending on your session driver, you may be able to invalidate the session server side.
For example if the driver is database, it can be as simple as a DB query to delete the session id (but well, you'll have to parse ALL sessions payloads to find the correct user id)
One simpler way to go is to add a session_token field to your user table. On login, you generate a random value and store it both in session and in database. Then in a middleware, check whenever the DB's session_token match with the one in the session.
To logout an user, simply reset the token in the DB and here we go !
Might something like this can help you.
let me know
$userToLogout = User::find(1); // Any userId you want to logout
Auth::setUser($userToLogout);
Auth::logout();
You can create a new column in your users table called force_logout for instance. Then on every request (in your authentication middleware), check this force_logout. Then you can log the user out with Auth::logout(); IF force_logout is 1.
So if you wanna log any user out, you just need to make force_logout of the user 1.
I've created a webservice, on which users can log in sending an oauth token. As response, this webservice returns a PHPSESSID cookie to keep the user logged in.
However, if you do log in several times, a new ID is generated each time. Examples:
ts1i3plmdcnmoivai637a27oe1
bhn1snms8kajmpo8ape5e5ctj3
d5467idr1ree9dcq6h9cqt9oj2
en2vbo1r62fqmrriid8l4rkvd3
All those 4 ID's are valid.
Is there any way make this sessid unique per user? So for example, when ID#4 is generated, previous 3 are discarded. Then I could handle a 403 error or whatever.
On the other hand, a second question:
Is it possible to make this PHPSESSID token longer?
If you want that then it's better to use your own cookies instead of php sessions.
You'll need to generate a random cookie key when someone log in, I'll call that random cookie key as cookie_id.
Then you need to store it in the database with the user_id it's connected to, so you can make a new table in database called sessions, with cookie_id and user_id fields (user_id needs to be unique), or you can extend your user table with cookies_id field.
After saving the cookie_id value with it's related user in db, you'll give that cookie_id to that user through cookies.
You can verify logged-in user with his cookie_id.
When logging out cookie_id will be null in db.
When another login happen, new cookie_id will be written over the old cookie_id in db.
That's it
Also You can set the period of your cookie with the expire parameter: http://php.net/manual/en/function.setcookie.php
For more security you can make cronjobs to delete cookie ids from db after some period of time. (You'll need to store the login date to do so)
I am developing the user management portion of a website that will host a webcast. The goal is to prrevent the same user nam (email address) from being used concurrently. That is, we don't want two individuals using one login to view the event.
I've already setup a table that holds the user registration data with regID as primary key. My thought is to create a login history table with username as primary key, foreign key to user name in registration table. The login history table would simply timestamp when the user logs into the site. However, this won't accomplsih my goal of preventing more than one individual from using the same login name.
Instead, would it be better to have a login status field either in the login history or user table that is set to 1 for logged in and 0 for logged out? It would need a stored procedure to update the value at login and at logout, and would need to be validated when a user logs in such that if login status = 1, user already logged in and cannot login a second time. Is this a feasible approach?
Please share other methods you've used to prevent the same login credential from being shared amongst multiple individuals.
Thanks,
Sid
If it is OK to logout an already logged in user if someone else logs in with the same credentials then you could do the following: when a user logs in generate a random ID in your database for that user and the same in a cookie session. The two must match to authenticate.
Without rolling your own session handler, you could do a little parallel tracking. When a user logs in, you can store the user's session ID and login time in the database (maybe inside the user information table). The login script could then check for the existence if this sessionID and allow/deny login based on the presence of the session ID. If the ID's null/blank, then the user logs in. If there's a session ID present, and it's more than X minutes old, allow the login. Otherwise deny them.
Of course, you'd probably want to roll your own session cleanup handler at that point, so that when stale session files get deleted, you can remove the associated IDs from the database at the same time.
The problem here is detecting the user is logged in (i.e. whether he didn't logout).
One possible way is to register in the database the time of his last activity and the time of his explicit logout. You could then deny a login if it this was attempted less than say 5 minutes ago relatively to his latest activity and if he didn't login in between.
You could force "activity" by having the website pages periodically poll the server with Javascript.
It's easy to determine when someone logs in. It's much harder to determine when someone logs out. If you have a mechanism of killing the webcast streaming to a particular user quickly, you might want to have something which pops up asking the user if they want to kill their other session if you think there might be one active.
How are you doing user sessions on the server? If you store them in the db, you could query the active sessions anytime someone attempts to log in and see if they're already in there. Of course you'd probably also have to check some kind of timestamp since you're not guaranteed that sessions will disappear at session.gc_maxlifetime.
You might want to consider making a global variable in php to store a hash array with login status. This has the benefit that if the application has to be restarted for some reason, the user isn't stuck in the wrong state in the database.
You can store a mapping from user ID to IP or session cookie and redirect requests that come with different information to the login page. If the user logs in, the other session would be invalidated and further requests in the last session forward to the login page.