So, I'm looking at architecting an application using nginx with the nginx-http-push-module and PHP-FPM, and after lots of fun configuring, I got it working to the point of handling PHP pages as it should.
What I don't get, though, is how sessions are supposed to work - all of the examples I've seen for nginx+NHPM run through the publisher-subscriber system, but it's never clear what should happen if the subscriber channel is going to be, effectively, unique to a subscriber. Think of a chat system with a public channel and a private channel for each user, for example.
Now, in a conventional PHP setup, you'd be passing the cookies to PHP, looking up the session from there, and handling the rest of the page based on whether the user was authenticated or not, but with PHP-FPM and long-polling, it doesn't seem like it should work like that.
I can understand if the request is a non authenticated user, you just dump them with an error message and terminate the long-poll from the client knowing that it's not valid, but with a valid request, you almost need to poll from the client, authenticate in PHP, then disconnect but leaving the request open - and I'm not sure how that part works.
Can anyone explain how it should be achieved, ideally with an example if possible? Please note I'm not looking for HTTP Basic authentication here, I need the authentication to be looked up against a separate data storage which is in MongoDB.
Disclaimer: I can't clearly understand your 4. paragraph.
As far as I can tell, the main problem with authentication in NHPM is that the PHP application gets absolutely zero notification of incoming connections. The Comet part of your setup is write-only for PHP.
A possible solution follows, I'll be trying this out in the next days.
nginx configuration:
push_subscriber_concurrency first: so that the channel can only be used by the intended user
push_authorized_channels_only on: not strictly necessary, but good to have in my opinion
Authorization workflow:
Client sends credentials via old-fashioned requests
Server authenticates, and generates a token (channel id). Creates the channel and responds with the token.
Client tries to open long-poll to the given channel.
If it fails (possibly because the channel was hijacked), it tells the server that channel so-and-so is invalid. Mind that we use old-fashioned requests here, so you can use any auth method. Server deletes the channel. Back to step two.
If the connection is successful (you probably won't know this, only that it hasn't failed), the channel can be considered authenticated.
Note that if your application should be accessible from multiple pages in the same browser with the same login, then you'll need to prepare for multiple channels per user.
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 developing a web site which calls .PHP scripts to inject data into a MySQL database.
Because there is no security on these .PHP scripts, anyone in the world could run them over the web if they knew the proper parameter names and inject data into our database.
I know very little about security so I'm looking for a solution to secure these "web services".
I've read that using SSL may be the way to go but I'm not sure.
If anyone could make a recommendation and point me to a tutorial or website on how to implement this I would be greatly appreciative.
We are using Apache web server by the way if that matters.
SSL will not solve the problem by itself. If someone can hit http://yoursite.com/service.php, they can also hit https://yoursite.com/service.php. SSL simple ensures that the actual data going over the wire is encrypted. But an encrypted injection request will have the same effect as a standard unencrypted one - you'll still have data injected into the database.
What you need is a password system of some sort. A bare bones minimal system would require a secret word to be sent along with each request, and any request without that word gets rejected/ignored. however, then you have to keep this secret word secret, and nothing on the web stays secret for very long.
Next up is assigning a specific key to each authorized user of your service. Nothing would prevent the users from sharing their key with others, but then you've got a per-user key that you can track down and beat up the person who DID share their key.
Past that, you can use HTTP level authentication, coupled with per-user access keys, which should prevent casual poking at the API. Without the http-level password, the API script is not even invoked, and even when it is, the proper API key must be present as well.
I used to work for a bank, that had a very cool feature in it's intranet. Once you logged in your computer, there were global variables set in PHP through Apache, and they contained the identity of the user that was logged on on the computer. Now I'm at a new job, and I'm wondering, how this thing worked! I would like to implement this kind of thing once again.
What I'm working with here:
FreeBSD server, version is unknown to me.
Apache 2.2 web server
PHP 5, some custom compilation, that for various reasons, I can't upgrade or modify.
MS AD
All of the users logging on to their computers are using active directory, all are in the same domain.
What I used to have was something like this:
echo $_SERVER['username']
which would print the username of the user currently logged in.
Could someone explain, how this could be done?
P.S. If any of my server settings are not what is required, say so, because then I will have a reason to ask the bosses to give me one of my own, with more control.
There's lots of ways this might be implemented. However a lot of them depend on having control over the client as well as the server.
Obvious sources of data include:
NTLM
Client side certificates
The Ident protocol (not very secure without the encryption extensions)
A long lasting cookie (again, not secure)
HTTP authentication methods
However none of these explain how the value appeared in the session - this must have been implemented within the PHP code.
So without knowing how it was implemented at your previous site we can't tell you:
Whether it was secure and correctly implemented
how to replicate the behaviour
Given your resource list, while it would be possible to implement authentication based on direct LDAP calls, passing the username and password through your application, I would strongly recommend using (e.g.) openId - but restricting the providers to just your openid provider - which would use the MSAD as the backend.
I did not understand correctly the question, so I edit my post...
you could use apache auth, you can make auth by ip's or hostnames
http://httpd.apache.org/docs/2.0/en/howto/auth.html
Basically im trying to build a bot that can send a message using one of many accounts out to a user and be able to receive messages to that account it originally used process and do whatever I need it to do. So far I found the JAXL library (http://code.google.com/p/jaxl/) but based on examples it is only able to handle one user at a time. Any suggestions or ideas?
thank you in advanced.
btw if there is anyway to make the server automatically forward those messages to another program or whatever that works just as well.
I think you are looking for a external component.... Jaxl v 2.0 does allow you having component bots written in PHP http://github.com/abhinavsingh/JAXL
I think what you're asking is: "Can I send a copy of all the 'outgoing' messages on a server to an XMPP client?" The answer to that question is "sort of."
You're looking at two pieces, server configuration and client/component configuration. You probably don't want a client. because it needs to log in as a particular user. You're describing a component, which is a trusted application running on the XMPP server or nearby, and acts as part of the server.
The server configuration part depends on which server you're using. I know XCP can do this kind of thing, such as with a message archive component. With ma you'd make a component to write the messages to a log or database. You'd be making a similar component that grepped strings for street addresses and sent out flowers, or something -- whatever action you needed to happen.
The big assumption I'm making is that you are in complete control of the server here. If you don't then the answer is "no."
I recently used the smack library to host dozens of 'Xmpp bots'. There was no such limitation that you could only connect as a single user. Just spawned a thread for each bot, made him connect as an individual xmpp user on a server (and even on different servers) and do its job. In my case the bots simply sent test messages to test chat rooms, but a proxy service (as I understood it from your question) is possible as well.
The threads were even designed to create the user and delete it after stopping.
I am in need of an authentication system that would work in harmony with the current authentication system my client's server uses.
The current system works as follows:
A page requiring authentication invokes an in-house developed mod_auth Apache module in the .htaccess file.
The user is redirected to a generic log in page.
After entering valid credentials, a cookie is created, which has the IP address of the client, a public key, and other helpful info about the user, all base64 encrypted.
Any page requiring authentication after this point checks the public key and the requesting IP address. If the user's IP has changed, they are redirected to the login screen. If the cookie is tampered with, they are redirected.
The benefit of the above system is that a cookie can not be used on another machine (other than on the same LAN, but other measures check against man-in-the-middle attacks), as the IP address won't match.
The downside is that this method prevents the user's session from being extended server-side. In other words, a server-side script can't get information on behalf of the user since the IP address won't match.
This limitation makes sense under most circumstances, as it avoids allowing the server from "stealing" the user's cookie. However it also means that a Web Service can't be protected using the same authentication system, since requests will always come from the server's IP, never from the client (unless AJAX is used, which is a very limited usage of a web service).
What I would like is for the web service client (server-side) to pass the cookie to the web service server and have the web service server verify the authenticity of the cookie directly with the end-user's client.
My basis for this is how sites like Stackoveflow use Open ID to check log-in status at the browser level without the end-user being involved unless the check fails.
A quick wikipedia search leads me to understand that the underlying system involved is a protocol called Yadis.
So I would like to know if I am missing any pieces to this puzzle and if I'm leaving myself open to major security flaws:
User logs in as normal
Page user requests needs web-service
Page passes user's authentication cookie to web service
Web Service uses same cookie to request a generic "confirm authentication" page via user's browser. (without user seeing this).
"confirm authentication" page returns a "user logged in" message or the browser opens a new window with log-in page.
Upon receiving the "all clear" message above, web service returns any info requested by original page that user is logged in to.
Am I missing any details? Is Yadis just a name give to this idea or will I need to install something to make sure it works correctly?
The term "Yadis" can be a little murky because it's referred to different things over the years, but more than anything it refers to the discovery phase of the protocol. That is, it answers this question: given an identifier (like http://keturn.example.com/ or xri://=keturn*example or whatever), what is the authentication server to use for this user? What version of the protocol does it support?
Which, if I read your situation correctly, is not at all what you're trying to address.
What you describe, authorizing one web service to act on behalf of the server with another, is more the domain of what OAuth is meant to address. But if you're stuck with your client's currently implemented auth protocol, I'm not sure that helps you either. But it's probably worth a look, it's not dissimilar from the solution you propose.