How to implement a single sign-on authentication server? - language-agnostic

I want to implement a discrete remote authentication server that handles login for many sites. Somewhat similar to OpenID.
Basically, I have site-1 and site-2 and they're both reliant on the same user database, which is on a separate auth-site. So, auth-site handles user authentication for them, and during this process, makes information on the authenticating user available to the requesting system.
Each site can be on a completely separate domain name, on completely separate machines.
This is all via HTTP(S), there can be no direct database access.
There's one last quirk: once an user has logged in to site-1, when accessing any other site reliant on auth-site, the site must treat the user as already authenticated.
This whole business must be entirely fuss-free to the end-user. It should work like a simple everyday login form.
As a concrete example, say we're talking about stackoverflow.com and serverfault.com, and they both authenticate via authentic-overflow-server-stack.com. Again, once logged in to either site, I can go to the other and do my business without logging in again.
What I'd like to know are the general interaction mechanism between the sites behind this scenario.
In my particular setup, I'm using Rails, but I'm not looking for code[1], just general best practice and guidance, so feel free to answer in pseudo-code or any generally readable language. OTOH, bear in mind that I'll have decent MVC, REST, and meta-programming in my toolkit.
[1]: unless you happen to know an existing tiny neat free MIT/BSD-licensed app/plugin/generator that handles this.

It sounds like (especially with the emphasis on fuss-free), you want something like what the Wikimedia Foundation is doing. Basically, you log on to en.wikipedia.org, then that server communicates with other servers (e.g. en.wikinews.org) and gets authentication tokens. Finally, those tokens are embedded into images, e.g. http://en.wikinews.org/wiki/Special:AutoLogin?token=xxxxxxxxxxxxxxx , and when your browser visits that url (img src) it gets a authentication cookie for Wikinews. Of course, the source code is available for your reivew at http://www.mediawiki.org/wiki/Extension:CentralAuth .
OpenID is also a good choice, but it does require that the user "consciously" visit two domains. An example of one entity with two domains doing this is Canonical. E.g., if you go to https://help.ubuntu.com/community/UserPreferences they will redirect you to Launchpad (https://login.launchpad.net/+openid) for authentication.
Note that Wikipedia is doing this over http, but you can do it all https to ensure the img src tokens aren't intercepted.

Looks like CAS is good enough for me, and has ruby implementations, along with dozens of other lesser languages, e.g. one that rhymes with femoral bone rage.
http://code.google.com/p/rubycas-server/
http://code.google.com/p/rubycas-client/

It sounds like you want to actually use the OpenID protocol itself. There's no reason you can't restrict the authentication provider to only your own server, and do some shortcuts that make the authentication process transparent. Also, the OpenID protocol supports what you describe about logging into one implies logging in to all services.

Related

How to keep backend session information in Polymer SPA

I'd like to login to a RESTful back-end server written in Laravel5, with the single page front-end application leveraging Polymer's custom element.
In this system, the persistence(CRUD) layer lives in the server. So, authentication should be done at the server in responding to client's api request. When a request is valid, the server returns User object in JSON format including user's role for access control in client.
Here, my questions is how I can keep the session, even when a user refreshes the front-end page? Thanks.
This is an issue beyond Polymer, or even just single page apps. The question is how you keep session information in a browser. With SPAs it is a bit easier, since you can keep authentication tokens in memory, but traditional Web apps have had this issue since the beginning.
You have two things you need to do:
Tokens: You need a user token that indicates that this user is authenticated. You want it to be something that cannot be guessed, else someone can spoof it. So the token better not be "jimsmith" but something more reliable. You have two choices. Either you can have a randomly generated token which the server stores, so that when presented on future requests, it can validate the token. This is how just most session managers work in app servers like nodejs sessions or Jetty session or etc. The alternative is to do something cryptographic so that the server only needs to validate mathematically, not check in a store to see if the token is valid. I did that for node in http://github.com/deitch/cansecurity but there are various options for it.
Storage: You need some way to store the tokens client-side that does not depend on JS memory, since you expect to reload the page.
There are several ways to do client-side storage. The most common by far is cookies. Since the browser stores them without your trying too hard, and presents them whenever you access the domain that the cookie is registered for, it is pretty easy to do. Many client-side and server-side auth libraries are built around them.
An alternative is html5 local storage. Depending on your target browsers and support, you can consider using it.
There also are ways you can play with URL parameters, but then you run the risk of losing it when someone switches pages. It can work, but I tend to avoid that.
I have not seen any components that handle cookies directly, but it shouldn't be too hard to build one.
Here is the gist for cookie management code I use for a recent app. Feel free to wrap it to build a Web component for cookie management.. as long as you share alike!
https://gist.github.com/deitch/dea1a3a752d54dc0d00a
UPDATE:
component.kitchen has a storage component here http://component.kitchen/components/TylerGarlick/core-resource-storage
Simplest way if you use PHP is to keep the user in a PHP session (like a normal non SPA application).
PHP will store the user info on the server, and generate automatically a cookie that the browser will send with any request. With a single server with no load balancing, the session data is local and very fast.

