I am running two linux instances behind an ELB. My app has facebook login as a way of signing up. On the live environment, the user signs up from one instance, session is created for that but the redirection happens on the second instance a lot of times resulting in null session from facebook as that session is there on the first instance.
Help me fix this. This is very crucial to our product.
Arguably, the most correct answer is that you should not design web applications without a proper session database that is accessible to all of the web application servers.
However, ELB provides a workaround for this oversight, known as "sticky sessions" (or "session affinity").
By default, a load balancer routes each request independently to the application instance with the smallest load. However, you can use the sticky session feature (also known as session affinity) which enables the load balancer to bind a user's session to a specific application instance.
http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/US_StickySessions.html
Of course, if an application server fails, or is taken offline for maintenance, your user still has an invalid session... but for the most part, this feature should accomplish what you want.
Related
I am setting up a socket.io server to handle, well, socket requests. This is running on port 1234. This is running along side a laravel 5.1 application. Laravel is using redis to handle sessions.
I have plenty of tutorials on hooking up laravel with socket.io, it's all pretty straight forward. I can connect, respond and forward messages back down the socket and to the laravel application.
However every tutorial avoids the auth part of this setup. Once the message is received within the socket:1234 space, how do I forward that message through to laravel while making sure that request is auth'ed.
Ideally I would simply share the session, and verify the XSRF token. Because the two applications are on different ports, I can't pick up the session directly.
Currently I am using an alternative approach, it involves the following:
Upon socket connection (in node), I decrypt the cookie sent up on connection using node's Crypto library and node's PHPUnserialise library.
This gives me the laravel session id (from the cookie)
I use this to access the redis laravel session
I then decrypt that session, which in turn, gives me access to the user id
It works, but I feel it could be potentially be a security hole, because I am not actually using _token to verify the origin.
I think your code is the right, and maybe the only way to do it.
A session_id is usually stored in the cookie, and at some point has to be sent to the server. Since node and php are different languages, they cannot share a session directly. You always need a intermediate storage like redis, mysql or filesystem. And of course a way to retrieve the session. The key to retrieving a session is of course the session_id.
An interesting post about securing websockets:
https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html
What he suggests is to add a random generated key to your session, that you can verify when you the websocket connection is established.
The session_id itself is already random, but these session_id's are usually long-lived, so a short-lived random id could increase security. Short-lived should be as short as possible: let php add it to the database, and once the connection is verified in node, remove it from the database, so you cannot use it again.
There are lots of additional session verification techniques, like checking the browser string, or fixating a session to one ip adress:
http://phpsec.org/projects/guide/4.html
I would not recommend these type of checks, as they don't really add much extra security, only annoyance with the end user.
Most importantly i think is that:
You use a secure way of communicating session_id etc. This means HTTPS
Sessions should expire when the user closes their browser
User should be notified if he connects from a different location, or should have access to his "login log"
I had found a good solution for this about a year ago. I decided to make it a module, its really easy to use. helps you get the cookie without hard coding it. helps you get that session Id and retrieve it from mysql and redis
https://www.npmjs.com/package/node-laravel-session
I'm writing a JQM web app with a PHP web service. Users will be able to sign-in and register that they've made a purchase of, for instance, a soda from the club. This info will be stored in a database and eventually billed.
To illustrate what I want to do: I have already implemented this as an Android app. My "session handling" in the Android app consists of simply storing the user's credentials in Android's savedPeferences (persistent local storage) upon succesful authentication with the server. These credentials are then resent with every subsequent server request so that users only ever have to sign-in once - upon running the app for the first time.
I want to mimic this behavior in my JQM app as closely as possible. Ideally, the user should only ever have to sign in once unless they choose log out.
I'm a bit rusty when it comes to website programming, so what would be the best approach? Non-expiring cookings? Do I use a PHP session or handle everything in javascript?
This is for a hobby project; I prefer a simple solution over something overly secure and complex. Thanks!
Edit: After reading Mike's answer I stumbled across this plugin: https://github.com/carhartl/jquery-cookie
Perhaps this is the easiest way to keep users logged in..?
PHP sessions are going to be invalidated after a set amount of time (depending on your php.ini settings or any runtime modificatoins to the settings).
You can use long-time expiring cookies to persist a login (typically user is given checkbox at login to allow their login credential to be stored).
Since you are developing for a mobile device, you do also have the alternative of using HTML5 local storage since most every Android browser out there supports it. See more info at the link below.
HTML5 Local storage info
I prefer this as the login hash could be persisted even if the user clears their browser cookies and it can be handled strictly within Javascript.
I run a computer lab for grade schoolers (3-14 y.o.) and would like to create a desktop/dashboard page consisting of a number of iframes, each pointing at a different external website
(for which we have created individual accounts for each child); and when a kid logs in (to the dashboard) a script will log her in to those websites, so she does not have to.
I have 1 server and 20 workstations, I'll refer to them as 'myserver' and 'mybrowser'(s) respectively. All these behind the same router (dynamic IP).
A kid gets on a 'mybrowser' workstation, fires up Firefox and runs desktop.php (hosted in 'myserver') and gets a login screen (for 'myserver')
'mybrowser' ---http---> 'myserver'
Once logged in, 'myserver' will retrieve a set of username and password stored in its database and run a CURL script to send those to an 'external web server'.
'mybrowser' ---http---> 'myserver' ---curl---> 'external web server'
SUCCESSFUL, well, I thought.
Turns out CURL, being run off 'myserver', logs in 'myserver' instead of 'mybrowser'.
The session inside the iframe, after refresh, is still NOT logged in. Now I know.
Then I thought of capturing the cookies from 'myserver' and set it into 'mybrowser' so that 'mybrowser' can now browse (within the iframe)
as a logged in user. After all, we (all the 'mybrowsers') are behind the same router as 'myserver', thus same IP address.
So in other words, I only need 'myserver' to log a user in to several external websites all at once ,and once done pass the control over back to individual users' browsers.
I hope the answer will not resort to using CURL to display and control the external websites for the whole session, aside from being a drag that will lead to some other sticky issues.
I am getting the nuance that this is not permitted due to security issues, but what if all the 'mybrowsers' and 'myserver' are behind the same router? Assuming there's a way to copy the login cookies from 'myserver' to 'mybrowsers', would 'external web server' know that a request came from different machines?
Can this be done?
Thanks.
The problem you are facing relates to the security principles of cookies. You cannot set cookies for other domains, which means that myserver cannot set a cookie for facebook.com, for example.
You could set your server to run an HTTP proxy and make it so that all queries run through your server and do some kind of URL translation (e.g. facebook.com => facebook.myserver) which then in return allows you to set cookies for the clients (since you're running on facebook.myserver) and then translates cookies you receive from the clients and feed them to the third party websites.
An example of a non-transparent proxy that you could begin with: http://www.phpmyproxy.com/
Transparent proxies (in which URLs remain "correct" / untranslated) might be worth considering too. Squid is a pretty popular one. Can't say how easy this would be, though.
After all that you'll still need to build a local script for myserver that takes care of the login process, but at least a proxy should make it all possible.
If you have any say in the login process itself, it might be easier to set up all the services to use OpenID or similar login services, StackOverflow and its sister sites being a prime example on how easy login on multiple sites can be achieved.
So if I use a server to make call to web page (cURL or file_get_contents or something), and that web page assigns a session to that call (like I use that call to add an item to a shopping cart), is it possible to then migrate that session to a user's browser from the server?
If I'm understanding correctly, you want your server code to browse to a separate site behind the scenes, do something there that creates a session, and then redirect the user of your app to that separate site, but using the same session you created.
If the session is maintained using a cookie, as is likely, than no, you can't -- you'd have to set the cookie in the user's browser as if it came from that other site, and you can't. In general, this seems like it would be prevented by any sort of session hijacking protection, which most decent sites do have.
The alternative, I suppose, is to proxy for your user for their entire use of that other site (i.e. they click on stuff in your app and you pass it on to the other site behind the scenes).
I would suggest to use simpletest's scriptable browser ( http://simpletest.sourceforge.net/en/browser_documentation.html ) to keep track of states while browsing the interwebs form your PHP codez
Probably not - That call to cURL / file_get_contents will likely generate specific session information for the machine that requested it (i.e. your server). The remote machine should be keeping track of things like IP address and other identifiable information to prevent such a maneuver.
If this is possible, then your shopping cart software is horrifically vulnerable to session hijacking.
I don't believe that is possible. But you can start a session between the user's browser and your server, which keeps track of the session cookie that the remote web page issues you.
I am currently working on 2 web servers, One Coldfusion and the other PHP.
Right now, the Coldfusion server is my main server where users log in to access restricted data.
However, I have also begun using a PHP server and want to make it transparent for users to access a specific page on that server - that server requires log in information as well.
I do not want the users to log in twice.
Is there a way to accomplish this ?
Thx
UPDATE: Working in an Intranet environment, so I can't use any public solution.
UPDATE: Reason I am asking for this is because we are moving from a MSQL / Coldfusion environment (Initial server) to a PHP / ORACLE (new server). So I have 2 user tables as well (although they contain mostly the same information).
I am trying to faze out the use of our initial server in favor of our new server transparently to the user and thus I have to work in parallel for the time being.
Most single-sign-on solutions work a bit like this...
Main system authenticates use
User opts initiates a need to move to system 2
Main system authenticates the user with system 2 in the background
System 2 supplies a random, long and disposable token to Main system
Main system redirects the user, with the token, to system 2
System 2 checks the token (and other factors such as IP address) to validate the session
System 2 disposes of the token to ensure it can't be replayed
You would want to ensure that the transmission channels had some security on, especially where Main system and system 2 are talking to each other. You would want that to be a secure transport.
Store sessions in a database, and share them between the two apps.
You could use xml-rpc to get user data and log the user into the other site when they have a login cookie for the first one and vice versa.
Php manual page for XML-rpc
Here is what I have done, in running my own game server, had users on sql server, and on mysql, and wanted to integrate them both.
I made sure that if a user was created on 1 system, was also created on the other.
So you can modify code in both applications, to automatically create a user in other system if it is created on here.
Depending if both servers share a domain, can you do cross-domain sessions or cookies...But my best guess is to store and retreive data...
Or..
as a person logins/registers record their current ip address, on both servers, then check if this person was on the other server within 2-5 minutes, if so, use the ip address to identify them....
This system is tricky because timing is important, so your not leaving a huge hole in your security....But for short term, going between servers, this is simplest solution, in my own opinion.
Good Luck.
If you are on an intranet, you can actually sniff out the network username of the user from the PC they are logged into the network on using PHP. This assumes that:
You are using IIS to host your PHP application.
Your users are using Windows.
Check the section "2.2 Enabling Support for Detecting Usernames" here.
After that, all you need to do is investigate if the same is possible from Coldfusion, and you have the basis of an SSO solution based on the network usernames.
How about implementing an OpenID solution, much like the one apparent on StackOverflow?
You may benefit from dropping a shared object on the client machine via Flash or Flex. This object could then be read from ColdFusion/PHP/Python on servers that otherwise had no connection to each other or access to a common database.
Here is a simple example from the Adobe Docs
Maintain local persistence. This is
the simplest way to use a shared
object, and does not require Flash
Media Server. For example, you can
call SharedObject.getLocal() to create
a shared object in an application,
such as a calculator with memory. When
the user closes the calculator, Flash
Player saves the last value in a
shared object on the user's computer.
The next time the calculator is run,
it contains the values it had
previously. Alternatively, if you set
the shared object's properties to null
before the calculator application is
closed, the next time the application
runs, it opens without any values.
Another example of maintaining local
persistence is tracking user
preferences or other data for a
complex website, such as a record of
which articles a user read on a news
site. Tracking this information allows
you to display articles that have
already been read differently from
new, unread articles. Storing this
information on the user's computer
reduces server load.
Full Information: http://livedocs.adobe.com/flex/3/langref/flash/net/SharedObject.html