Authenticate user on NodeJS connecting from IIS hosted site - php

I currently have an antiquated CMS system that I'm trying to add a realtime chat feature to. The CMS runs using IIS, MSSQL and PHP.
The chat feature will run from a separate linux box running Nodejs and Socket.io
I've managed to get the CMS to successfully open a connection to the Node server and now I need some way of authenticating the user.
The Node server will NOT have a database behind it
The Node server will NOT be able to access the CMS other than through the socket
The possibility of new CMS users (very regular occurrence) means I can't just copy the users passwords to the Node server
My only idea at the moment is to put together an array of user data (id, name, email address), create a hash of this data and then send both the data and the hash to Node. The Node server would then attempt to hash the data and validate it against the hash sent by the CMS. (obviously both the CMS and Node would have a predetermined private salt for the hashing)
Is there a better way of achieving this?!

A good rule of thumb is: Don't roll your own crypto unless you're a cryptographer, and even then think twice.
My suggestion would be this:
Run both servers over HTTPS, on their own subdomain (same domain obviously)
Use a *.domain.com cookie domain on your session cookie, with the Secure and HttpOnly flags so that both subdomains can see it
Persist your PHP sessions in JSON to an external key/value store which both servers can access
The Node server can then simply look up valid sessions according to the ID in secure cookie

Related

How to store username passwords in PHP Script file secure

Be Clear: This question is not about password encryption/hashing to save into database.
I have developed a PHP application for a client. The application is installed on client machine with XAMPP (placed at htdocs/project_name). Client uses that application locally but the local database is synchronized with remote MYSQL database by Export Report button available on web interface.
My concern is when I store a connection string for remote database in my PHP code the username & password are visible to any guys who can hunt PHP script file and can see it. I don't even wish the client be able to view passwords used for remote connection/synchronization.
How can I achieve this?
You want to give user permission (login data) to connect to the
database but at the same time don't give him permission (login data).
The only thing that is on my mind to store login data corrupted,
and in code decrypt this data with some key hardcoded in the script. This is hackable,
but if the user is not programmed it is unlikely to do this
If you accept Kerckchoff's principle then it is impossible to provide an authentication which is available to a program run by a user without making that token available to the user. If you provided a better description of the problem, specifically the modes of operation you are trying to prevent then we might be able to provide effective solutions (e.g. encapsulating all data access in packages would restrict access to data for specific users).

Good practice to 'authorize' HTTP-File-Upload to different Server (CDN-like)

I'm searching for a good practice to authorize HTTP-Uploads using jQuery to a different server.
We currently have a setup of two servers. One for the main Web-Application and one for file-storage. Users need to be able to upload their content to the second server while working with the main application on Server #1.
The key point is the fact, that these uploads must be 'authorized' to prevent users from uploading whatever to the storage server. So if eg. the user clicks on "Upload new profile picture" the Main Application needs to generate a token and submit it to the storage server which then validates it.
Now the question: Is there a more elegant way like injecting the user's session to the storage server or any other best practices?
I believe using a token IS the best practice. If you can setup a common 3rd party server to handle the key verification that would probably be a good starting point and I've included a basic setup for this below.
Simple Version:
Basic Keystore server (redis is more than capable).
Have both the app server and storage server able to authenticate to the redis store.
When a user needs to upload, have the app create a one-time (GUID) key in the redis store. When you submit the upload include this key in the header.
When receiving the storage request the storage server should pull the key out of the header and verify it exits in the redis store and then clear the key.
You could add any additional data you wanted to in that request as well such as the username, but the key is going to be your authoritative decider.

php - authenticate with one server for access on another server