What library/function would I use to create a mail client?

I'm attempting to make a mail client that is HTML5/JS only where users would have to define their mail server and credentials.
I've surfed google leading to dead ends and figured that this is the next best place (or superuser.com).
I was thinking of using HTML5 WebSocket if I could to make the connection to the server but I don't know enough of smtp, imap, or pop3's architecture to understand how javascript could pass the args and perform what I want it to do.
PHP cannot be involved in this project otherwise I wouldn't be asking the question.
Any help in locating this would be fantastic.
Nothing is impossible. Except this.
In standard HTML or JavaScript, you can't make raw-socket connections, which is what you'd need to speak any of the protocols you've listed. The WebSocket API doesn't help you, because the server must also speak WebSockets, and mail servers don't. This is actually all a good thing, though. Imagine if you visited a random website and it telnetted to your home router, setting it on fire and burning down your house. That's what websites would be able to do if they could initiate plain TCP socket connections.
You have a few options I can think of, neither of which involves building a webpage. (And to be clear, you didn't say your project had to be a webpage; you merely said HTML/JS, so these are indeed legitimate options.)
First is something like node-webkit. As the readme says, "You can write native apps in HTML and Javascript with node-webkit." You'll still have to distribute it as a native app, because that's what it is.
Second is a Chrome app, specifically using the chrome.socket API. But have fun writing a TLS layer over those sockets, which you'll find is a requirement for almost any mail server these days. If you succeed in doing that, you'll be able to distribute your mail client in the Chrome Web Store, where I assure you an email client will be quite popular.
Third, write a webserver that operates locally, so your users will visit something like http://localhost:9999/mail in their browser. This will be a real pain to distribute, but you can use almost any technology you want.
I'm sure there's a fourth valid option, and someone else can chime in on that one.
Best of luck.

HTTP DELETE request with extra authentication

I was searching for a solution of the following problem, so far without success: I'm planning a RESTful web service, where certain actions (e.g. DELETE) should require a special authentication.
The idea is, that users have a normal username/password login (session based or Basic Auth, doesn't really matter here) using which they can access the service. Some actions require an additional authentication in form of a PIN code or maybe even a one-time password. Including the extra piece of authentication into the login process is not possible (and would miss the point of the whole exercise).
I thought about special headers (something like X-OTP-Authetication) but that would make it impossible to access the service via a standard HTML page (no means to include a custom header into a link).
Another option was HTTP query parameters, but that seems to be discouraged, especially for DELETE.
Any ideas how to tackle this problem?
From REST Web Service Security with jQuery Front-End
If you haven't already, I'd recommend some reading on OAuth 1.0 and 2.0. They are both used by some of the bigger API, such as Facebook, Netflix, Twitter, and more. 2.0 is still in draft, but that hasn't stopped anyone from implementing it and using it as it is more simple for a client to use. It sounds like you want something more complicated and more secure, so you might want to focus on 1.0.
I always found Netflix's Authentication Overview to be a good explanation for clients.

Which authentication mechanism to choose?

Well, on my free time, I'm making this small web site. The site will not require to authenticate, only some actions (like leaving a comment) will require to do so.
I would expect to have up to 100 (probably less) unique visitors a day. I don't really expect more than 50% to (bother to) register.
Right now, I'm thinking of three possible authentication mechanisms (but I'm open to suggestions):
OpenID authentication;
HTTP Digest or at least HTTP Basic authentication;
My own (form based) authentication.
OpenID seems to me a little bit of an overkill for a small site like this. Also, buzzword like "OpenID" on the login page of my site might scare away the less tech-savvy people.
HTTP Digest (or Basic) authentication provides a low security level (or none at all), because the site will not be under HTTPS.
My own implementation would, most likely, suffer the same security problems as the HTTP Digest would. Although, I could implement some more protection against brute-force attacks (display a captcha after three failures etc).
What other mechanisms would you suggest? What are the pros and cons that I'm not seeing? What would you choose?
Well, if you want your visitors to leave comments I really think you're better of with something like OpenID. Because if you provide your own form based authentication who will really bother registering yet another account with some password wondering if they can trust you?
I think it's safe to say that people who like the internet own a gmail account, and all those people have an OpenID (Google account).
I suggest you use that... that's what I would do.
You haven't said what language/technology you're using. It could affect things. But I'd be inclined to just roll your own form-based authentication. It's not terribly difficult. Just remember a few basics:
Always sanitize user input. It can't be trusted;
Never store a username or password in a cookie (believe me people do);
Only store encrypted passwords using a reliable encryption method like MD5 or SHA1;
Use a non-predictable salt;
Require cookies to be enabled. Don't try and do URL rewriting.
Why not just have a name field when they post a comment, perhaps remember it in a cookie if you want. Most users just want to identify themselves not have an account.
Just make sure that you have some spam blocking in place as forms attract spam bots. Even if that is just a capcha with the form every time.
Openid is the best I think. Also if you give proer help about open id (or like SOF shows) then people will uderstand. Once less tech savvy people uderstand the use of opend id (no new username and pwd) then they will start liking it.
Definitely go with OpenID - the more people we get onboard, the more familiar people will become with it, and it's not really that strange to use the first time. If you are a microsoft dev, the dotNetOpenID library makes implementation pretty straightforward - I have done this for both ASP.NET and ASP.NET MVC sites with no problems.
EDIT:
With regard to supporting non tech-savvy users, some links / explanation on the login page would go a long way to alleviating concerns. The redirect they will see is quite similar to experiences that they are more familiar with, like credit card or paypal authorization, so should be easy to explain in these terms.
It depends in part who your target audience is. If they're all computer geeks, go with OpenID. They're either familiar with it, or will understand what you're doing. If they're not necessarily computer geeks, they may not have been exposed to OpenID authentication yet, so OpenID could present a barrier to entry. In that case, you might want to go a more traditional route, such as register/validate email/login approach, whether roll-your-own or off-the-shelf.
You could distribute some RSA SecurID to your visitors ;-)
Seriously, the main question to ask is: does the total hour of work to implement a decent security system for my users to log in are worth the content that may be accessed if the website security is broken?
You should look into RPX (https://rpxnow.com/), its a layer on top of OpenID and a few other schemes that for most languages is really easy to implement (there is a gem for ruby and I know a friend of mine got it into his php application in a less than a couple of hours).
OpenID rules! As an informed user I'm not sure it's been looked at to the point where it's "bulletproof" for security, so I probably wouldn't use it for financial / medical websites, but for the 95% of other websites, it would save me from having to write down my cheat-sheet of 137 different usernames and passwords. I've used it in a (nonpublic) site I developed and it was a bit of a hassle to get the authentication working properly, but if you can use one of the libraries out there, go for it!
HTTP authentication is standardized but something about it disturbs me. I dunno what. Something about a separate dialog box popping out of the browser makes me suspicious.
p.s. BBC's Digital Planet had a radio program my local radio station aired yesterday (17 Feb 2009) that talked about OpenID. So I guess when the radio talks about it, it must be starting to go mainstream.
My advice: do not reinvent the wheel. Web authentication is a wheel if I ever saw one, and it's remarkably difficult to get all the subtle pitfalls handled correctly. Chances are you'd miss something and end up with effectively no security.
Either go with an OpenID solution, or look into the many auth libraries out there, and pick a thoroughly-tested one.
See also: The Definitive Guide To Website Authentication

Multi-site login ala Google

Not sure if the title is quite right for the question but I can't think of any other way to put it..
Suppose you wanted to create multiple different web apps, but you wanted a user who was logged into one app to be able to go straight to your other app without re-logging in (assuming they have perms to look at the other app as well). If I'm not mistaken, if you're logged into gmail you can go straight to your iGoogle, googleReader, etc without re-logging in (if you set it up right).
How would you approach this? What would you use? Assume the apps already exist and you don't want to change the initial login page for the users.
What you're looking for is called Single Sign On. If you follow the link you'll find several implementations.
Open ID as others have mentioned is not such a scheme as it requires a seperate login for each site. Open ID is merely a shared authentication system.
You would issue a cookie against foo.com, which would then be visible on app1.foo.com, app2.foo.com.
Each application can then use the cookie to access a centralised authentication system.
Try CAS it should provide the features you are looking for.
What you want is a single sign-on (SSO).
There are two approaches to solving this problem:
Roll your own implementation. In its most trivial form it can be implemented by the first site setting a cookie that holds the ticket for the logged on user and the second site verifying that ticket and accepting the logged on user. There are quite a lot of potential pitfalls here:
you have to protect yourself against information disclosure - make sure that the ticket does not contain the actual user credentials
you have to protect yourself against spoofing - a man in the middle stealing a valid ticket and impersonating one of your users
and others
Adopt a third party SSO mechanism. Google, Microsoft, Facebook and other big companies allow integrating with their identity providers, so that your users could log on to their website and they handle verification, ticket issuing and so on. There's also OpenID, which is an open protocol you can use to enable SSO on your site through virtually any identity provider that supports OpenID. The potential drawback here is that somebody else controls your access to your user identity and can limit the features you can offer and data you can mine for your users.
As mentioned you can use something like OpenId or similar to make the process simple. Otherwise if you roll your own you could use a cookie to store the login, then basically ALL applications must have an entry point that mimics the base url.
Google for example uses mail.google.com to as a pipline into Gmail which allows it to read a cookie stored with the google.com domain.