GitHub - privacycg/is-logged-in: The IsLoggedIn API (original) (raw)

Explainer: Login Status API

A Work Itemof the Privacy Community Group.

Editors:

Participate

Table of Contents

Introduction

This explainer proposes an API called the Login Status API with which websites can inform the web browser of the user's login status.

Currently, web browsers have no way of knowing if the user is logged in to a particular website. Neither the existence of cookies nor frequent/recent user interaction can serve that purpose since most users have cookies for and interact with plenty of websites they are not logged in to.

Why Do Browsers Need To Know?

The current behavior of the web is “logged in by default,” meaning as soon as the browser loads a webpage, that page can store data such as cookies virtually forever on the device. That is a serious privacy issue and also bad for disk and backup space. Long term storage should instead be tied to where the user is truly logged in.

There could be other powerful features and relaxations of restrictions besides storage that the web browser only wants to offer to websites where the user is logged in.

The ability to do these things requires knowledge of where the user is logged in.

Existing Functionality

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. However, there was never a way to log out. Regardless, those technologies are now 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.

Cookies and other kinds of storage may carry login state but there is no way to tell general storage and authentication tokens apart. Persistent cookies have an expiry function which could serve as an automatic inactivity logout mechanism whereas web storage such as IndexedDB doesn’t even have an expiry functionality.

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 recording a login could look:

navigator.recordLogin(
    username: non-whitespace string of limited length,
    credentialTokenType: “cookie”,
    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 cookie manages the expiry of the login.

Here’s how the API for recording a logout could look:

navigator.recordLogout(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 login status could look:

navigator.checkLoginState() –> 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 login 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 login status 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 login status even after the user logged out.

There are several ways the browser could make sure the login status is trustworthy:

Credential Tokens

Ideally, a new Logon Status API like this would only work with modern login credentials. The proposedHTTP State Tokenscould become such a modern piece. However, to ensure a smooth path for adoption, we should support cookies.

Both HTTP State Tokens and cookies would have to be explicitly set up for authentication purposes to work with the Login Status API. In the case of both of these token types, we could introduce an __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 cookie or token should be picked up as recordLogout().

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 login 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 the Login Status API.

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 Login Status API needs to support such logins.

This could be achieved through integration between the Login Status API and the proposed WebID.

If federated logins were to be supported by the Login Status API alone, it could look like this:

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.initiateRecordFederatedLogin(destination: secure origin) –> Promise<void>

For the promise to resolve, the user needs to already have login 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.recordFederatedLogin(
    loginProvider: secure origin,
    username,
    credentialTokenType,
    optionalParams { }
) –> Promise<void>

The promise would only resolve if the loginProvider had recently called initiateRecordFederatedLogin() for this destination website.

Challenges and Open Questions

Considered alternatives

[This should include as many alternatives as you can, from high level architectural decisions down to alternative naming choices.]

[Alternative 1]

[Describe an alternative which was considered, and why you decided against it.]

[Alternative 2]

[etc.]

Stakeholder Feedback / Opposition

[Implementors and other stakeholders may already have publicly stated positions on this work. If you can, list them here with links to evidence as appropriate.]

[If appropriate, explain the reasons given by other implementors for their concerns.]

References & acknowledgements

[Your design will change and be informed by many people; acknowledge them in an ongoing way! It helps build community and, as we only get by through the contributions of many, is only fair.]

[Unless you have a specific reason not to, these should be in alphabetical order.]

Former editor: Melanie Richards, Microsoft