On my local server I have written a script that takes a username & password and confirms it is valid against my LDAP server.
I have a web site professionally hosted on a remote server. I have a CMS on the remote server and I would like users to use their LDAP credentials to gain access to that CMS.
My plan is to have a login form on the remote server. The form will POST the username/password to itself using https. It will then use CURL to POST the username/password again but this time across the internet to my local server, again using https. My local server will be setup to provide a simple "TRUE" or "FALSE" as a response. If the remote server gets back TRUE, session variables are set to permit access.
Security-wise, is this a safe practise. Should I consider another way?
note: I'm not particularly proficient with cURL but I think I can figure out how to do the above.
LDAP - Lightweight active directory protocol which is used to communicate with your active directory server.
LDAP is there only to authenticate & access AD server in most secure way.
Here is the solution for problem :
Customize existing login functionality of your CMS in a way like - If user his details check with AD server using LDAP whether user is exist in AD, if yes update his credential to your DB(Also keep flag that user is AD enabled), if user is present is AD & not there in your DB create that one.
Likewise after some time al your user from AD server will migrate to your DB & you are not required to keep seperate application to for user migration.
Also every time authenticating with AD is best to provide security but its all up to you, because after migration of all user you can remove this functionaity.

Restrict php script to only one computer without login

I want to make a php webpage accessible from only one computer.
IP checking isn't suitable for that (Dynamic IP).
I could set a cookie (with no expiration date) with a token. Then I could check if the cookie has the correct token and display the page, else I could die(). I think that this isn't a secure solution, because a cookie can be stolen, can't it?
So, what to do?
P.S. Obviously I can't login every time.
So here are a couple of options:
Client side certificates
Create a client side certificate and configure your webserver to authenticate using client certificates. Problem solved. In future, if you need to have more computers connect to the server, give them client certificates as well.
IP based : using Dynamic DNS
Give your computer a dynamic-dns name (myclient.dyndns.com) and install a dyndns client on your computer. The dyndns client keeps checking its own IP and updates the nameserver entry whenever your computer's IP changes. On server side all you need to check is if the IP that the requester presents is same as myclient.dyndns.com and allow access if it is.
A slight gotcha in this one is that there is a small (configurable) window of time between when IP changes and the dyndns client pupulates it to the nameserver. So, whenever your IP changes, until the dyndns client on your computer detects it and updates the nameserver, your server will not allow any requests from your computer in that time window. Thats because your computer will present the new IP and myclient.dyndns.com will resolve to your old UP. This time window can be made as small as you want (even 1 second). The other small gotcha is that in this n second window, any random computer that gets your old IP assigned by the ISP can access your server. The probablity of this is very small but just mentioning as a possibility.
There are many free dynamic dns services out there. You can google them.
Cookie Based
You could use cookies. However as you correctly identified, cookies can be stolen. Now, there are two ways they can be stolen:
Copying the cookie off the computer: Someone who has access to the computer can copy that specific cookie and impersonate as your computer to your webserver. If this is possible (if potential malicious users can remote desktop or physically access your computer), then cookie based solution is not for you.
Sniffing over the network: Cookies can be easily sniffed over the network. A easy way to prevent sniffing is enabling SSL. Given that you are confident that cookies cannot be stolen off the computer by copying it over, cookie+SSL option works in your case. In this case its just like a shared secret key. You do it via cookie or querystring, it doesn't matter. Cookie obviously are preferred over querystring because cookies aren't normally logged in browser history or webserver logs.
Also just a thought: For all the computers that aren't authenticated, send a standard 404 response rather than some custom "Access denied" page. This way anyone who is running a crawler/bot/scanner on your site will not be intrigued by this custom response and will not attempt to circumvent your security controls.
Couldn't you just use a unique passphrase as a parameter in the uri?
e.g. http://www.example.com/index.php?passphrase=sfauh452h8243nf2489ht8924t48nf3984
and check to see if it matches the one stored in the server?
Well I get if you are not the user it is someone else... then you need only that specific client (computer) to be able to access the page
Either way the first time there must be some sort of registration. Maybe the example uri above works like this:
you request: http://www.example.com/index.php?passphrase=sfauh452h8243nf2489ht8924t48nf3984
the passphrase is checked of being correct and a boolean value is stored in the server as to never be able to "register" again.
If it is correct, a cookie is being generated with a unique key.
This same key is also stored in the server (file, database or something)
Therefore on subsequent requests when you just compare the key stored in the server and the key in the cookie you know who is the client

Persistent login info from server to server

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

Categories