I have two websites https://www.foo.com and https://www.bar.com. bar.com is the actual application, but foo is where the clients would prefer applicants log in. Historically I have logged in at www.bar.com, but now wish to create a form on foo.com to login to bar.com that passes the login to bar.com securely. If there is an error with the info entered into foo.com, i'd like to redirect to bar.com.
[both sites are https]
I've got a form built for the clients, but certainly don't want to send passwords in clear text.
clarification The form is to be given to multiple clients that they will then put on their own page to login to the actual application. The clients are SaaS, that no longer want the company that "does all the lifting" to be what their clients log into
It doesn't sound as though you need any complicated server-side solution for this. Just copy the form from bar.com to foo.com, and modify the action attribute of the form element to start with https://bar.com/. No other changes would likely be necessary, and this would be no less secure than logging in on bar.com directly.
You don't want to pass credentials between sites. This is inherently insecure. What you want is a single sign-on (SSO) solution that allows for centralized authentication and access control.
Read up on SSO:
http://en.wikipedia.org/wiki/Single_sign-on
CAS is a popular SSO, and there are many languages you can use.
If you make those two web sites http://www.foo.com and http://secondsite.foo.com then you could share a single login cookie between the two sites (rooted to "foo.com") and the user could freely go between the two sites, logging in on either one.
There are some javascript md5 encryption functions that can encrypt your password before sending it to http://bar.com/login. If you choose this method be aware those functions have mistakes and some of the generated hashes aren't right.
I would personally choose using ssl as this is the most secure way.
Related
I have a webservice (abc.com) for my company with an own user database and it is working just fine. Now my company wants to add some additional services which are located on a completly different server with another domain (xyz.com) but still use the same login data from abc.com because we have complete control over it and there are going to be similar servers like xyz.com so it is out of question to just import the user database on xyz.com.
My first thought was to use my checkuser.php from abc.com while submitting the login form from xyz.com but then I learned that the session cookie stuff is bound to the domain. At least that is how I understood it.
After that I wanted to access my checkuser.php via AJAX and HTTPS and submit the session data encrypted via POST to xyz.com. That failed too as AJAX seems not to work across multiple servers for security reasons.
Now I am out of ideas and dont know how I can securly authenticate out users on the foreign servers using our user database.
I would use single sign on (SSO) in stead of a shared session. That way, you don't make the sites code dependent on each other. If you later decide to change something on one of the sites, there is less reason to worry about breaking functionality on the other sites, and if you choose to link in a new site you are able to reuse the same solution.
What's better is that someone already made it for you, and it may even be more secure that what you'll be able to create yourself.
Wikipedia has some good general knowledge on SSO. Also, look into OAuth and OpenID. Combine these terms with PHP and a search should get you on the right track.
Another option is to simply have the login function on xyz.com connect directly to the database of abc.com to check the login name and password. Then you use xyz.com's database for everything else. Also if you really wanted to you could store the session information in your database on abc.com instead of a temporary file then you can also access that data from xyz.com. Here is an example of how to do this.
I haven't been working with php very long and have not encountered this problem myself, however, I've been hitting the books hard and came across an answer that my help you out.
If you are just trying to access the scripts and DB on server xyz.com, you can literally grab the content of a script using its url or IP address from within a script located on a separate server (abc.com) using the following function:
/* This example allows my example script on server mvc.com
to access the script on oreilly.com */
file_get_contents("http://oreilly.com");
Since you are accessing the code remotely, and I'm taking a shot in the dark here, I think that file_get_contents ( ) would allow you to set variables via $_POST or $_GET methods from the script on server xyz.com and send the values to the script on server abc.com. From there, you could then store these variables inside $_SESSION variables located on a single server, which ever server that handles the original $_SESSION variables and most of the processing.
It could become a quite complex 'game of catch' between the servers if you need to go back and forth frequently, but I think it may be a way around your problem if you can't move the data onto a single server. If you plan the structure of your scripts well this would allow you to store those $_SESSION variables all in a single place.
I've been asked to leave passwords and user names aside since most of the site visitors are stop-buy-come-back-several-months-later-kind of visitors, and the motivation was somewhat along the lines "they would forget there passwords any way and have to request new ones".
I suspect there is no realistic way for me to do this thinking IP:s probably change and browsers get updated, cookies are cleared and so forth.
Or do I have any options?
(not that I'm looking for code but rather concepts and pseudo but the language in the project is php/js coupled with an apache server)
Use OpenID.
Let Facebook, Google, Wordpress, or even Stack Exchange handle the authentication for you, and people wont have to remember another password.
Alternatively:
Many users understand the "forgot my password; check my email" routine by now, so why not just short-cut it by having them input their email and send them a login url with a randomly generated token to log in with.
Once they're logged in, keep them logged in for as long as you deem secure.
We do the following in our e-commerce solution:
We use email as a unique identifier.
When a customer makes a purchase using the same email, the order will be attached to their existing user. You don't however get any address details or stuff like that, but have to enter it manually.
The customer will receive an email with a generated password if it is a first time buy. If it is a second time buy, they will just be instructed to log in. This can however be combined with a url and a login token. Likewise for logging into the site, you could just have them enter an email to receieve a login url token.
Combine this with a long living cookie and/or the browsers datastorage to remember the customers details (address and stuff like that).
Another option would be to have them entering something about themselves that they would always know, but others wouldn't. However it is hard to have an internationally workable solution for this.
You could use so-called supercookies, which is offline storage on the client side. Either through html5 offline storage, or plugin like flash to restore deleted cookies. Although, these cookies is likely to be banned at some point, since they're mostly hidden for the user, and very hard to get rid of. (Not recommending this approach, just saying it's possible)
Authentication credentials break down to three options;
Something you know - passwords
Something you have - physical keys, cards
Something you are - iris, retinal and other biometrics
The best you can do is use cookies I think. Or...I guess you could have them download a file, and upload that file as their access credential - same idea as a cookie but unlikely to be deleted. You would have to think carefully about what to put into the file however - their user id isn't enough, as it would be easily hacked. A random long string would do, one that is saved into the database on their account. Nothing that can be predicted, and nothing that can be used to guess a different account's credential.
A couple of options come to mind:
Use a persistent cookie, but only do this in conjunction with SSL (so it simply can't be sniffed off the wire)
Another option is OpenID like you use here - therefore vistors can use an account they use often to log into your site.
It seems to me that your only option is giving them a forever cookie and hoping it doesn't get purged between visits.
You can read about them here.
two years ago I had to design a system to share authentication data across multiple domains, all of them shared the same server/db. I was able to pull this off with a complex system of cookie sharing which, to date still works.
I'm now in the process of redesigning the system and I was wondering if there are better ways to achieve this without having to write cross domain cookies.
Basically the system MUST do this.
Once logged in one site the user must be logged in all of the other site seamlessly, not only following a link, but even by directly writing the domain name on the address bar.
To my knowledge the only way to achieve this are cross-domain cookies, if there are alternatives please tell me.
Thank you very much
My Idea would be to include a login-Javascript from a third domain which gets includet in all sites. This javascript sets and reads the session-cookie and calls the current domains server via ajax with the result. (No validation should be done in the JS - this simply sets and reads the cookie)
If cross domain AJAX does not work, you can still call the thirds domain server which acts like a proxy and calls the current domains server.
The StackOverflow sites have implemented something similar to this. Check out the details at the following links.
Here is a post giving an outline of how they did it.
And here is even more detail.
For this you do have to use cookies, but you can vary what you store in the cookie. The cookie doesn't have to contain user credentials but can instead contain something more like a token that you use to "centralize" your sessions.
Easies way would be to let all hosts share a single memcached server and use the content of the users cookie as your key.
I have 2 site: example.com and exampletwo.com
I want that when a user login on example.com then he is automatically authenticated also on exampletwo.com
How can I do that ?
I use Django + Nginx on first website and Tornado framework + Tornado server on second website.
Thanks ;)
.
P.S. If you don't know this platforms ( Django or Tornado or Nginx ), I accept also a solution for a generic PHP+Apache platform and then I will do some research :)
I would have the code handling user registration on example.com immediately send an https request to exampletwo.com (which authenticates it based on certificates, of course) meaning "add this user with these credentials". This approach seems to be workable for any two web servers / frameworks / languages as long as they're able to send and receive HTTPS requests and authenticate certificates.
If you can't authenticate certificates, you could send the "add this user" message encrypted (as long as the two sites can share a secret to use for the encryption). This may be vulnerable to replay attacks, but if you make a timestamp part of the "add this user" message, you can highly restrict the time window of vulnerability for the replay attacks, probably enough to make this approach viable.
If you can't safely share secrets between the two sites, not everything is lost: you can still use public key encription. The sender encrypts the "add this user message" (including the timestamp of course) with its own private key, then with the receiver's public key; the receiver decrypts what it receives with its own private key, then with the sender's public key. A bit messy and perhaps a bit slow, but under such difficult constraints it's surprising that it can still be done at all;-).
Assuming both the websites can access a single shared database this can be done with both the webpages accessing a table and checking whether a user has logged in or not. I am not familiar with Djano or Tornado, but if the above solution is dubious, you may wish to expose a Web Method (Web Services) of one website and then use (call) the web method from the other.
Cookies are a no brainer as they are site dependent.
And another approach is tracking the user through the IP, but dynamic IP's can pose a great problem and may be used to breach the security.
The problem is that one site cannot set cookies for another. Even if your login code on example.com were to do a server-to-server request to tell exampletwo.com that the user's validated, there's no way to set a cookie to carry this message over when the user actually visits exampletwo.com.
Client certificates are way around this, but if this dual-auth system is for the general public, not a particularly good one. Most people will see some weird request ('Do you want to add this cert?') pop up and run off to the hills screaming.
The workaround is do have example.com spit out SOMETHING that'll cause the user to load something from exampletwo.com. An image, a chunk of javascript, etc... and put an encrypted token in the request (<img src="http://exampletwo.com/login.php?remoteauth=ENCRYPTEDTOKEN">). Then exampletwo can decrypt the token, and if its contents are ok, and send out the image (or whatever you're transferring) with the appropriate cookie set.
I was looking at the livehttpheaders plugin for Firefox and decided to test my login page. I noticed that the parameters shown inside of it contain my login and password. For example:
username=sarmenhb&password=thepassword&submit=Login
in plain English.
I don not see this on other sites.
What can I be doing wrong? I see this as a security flaw. The login page, all it does is validate and log in the user. All fields are ran through mysql_real_escape_string (in case that is relevant).
The information has to get to the server from the client some how. Use SSL if you are worried about security.
Even if you do an MD5 hash in Javascript, this does not help because it is trivial to submit the hash to the login page, and the hash effectively becomes the password. All things are plain text until they, or the transport, is encrypted. POST the variables, use SSL.
To add from my comment below. You may not see the headers for other-sites because they may use AJAX, POST method or another client-side mechanism to authenticate.
This reminds me of a certain building in a large city (I am sure there are others in other places) where they have a web based interface to the building concierge. Residents can log on to a web site (over http) and specify (among other things) who is allowed to enter their apartment for repairs etc in their absence. I am sure the whole thing was programmed by someone's nephew who is a 'guru'.
I am sure it is, shall we say, good enough.
You're seeing it for your site and not for others because livehttpheaders shows the URL for GET requests, but doesn't show the content for POST requests.
Sending login information through GET requests is a minor extra security hole over sending them POST, in that the URLs for GET requests are often logged in various places, whereas almost no one logs POST content. Does everyone with permission to look at the webserver logs have permission to know the CEO's password?
However, as others have pointed out, unless you're using https: for login, data is going across the network in plain text whether you use GET or POST. This is almost always bad.
Still, as an intermediate measure I would change your app to send username and password stuff as a POST, not a GET, so that you don't end up storing usernames and passwords in your webserver logs - it's no use using https over the wire if you're doing something that then writes the username and password to an insufficiently protected logfile on the server.
When you are using http and submit a form, the form contents are sent across the wire "in the clear", as you're seeing. When that form submission includes credentials, then yes, you have a security issue.
Among your alternatives are:
Use https, so that over-the-wire communication is encrypted
Use OpenID for login, which pushes management of https credentials off onto the user's OpenID provider
Use Javascript on the client side to encrypt the credentials before posting the form
The latter approach tends to get people into trouble if they're not very careful, because the mechanism for encrypting the credentials is fully visible to anyone who cares to inspect the javascript.
HTTP live header shows POST requests as well. Post sends the data the same way as GET does but the only difference being that the variables are passed in the url itself in GET but in POST they are appended to the HTTP header.
To get better security use encrypting in JS (only password or token+password). But that still can be hacked using rainbow tables for say MD5 or any other hashing technique.
SSL is the only way to achieve high security.