On Sat, Feb 25, 2012 at 2:44 PM, Lloyd Hilaiel <
ll...@hilaiel.com> wrote:
>
> I think this is the right question to start with. It
> took me personally a couple months to become comfortable with this API
> change,
> as API complexity can hurt adoption, and I really want to see BrowserID
> succeed
> deep down in the cockles of my heart.
>
> So In short, we can do at least two important things with this change:
> 1. Make all sites that use browserid have robust support for users logging
> in on computers that are not their own.
> 2. Improve UX public enemy #1 - make it easier to verify your email
> address the
> first time you use browserid.
>
> Those two motivations are what I chose to focus on in the post that
> proposes the
> API. Before writing that, I wrote a much longer, more gory post that
> explores
> the costs, benefits, and requirements in more depth:
>
>
http://lloyd.io/doing-more-with-browserid
Ok I think I grasp this now. In a way, it becomes a lot more like Facebook
auth:
#1 is: You want "logout of browserid" to be the same as "logout from all
applications which you logged into with browserid". Right now browserid is
really just an authentication service, not a session service.
#2 is: Since browserid will maintain session state on behalf of the
application, it needs to inform the application of changes. In particular,
it needs to inform the application of login when that action takes place in
some other window or possibly even other web browser.
So... our website, Voost, is now public (to be announced widely tomorrow).
You can look at our approach to dual-auth (Facebook and BrowserID) here:
https://www.voo.st/
We've done a little usability testing and we are definitely concerned about
the signin with browserid flow. Our first test subject *closed the
browserid dialog* (doh!) before going to check her email for the link.
After clicking on the link, she found herself on a big browserid page and
felt lost.
This would be significantly improved simply by including a link to the
originating site on the final page at browserid. Even if it just landed
them back on an unauthenticated page and they have to click Sign In again,
it at least gets them back to our site. This is something you could do now
without any API changes.
I can see how an event-based system improves the options here - the page
can be aware of auth state changes even without explicitly asking for them.
Another solution, which covers the server side nicely, is to set a signed
cookie. Facebook does this, although they've been asshats about
documenting it (standard behavior from those guys). The server can
evaluate the cookie and render a logged-in experience or a logged-out
experience without a page flicker.
I find all three mechanisms valuable in different situations:
1) Explicit get current logged-in status (ie, FB.getLoginStatus())
2) 'login' and 'logout' events fire
3) A signed cookie is set
BrowserID has a signed value - the assertion, but it's kinda fat to make a
cookie. On the other hand, it's not atrocious and I wouldn't hesitate to
use it that way in my app.
> * How would this even-based system work in the context of a dual-auth
> > system (say, Facebook and BrowserID)? In particular, with persistent
> login:
> >
> > -- Let's say I want to have FB auth take precedence over BrowserID.
>
> This makes me think we should really build a simple app which does this as
> well as we can muster, both as an example and to ensure that BrowserID
> works
> right in this scenario. There are a lot of features that have been
> explored
> to optimize this that we can explore in this demo.
>
> It sounds is one question to start with: What authentication mechanism
> does this
> user prefer. You can capture this information in an informational cookie,
> and then
> optimize the login screen based on what this cookie says. It can be based
> on
> explicit user behaviors (logged in with facebook in the past from this
> browser,
> or clicked the browserid sign-in button in the past).
>
> Concretely, I'm saying what if you only register for browserid events
> when you already know that the user uses browserid? So a new user, would
> have to
> explicitly state their preference?
>
This does not sound good to me. It sounds like the UX will be broken (or
at least hopelessly complicated) when UserB sits down at a computer that
UserA was using when UserA and UserB log in with different methods. At the
very least, if we never start watching for BrowserID, the browser chrome
login button can't work. Seems to me that any functional system must
always be sensitive to login events from all sources.
I'm actually not disappointed with Voost's existing UX (other than getting
the user back from browserid). Click on either button to log in.
Persistent login is tried in sequence, with FB preferred.
The really complicated aspects of dual-auth surround merging accounts when
a user logs in with both Facebook and BrowserID. Same email == same
account is easy, but we have to handle the other cases. To give you an
idea, here's two:
CASE A:
* UserA sits down, logs into Voost via BrowserID
* UserA steps away from keyboard
* UserB sits down, logs into Facebook
* UserB visits Voost
Presume that UserB normally logs into Voost through Facebook. Voost gets a
FB login event for UserB; either we ignore it or we use this to replace
existing credentials.
CASE B:
* UserA sits down, logs into Voost via BrowserID
* UserA clicks on Voost "your account" page
* UserA clicks on "Attach Facebook" and logs in with Facebook
If UserA's email address is different on FB (and it often is), now we get a
FB login event that is indistinguishable from the above case. But somehow
we need to know that this is an intentional "merge account" action.
The solution is that we don't use FB's event handling system at all. For
us, login occurs:
* Via persistent login, explicitly fetched at page load
* As a callback to an explicit login call when user clicks either Sign In
button
* As a callback to an explicit "merge accounts" login call
If Facebook only offered an event-based system, we'd be in trouble with no
way to distinguish a deliberate merge operation.
With BrowserID, we have a similar problem: Changing email address. A user
can be logged in with Facebook but want to change their email address. Try
it. We just figure up the BrowserID login process and treat the callback
as a deliberate "change my email" operation. If this was purely
event-based, we have the problem of distinguishing between a "UserB logs
in" situation and a "change my email" situation.
Maybe this is something that can be solved with an explicit change email
API.
> Also, it means the server
> has to either a) fetch this info from persistent storage with every page
> > hit, or b) encode it into whatever signed token gets passed back and
> forth
> > with every request to represent to the server what the signed in ID is.
> > This makes the "change email address" process even more convoluted. Do I
> > understand this correctly?
>
> I think I understand, and yes, the server would need to extract the
> currently
> signed in user from their "session", be that encrypted cookies or more
> traditional
> server side sessions with a session identifier in a cookie. And yes, the
> server
> would need to then ship this information down for each page request in
> time for
> page load. But this is specific to the event proposal.
>
> The key interesting question for me in the event proposal vs. .watch() is
> that the
> .watch() approach allows for the possibility of delaying this stuff until
> after
> the initial DOM is loaded, and lets you write a site with 99+% highly
> cachable
> common resources and then bring in auth stuff in a tiny request post page
> load and render.
>
watch() does seem superior to the previously described event handling
system.
The thing I want to point out is that this idea of pages that load, then
fetch auth and other data, is not really how people build web applications.
Yes, for many pages there is often data fetched post-load. But *very* few
applications render pages without knowing the authentication state of the
user. Not even Google does this. The only apps that can afford to do this
are single-page webapps where a long initial startup is ok. Most
page-by-page apps simply can't wait for dom load, auth state to resolve,
fetch user-based data, then rerender the page... all in serial. I don't
expect this to change without an order of magnitude drop in worldwide
network latency, so it seems odd to optimize for this use case.
This is why I hate the
myfavoritebeer.org example. The only apps that
actually work like this are single-page GWT-type apps. I've written them,
it's a nice solution for some problem domains, but it's not likely to
become the dominant app architecture anytime soon. So the canonical
example of BrowserID usage is, basically, giving you an unrealistic view of
RP requirements.
Jeff