Re: Explainer: IsLoggedIn (in preparation for TPAC)

Hi Brad!

> On Sep 12, 2019, at 3:04 PM, Brad Hill <hillbrad@gmail.com> wrote:
> 
> Just as a first pass, it feels like there is already a widely deployed
> and well understood mechanism for doing this, which is
> private/incognito browsing mode.

There are three important differences:
We are not saying the lack of IsLoggedIn has to behave like Private Mode. We’re just saying the current practice of dropping >10 year cookies on users as soon as they visit a website is not acceptable. The browser needs to know where the user is logged in to be able to support long(er) term logins while setting a cap on storage which resulted from casual visits.
Private Mode is ephemeral. We are not saying browsers have to make non-logged in website visits ephemeral. In fact, you can’t persistently log in to a website in Private Mode so this is a very different thing.
Private Mode is opt-in. We’re trying to address things for regular browsing mode.

> I'd love to hear from those who've worked on existing
> private/incognito browsing about what kinds of compatibility issues
> they see and what they expect might happen if that mode were the
> default.  Has anyone done an experiment where people were asked or
> allowed to make that the default?  How many people stuck with it and
> how many switched back?
> 
> Your own suggestion of browsers managing some of this transparently
> based on user engagement is already being done by Chrome:
> https://www.chromium.org/developers/design-documents/site-engagement
> I'd love to understand why this kind of model isn't adequate to
> mitigate the harms you describe, without imposing update costs on the
> developer community to update every site with this (and imposing
> breakage on the user community at sites that don't update).

As mentioned in the explainer, there’s value in knowing where you are logged in as opposed to just knowing where you tap/click. Logging in and staying logged in is different from “visit daily.” We can use the IsLoggedIn signal to help the user stay logged in for instance. We could also gate privileged functionality on being logged in.

> I also don't know that, even if this is a good idea, that we should
> tie statefulness to the concept of being "logged in".  I think
> people's mental model of being "logged in" is not just state
> maintenance, but of durably attaching PII to state so that it can be
> accessed/restored in new contexts like a different device or browser.
> I feel there is substantial user privacy benefit in being able to have
> durable state in a single context which is not (yet) attached to PII.
> e.g. I can shop and fill a cart, but not "log in" until I want to
> check out.  If I come back a week later, it's good that my cart is
> still there and I don't feel like I've suffered any real privacy harm
> from that.  It's more harmful to my privacy if I have to log in and
> provide what is likely a global identifier (email address) just to
> start browsing, or play a game, etc.

We’re not suggesting that things in your shopping cart should be gone if you come back days later. But if you came back after a month?

> This is, coincidentally, exactly what Apple's App Store guidelines
> recommends apps do - delay requiring login until it is needed by the
> scenario.  I know you work on the web platform, but it's worth asking
> - is Apple considering limiting and regularly clearing storage +
> rotating IDFA for apps that haven't collected an affirmative "user
> logged-in" flag through the password manager or an ASWebAuthentication
> session? If you wouldn't do this in an app because it's a bad user
> experience for an app, why would you do it for the web?  Why is
> maintaining 1:1 state with a web site in a browser more harmful to
> privacy than maintaining state in an app on a device?

The web is by its nature a more ephemeral thing than installed software. You get a link in a text message, from a friend on a social network, through email, or a QR code somewhere. You should be able to follow those links without the browser treating your visits as logged in by default.

> From a publisher side, wouldn't this really negatively impact the
> ability to get compliance with soft paywalls?
> 
> It seems like the incentive this ultimately creates is for every site
> to push people to "log in" immediately at first touch, the way sites
> in the EU have done with cookie banners. I don't know many people who
> feel that cookie banners have made the world better in any way, and
> stacking up yet another dialog that means substantially the same thing
> (can we manage some state for you on this site) doesn't feel like
> something people would welcome.

As said, we’re not saying that the lack of IsLoggedIn has to behave like Private Mode. But we think there should be a possibility for browsers to have different storage expiry policies for sites the user logs in to and sites the user visits casually. It’ll be up to browsers to find the balance where this does not lead to mandatory login across the web.

Users might not have a high engagement index on every site they want to stay logged in to. Users also don’t want to be remembered and tracked by websites they’ve visited once or only casually. To figure out this balance, we think the IsLoggedIn signal is useful.

   Regards, John


> On Wed, Sep 11, 2019 at 3:11 PM John Wilander <wilander@apple.com> wrote:
>> 
>> Hi WebAppSec!
>> 
>> TPAC is around the corner and one of the agenda items is "Login API” with my name attached to it. Below is an explainer of what we want to achieve. I think Wendy is working on an “Unofficial Drafts” repo for our working group where I can put this for more of issue tracking style feedback. But I wanted to get something out today since there’s not much time left before we meet in Fukuoka.
>> 
>> Looking forward to the event and your thoughts on IsLoggedIn.
>> 
>>   Regards, John
>> 
>> # Explainer: IsLoggedIn
>> 
>> ## Motivation
>> 
>> We need a way for websites to declare to the browser that the user is logged in or out, and for those declarations to be trustworthy. This is why:
>> 
>> ### The Browser Should Know Where You’re Logged In
>> 
>> In olden times, Basic/Digest Authentication offered a way for browsers to know where the user was logged in and help them to stay logged in. Those technologies are obsolete for many reasons. Today, WebAuthn and password managers (including the use of Credential Management) offer a browser-managed way to log in but those features neither cover the expiry of the logged in session nor the act of logging out. We have yet to standardize a way for browsers to manage the logged in status.
>> 
>> ### The Current (Bad) Behavior Is “Logged In By Default”
>> 
>> For the purposes of client-side storage/state, the behavior of the web platform has been “logged in by default,” meaning as soon as the browser loads a webpage, that page can store data virtually forever on the device, and the browser may have to treat the user as logged in to that website. That is a serious privacy issue. Long term storage should instead be tied to where the user is truly logged in.
>> 
>> DOM storage such as IndexedDB doesn’t even have an expiry functionality, making it impossible for websites who use these storage mechanisms to state any guarantees on when traces of a visit to their site will go away.
>> 
>> As an additional note, allowing an ever growing, never expiring pile of website data from sites the user may have visited just once is bad for disk space and backup space.
>> 
>> ### Clearing Website Data May Log Users Out
>> 
>> Browsers may try to fix or mitigate the privacy implications of “logged in by default” by cleaning up storage and state at some cadence. Browsers may also evict cookies because of storage limits or truncate cookie request headers because of header limits. If the browser doesn’t know where the user is logged in, website data cleaning or limits may inadvertently log the user out of some websites, leading to a bad user experience.
>> 
>> ## Straw Man Proposal
>> 
>> Below we present a straw man proposal for how a web API for logged in status could look and work. This is a starting point for a conversation, not a fully baked proposal.
>> 
>> ### API
>> 
>> Here’s how the API for setting IsLoggedIn to true could look:
>> 
>> navigator.setLoggedIn(
>>    username: non-whitespace string of limited length,
>>    credentialTokenType: “httpStateToken” OR “legacyAuthCookie”,
>>    optionalParams { }
>> ) –> Promise<void>
>> 
>> The returned promise would resolve if the status was set and reject if not. The API could potentially take an expiry parameter but here we’re assuming that a designated HTTP State Token or “legacy auth cookie” manages the expiry of the login through their own mechanisms.
>> 
>> Here’s how the API for setting IsLoggedIn to false could look:
>> 
>> navigator.setLoggedOut(optionalUsername) –> Promise<void>
>> 
>> The optional username parameter highlights that we might want to support concurrent logins on the same website which would require the site to keep track of who to log out and credential tokens to be scoped to user names.
>> 
>> Here’s how the API for checking the IsLoggedIn status could look:
>> 
>> navigator.isLoggedIn() –> Promise<bool>
>> 
>> This last API could potentially be allowed to be called by third-party iframes that do not currently have access to their cookies and website data. The iframes may want to render differently depending on whether the user is one of their logged in customers or not.
>> 
>> ### Defending Against Abuse
>> 
>> If websites were allowed to set the IsLoggedIn status whenever they want, it would not constitute a trustworthy signal and would most likely be abused for user tracking. We must therefore make sure that IsLoggedIn can only be set when the browser is convinced that the user meant to log in or the user is already logged in and wants to stay logged in.
>> 
>> Another potential for abuse is if websites don’t call the logout API when they should. This could allow them to maintain the privileges tied to logged in status even after the user logged out.
>> 
>> There are several ways the browser could make sure the IsLoggedIn status is trustworthy:
>> 
>> Require websites to use of WebAuthn or a password manager (including Credential Management) before calling the API.
>> Require websites to take the user through a login flow according to rules that the browser can check. This would be the escape hatch for websites who can’t or don’t want to use WebAuthn or a password manager but still want to set the IsLoggedIn bit.
>> Show browser UI acquiring user intent when IsLoggedIn is set. Example: A prompt.
>> Continuously show browser UI indicating an active logged in session on the particular website. Example: Some kind of indicator in the URL bar.
>> Delayed browser UI acquiring user intent to stay logged in, shown some time after the IsLoggedIn status was set. Example: Seven days after IsLoggedIn was set – “Do you want to stay logged in to news.example?”
>> Requiring engagement to maintain logged in status. Example: Require user interaction as first party website at least every N days to stay logged in. The browser can hide instead of delete the credential token past this kind of expiry to allow for quick resurrection of the logged in session.
>> 
>> 
>> ### Credential Tokens
>> 
>> Ideally, a new IsLoggedIn API like this would only work with modern login credentials. HTTP State Tokens could be such a modern piece. However, to ensure a smooth path for adoption, we probably want to support cookies as a legacy option.
>> 
>> Both HTTP State Tokens and cookies would have to be explicitly set up for authentication purposes to work with IsLoggedIn. In the case of both of these token types, we could introduce a __auth- prefix as a signal that both the server and client consider the user to be logged in. Or we could allow HTTP State Token request and response headers to convey login status. Note that sending metadata in requests differs from how cookies work.
>> 
>> The expiry of the token should be picked up as a logout by IsLoggedIn.
>> 
>> Cookies have the capability to span a full registrable domain and thus log the user in to all subdomains at once. HTTP State Tokens have a proper connection to origins but can be declared to span the full registrable domain too. We should probably let the credential token control the scope of the IsLoggedIn status.
>> 
>> Explicitly logging out should clear all website data for the website, not just the credential token. The reverse, the user clearing the credential token (individually or as part of a larger clearing of website data), should also log them out for the purposes of IsLoggedIn.
>> 
>> ### Federated Logins
>> 
>> Some websites allow the user to use an existing account with a federated login provider to bootstrap a new local user account and subsequently log in. The IsLoggedIn API needs to support such logins.
>> 
>> First, the federated login provider needs to call the API on its side, possibly after the user has clicked a “Log in with X” button:
>> 
>> navigator.initiateLoggedInFederated(destination: secure origin) –> Promise<void>
>> 
>> For the promise to resolve, the user needs to already have the IsLoggedIn status set for the federated login provider, i.e. the user needs to be logged in to the provider first.
>> 
>> Then the destination website has to call the API on its side:
>> 
>> navigator.setLoggedInFederated(
>>    loginProvider: secure origin,
>>    username,
>>    credentialTokenType,
>>    optionalParams { }
>> ) –> Promise<void>
>> 
>> The promise would only resolve if the loginProvider had recently called setLoggedInFederated() for this destination website.
>> 
>> ## Challenges and Open Questions
>> 
>> Grandfathering. Some websites may not want to prompt an already logged in user or take them through an additional login flow just to set the IsLoggedIn status.
>> Expiry limit. What is a reasonable limit for expiry without revisit/re-engagement?
>> Single sign-on. If the browser supports First Party Sets, it may support single sign-on within the first party set, for instance with an optional parameter includeFirstPartySet: [secure origin 1, secure origin 2]. The browser would check the integrity of the first party set claim and potentially ask the user for their intent to log in to multiple websites at once before setting the IsLoggedIn status for all of them. The expiry of the login status for the first party set would likely be controlled by the expiry of the credential token for the single sign-on origin. However, there is not browser agreement on how to support First Party Sets in a privacy preserving way (see Issue 6 and Issue 7).
>> A full-fledged Login API. As we’ve discussed IsLoggedIn, we’ve also talked about what an API that actually logs the user in would look like, i.e. navigator.logIn(), navigator.logOut(), and navigator.isLoggedIn(), where either credential tokens are passed to the browser or the browser is asked to generate them. That may be where the WG prefers to go so we’re adding it here.
>> 
>> 
> 

Received on Friday, 13 September 2019 00:22:57 UTC