A Modest Proposal for Improving Website Authentication
kijinsung.com
kijinsung.com
Technically, you can already implement built in browser auth UI without changing today's browsers, by having the protected path return an http not authorized code triggering the browser chrome login dialog.
Note: "A modest proposal" in a title indicates the suggestion is satire. The original "modest proposal" was to eat babies.
"In English writing, the phrase "a modest proposal" is now conventionally an allusion to this style of straight-faced satire." — http://en.wikipedia.org/wiki/A_Modest_Proposal
I use LastPass and it usually doesn't miss login forms, either. But sometimes it makes mistakes that need manual correction, like trying to log in via the signup page, or loading the home page when the login form is actually on a different page, or remembering the value of every checkbox on the login form (even those with style="display:none"). Some websites also use weird tricks like loading an HTTPS login form in an iframe injected by jQuery, etc. This post was written because I got frustrated with mistakes like that and I realized that there's only so much second-guessing that a third-party tool like LastPass can do.
I don't let any software remember my bank passwords, so the issue of ridiculously convoluted logins didn't occur to me. Perhaps we could compile a public database of how certain websites (mis)behave, and tell browsers to handle such cases according to a script. But I guess we'll never be able to convince banks that automation like this prevents phishing better than the status quo does.
I also didn't want to propose anything that would require any more than a couple of lines of code to be changed on the server side. Switching from HTML login forms to HTTP auth would require more than a couple of lines to be changed on the server side.
(*me)
There's a constant ebb and flow of bad usage and pushback. I only mentioned it's a losing battle because I think there should be a bit more ebb and a little less flow.
Further, bragging about not being well read strikes me as anti-intellectual.
As for the "bragging", you probably should read the comment again, there isn't anything in there that could be described as bragging. I'll also just posit that there's also such a thing as being well read without delving into Swift.
Unfortunately, a lot of people have missed the original meaning, and now assume it merely means something that is true but trivial.
Edit: Just to be clear, I accept, and love, the fact that language evolves, but it's unfortunate when a useful word has its original meaning gradually overturned when there are no alternatives.
[1] http://www.etymonline.com/index.php?search=trivia
[2] http://www.grammarphobia.com/blog/2009/12/trivial-pursuit.ht...
[3] http://www.yourdictionary.com/trivial, see American Heritage Dictionary at the bottom of the page.
I'm confused. Neither Persona nor OpenID are centralized, but that might be beside the point. What sort of concerns do you have with Persona's architecture?
> I hate the idea of giving all websites a single email address to contact me
Then... don't? Persona lets you use as many addresses as you want. It already works with any valid email address, which means you can keep using all of your existing GishPuppy addresses. You can keep using your one-address-per-domain scheme with Persona. No problem.
The ideal workflow for me would be to sign in to persona using my Gmail address as my single identity, and then have it auto-generate (or retrieve by posting details to a Gishpuppy URL) an email address for that specific domain, and only pass that on to the website. In the current model I still need to confirm each new email address by clicking on a link, which reduces the value of a single login greatly. Also, I don't want to be choosing between 900+ Gishpuppy addresses when signing into a site again.
This might not be the ideal workflow for everyone, but its a feature I can't include, because of the lack of API hooks or extensions. Using 'the modest proposal' on the other hand, I could chain together browser extensions sufficiently to add the functionality I need, to get new email addresses from Gishpuppy and existing credentials from LastPass. I guess the word I was going for was not centralised, but inextensible.
That problem would go away if GishPuppy supported the Persona natively -- do you have contact info for someone at GishPuppy? I'd be happy to work with them to make that happen.
> I don't want to be choosing between 900+ Gishpuppy addresses when signing into a site again.
Persona locally remembers your last-used address, so this shouldn't be a problem, though we could probably improve the UX. We're currently trying to figure out how to sync this data in a way that's opaque to Mozilla.
> The ideal workflow for me would be to [...] have [Persona] auto-generate [...] an email address for that specific domain
I agree, but we're totally in the minority. Since you've already talked about chaining together browser extensions, you could easily do the same thing with Persona. It'd only take a small Greasemonkey script on the login.persona.org origin to make that work.
Thanks for the feedback!
The right way to think of HTTP Authentication is as an experiment that failed.
Couldn't that have been fixed with a new parameter in the Authentication header?
> It doesn't easily admit to "logout"
I think it easily admits logout—the browser should have a piece of UI which reads 'logout'...
> It doesn't gracefully handle token authentication.
It could be extended to do that, with a new authentication type, right?
The biggest problem, perhaps, is that it's mutually exclusive: A resource is either protected by auth, or it isn't. There is no room in the spec for pages that change their meaning depending on whether you are logged in or not.
Of course, one could argue that "logged in" pages should have different URLs, eg., /logged_in/*, and just use auth for those. The problem with that approach is that if you go to any resource not within that URL namespace, such as the front page, auth isn't necessarily sent by the browser, and so you can't know if the user is logged into the other parts of the site.
Nor is there anything that supports the notion of "login sessions" -- once you're authenticated, you can't un-authenticate, as far as I know. We actually have a payment provider (DIBS, a Scandinavian company) that uses basic auth for their admin login. The only way to log out of their admin, such as in order to log into a different account, is to clear the browser state.
And lastly, the login popup that browsers currently provide for basic auth is poorly implemented and altogether too simple. There is no way to ask for password recovery, for example, and there is no way to provide a signup button.
I use lastpass, and it's great. But I didn't always use it; before I started, I used a couple of passwords everywhere. Recently some site which I haven't even used in years was compromised, and as a result, one of my "frequently used passwords" was potentially compromised. I had to spend hours going to dozens of websites and changing my password. Every site has a different way to change your password, and different policies for acceptable passwords, and most don't even make it easy/obvious.
I think something like Mozilla Persona is a good start, but not quite complete. Give me one, central place to manage my identity. The ability to control which sites have access to my identity. The ability to allow, or not allow, different sites to correlate my identity with each other. The ability to have my identity independent of my email address. Good two-factor auth for establishing identity, and good password management policies. Single-sign-on, even across independent sites, with just a click.
So the problem is that a proposal like this encourages people to do the wrong thing; i.e. ask me for a username and password - without two-factor auth, without considering whether I will be able to manage yet-another-password, without considering whether they should even be in the business of authentication themselves.
I don't think there's anything in my proposal that makes 2FA impossible. That can be written into the spec. Enter your tokens into a little textbox that your browser pops up when you click "Login" on a website that requires 2FA.
Although many people seem excited about single sign-on systems like Persona, I respectfully disagree, for reasons I wrote about in a different post [1]. You ask whether individual websites should be in the business of authentication, but I'd rather ask why anybody should be in the business of authenticating anybody else to third parties. I'm not opposed to keeping all my credentials in a single location, but I want that location to be inside my own devices. I'm not opposed to sync, either, but I want sync to involve full client-side encryption. I have a great deal of trust in Mozilla, but precisely because I love them, I don't want them ever to put themselves in a position where a three-letter agency can ask them to hand over any information about me, even if it's just a list of email addresses that I use with Persona.
http://www.kijinsung.com/id/610a7b92-3d4e-4c44-b231-0f5e4d1a...
<form method="POST" action="/login/"> <input type="credentials" elements="email,password" /> </form>
This is pretty much exactly the same as the proposal, only it's in HTML rather than HTTP.
Introducing new input elements and HTML semantics will also require a lot of code to be rewritten, whereas a custom header can be implemented with a one-liner that you put in your .htaccess or webserver config file, or a turnkey plugin for most content management systems. The goal is to produce something that can be grafted onto virtually every existing website with the absolute least amount of code change.
If anything, a custom header is worse because it's too separated from the actual URL. I can't automatically update that file if I change the login URL, but I can if it's in the template.
I think a common login interface is important enough that we can't wait for the majority of websites to fix even a few of lines of code. (Does WordPress even allow plugins to modify the field names on the login page? It certainly allows them to add custom headers.) Copying and pasting a "Header add" one-liner in your .htaccess file requires 10x less programming skill and carries 10x less risk than rummaging around in a bowl of pasta, so it's much more likely to see widespread adoption. We could even open a service that crawls a given website and suggests reasonable values to put in their .htaccess files, for people who want the shiny new Login button to work in their websites.
I also don't see how it would be any more difficult for experienced programmers to update a header than it would be to update a template.
There's an interesting article on Technical Taco, "Range header, I choose you (for pagination)!" The author makes a good case.
[1] http://www.w3.org/TR/html4/struct/links.html#h-12.1.2
[2] http://otac0n.com/blog/2012/11/21/range-header-i-choose-you....
I'm thinking 'next' rather than 'next-page' because it seems to me that "next blog post" and "next page of results" would both benefit from basically the same thing, considering a paginated resultset to be a collection of collections of size $page_size.
Seems like the sort of thing a browser extension could easily pick up on and do something useful with.
You can try it on my blog at http://pygm.us/vwR2WSYJ or a thread in NeoGAF: http://www.neogaf.com/forum/showthread.php?t=559996.
Something Awful used to support it, but they broke it by making the Last Page button the designated `next` destination, unfortunately.
It’s really the only way to go through pagination-heavy content. Anything else is way too tedious.
Everyone with a blog should implement this. It’s just silly not to.
You could even solve that issue without waiting for browser vendors by adding browser addon that does queries to supporting sites by showing a lock icon in the url bar. When you click that lock icon, you do your initial setup with master password and/or key(s). After that you can click the button and toggle your login/logout state with a single click.
The Website only needs to add one php/ruby,python or .htaccess file that adds those http-headers. For DNS you need to add some Resource record fields.
I still don't get why Opera or Firefox didn't think of it, I mean Opera has "Unite" and Firefox has "OpenWebApps" which are in desperate need for a final solution to "Cross-Site Authentification" using built-in secure password or key stores..
The real reason I think browser vendors are uninterested in solutions like this is because they are already trying very hard to push their own identity providers: Google wants everyone to use Google accounts, Mozilla wants everyone to use Persona, and Microsoft wants everyone to use Microsoft accounts. Conflict of interest.
It is a set of keywords for satire.
There may be issues with a central identity provider, but given the wide range of horrible choices implemented by so many different websites I think the assumption that keeping identity between you and the site owner is a better choice than trusting a central provider is true only in a limited number of cases.
If I hadn't hit the lost password link I never would have known that they keep an unencrypted copy of my password. Finding one trustworthy central provider at least protects you from unknowingly trusting a large number of incompetent providers.
If we made it very easy for everyone to do the same, I think that the problem of insecure storage can be circumvented for the most part, even without moving to a centralized account management system. My proposal is basically to facilitate widespread adoption of password wallets like LastPass. Since such tools are already used by millions of people and does not require much effort on the part of individual websites, I think it has a better chance of success than trying to move everyone to use Persona.
One of the major benefits of identity providers is that we eliminate the need for a million passwords for all the sites you use, the only thing this does is provide a perhaps more convenient way of living with the problem instead of a solution to eliminate the problem.
Also, http://xkcd.com/927/
What is the reasoning behind this statement? Resolving the hostname for the HTTPS site still requires DNS. Is it because DNS isn't encrypted, so a MITM could change the POST URL? That's an issue with unencrypted HTTP, also, so you couldn't safely send this header on non-SSL pages. You'd need a login link that goes to an SSL-protected page first, in which case this just adds an extra (no longer useful) step.
HTTP isn't much better, either, but at least an HTTP website can be turned into an HTTPS website without too much hassle. DNS on the other hand looks as if it will be stuck in its current form for many years to come. With HTTP(S), you can choose to be secure. With DNS, you're insecure and you have no choice.
Maybe following headers:
Auth-Spec: type=plain; csrf_token='xyz'; action=https://www.example.com/login; method=POST fields=email,password,csrf_token
Set-Cookie: csrf_token='xyz'; HttpOnly
Could do the job? The submit button would need to copy csrf_token value from the Auth-Spec to the login request.Edit: I'm wrong. See below.
The attacker doesn't brute force someone's credentials, but uses own credentials to log the victim as the attacker.
To keep things as simple as possible, I propose:
Auth-Spec: type=plain; action=/login; method=POST; fields=email,password,nonce:8977340152
The "colon syntax" could also be used where the name of a required field is different from the defaults (another problem that I overlooked). For example, WordPress uses "log" for the username and "pwd" for the password, so it would be "fields=log:username,pwd:password".It wouldn't be possible to require a nonce, though, because it would break backward compatibility with sites that are already vulnerable anyway. As an option for new or updated websites, though, it would be a good idea to add a nonce field.
- No ability to put in an anti-CSRF token
- No ability to add an anti-phishing token (like a login image or phrase)
- No ability to style/brand the login page
- "Forgot Password" needs to be added somewhere - No ability to put in an anti-CSRF token
Yes, that was an oversight on my part. See my reply to mixedbit downthread for a proposed solution with a slight change of syntax: just add another field that contains a nonce. - No ability to add an anti-phishing token (like a login image or phrase)
The phisher can fetch those images for you, making them more or less ineffective. Besides, the whole point of embedding a login button in the browser toolbar and making it pick the correct credentials is that the button will not work on any other domain. I'm trying to be backward compatible with as many existing websites as possible, but I can't achieve perfect compatibility with banks that won't listen to reason. - No ability to style/brand the login page
- "Forgot Password" needs to be added somewhere
Logos and links can be added to the real HTML login page, which will continue to exist. The API will not replace the login page. It's just another way to send the POST request. If you don't know your password you obviously can't tell your browser to remember it, so the login button will not work and you'll have to visit the real HTML login page anyway.