Labs/Weave/Identity/Account Manager/Spec/1
Warning: This document is a DRAFT
- HTTP Extensions for Account Management and Session Identification
Authors: Michael Hanson and Dan Mills, Mozilla Labs
Contents
Introduction
This document specifies a set of extensions to the HTTP client/server message exchange that allow a server to describe an account-based user identification process in terms that a user-agent can understand. It is intended to complement existing practices around HTTP and cookie-based user identification, and to provide a graceful roadmap for adoption of new technologies over time.
Mozilla Labs is implementing client support for this protocol in the Account Manager browser extension.
This is an early draft and frequent changes are expected.
Informally, here's a VERY high-level overview of what we're trying to enable:
A web browser visits a new site. The site advertises to the browser that account management features are available. The browser user requests "connection" to the site. The browser negotiates account setup, possibly disclosing some personal information about the user, and learns a userid-credential pair. On a subsequent visit, the browser notices that it does not have an active session, and automatically establishes one. When the user requests "disconnection" from the site, the browser terminates the session. When the user views a "my accounts" page in his browser, she sees what information the site is storing about her.
Overview
The Account Management protocol provides mechanisms for a server to indicate to a client:
- Machine-readable direction as to how a user can create an account, log in to a session using an account identifier, log out of a session, collect information about an account, and/or change information about an account. A profile-based scheme is proposed to support various styles of account registration, including site-specific and federated identities, and various styles of authentication, such as username/password.
- A specific restricted-vocabulary indication of a user-agent's current session status with regard to a particular server or domain. This allows a server to signal to a user-agent that it is currently logged in with an affirmative identity, passively identified with a non-session-based identity, or anonymous to a server.
This proposal is NOT an attempt to deal with disclosure of per-user tracking technology that may be deployed by a server. The intent is only to provide a channel for a server to provide information that it chooses to disclose to the user-agent.
Account Management Realms
This proposal defines an "Account Management Realm" to be a set of HTTP(S)-addressed resources that are subject to a single account and session management control domain. In common practice, this means that they share a user session cookie.
It is an explicit goal of this protocol to support the description of user session status across an entire realm, even when not every URL or server in the realm participates in the protocol message exchange. This is intended to support large web properties, where a single host (e.g. "login.host.com") is responsible for issuing and clearing user session cookies.
Protocol Summary
On visiting a URL as the top-level document of a browser, a user-agent makes an "Account Management Status" determination for the page. This determination has three steps:
- The user-agent must determine what the Account Management Realm for the page is.
- The user-agent must access an Account Management Control Document for that realm.
- The user-agent must determine the Account Session Status for the page
The interpretation of the Control Document and the Session Status follows this message exchange overview.
Determining the Account Management Realm
The user-agent must follow this set of checks to determine an Account Management Realm on retrieving a resource:
- If the HTTP response has an "X-Account-Management" HTTP header, the realm is the value of this header.
- If there is no X-Account-Management header, the browser SHOULD discover the XRD Host Metadata for the domain of the resource. (as of this writing, this involves making an HTTP request to /.well-known/host-meta, or perhaps a DNS-based system TBD). The user-agent may apply standard HTTP caching practices to this metadata file.
Note that #2 means that an Account Management Realm defined in the Host Metadata applies to all resources on the host that do not provide an X-Account-Management header or a value in their HTML content.
See also the discussion in Security Considerations, below.
Determining the Account Management Control Document
The Realm MUST be a URL using the http or https scheme. The user-agent will retrieve the document by following the URL. The user-agent may cache this document according to standard HTTP cache control practices.
Determining the Account Session Status
The user-agent determines the account session status by following this set of steps:
- If the HTTP response for the resource has an "X-Account-Management-Status" HTTP header, the session status is the value of this header.
- If the HTTP response for the resource has a status that will cause a redirection (e.g., 303), the redirect MUST be followed and steps 1 and 2 repeated for the redirected-to resource. In the event that the redirected-to resource has no X-Account-Management-Status header, or it has a different value, the last resource to be loaded with the header will be used to determine the session status.
- If the resource currently being loaded corresponds to the sessionstatus method in the Control Document, the user-agent MUST abort and consider this attempt to determine the session status a failure.
- Otherwise, the browser MUST inspect the Control Document for the realm to see if a sessionstatus method definition is present. If one is present, the user-agent should execute that method to determine the session status.
The server is responsible for notifying the client of any changes to the current status of the session The user-agent MAY continue to present the last-reported status as current until notified otherwise.
The user-agent MAY use the sessionstatus method to request the current status at any time. The user-agent SHOULD use it after a client restart. user-agents SHOULD NOT request the status using the sessionstatus method on a page view, if the page contained the account status in the header or content.
Interpretation of the Account Session Status
The account session status value is a semicolon-delimited string. The first term of the status must be one of the values active, passive, or none. Following terms of the status are key-value pairs in the form <name>=<value>. The value may optionally be quoted with single or double quotes; if it is, the value may contain semicolons. If the value is not quoted, and semicolon in the value MUST be interpreted as a field delimiter.
These status values should be interpreted by a user-agent as follows:
active: The server is maintaining a session with the user-agent in the positive belief that it is interacting with the user associated with the account. No further credentials will be required to interact with the account. (NB that some applications, i.e. financial transactions, may require additional verification steps during a session. See Security Considerations, below).
passive: The server is maintaining a session with the user-agent according to some token other than a positive exchange of credentials, e.g. a long-duration cookie. The server may require the user to present additional credentials before taking action with the account.
none: The server is not maintaining a session with the user. It is up to the user-agent to render additional user interface elements if the user-agent believes that it has credentials that would allow a session to be established.
Legal keys in the attribute list are:
name: A human-readable label for the current session. The entire text of the string SHOULD be presented to the user as the current session identifier. In common practice, this will be the username, display name, or given name of the current user.
Example:
X-Account-Management-Status: active; name="Joe User"
Contents of the Account Management Control Document
The Account Management Control Document (AMCD) is a static document an Account Management Realm uses to advertise to a user-agent what account-related capabilities it supports, and details around how the user-agent may access them. These include specific methods, endpoints, schemas expected, and so on.
It is the responsibility of resources to refer to the AMCD. A single web host may contain multiple realms, and therefore multiple AMCDs. An Account Management Realm may span multiple web hosts. This feature of the protocol means that the contents of the AMCD are sensitive and require secure handling; see the Security Considerations section, below, for more detail.
The Control Document is a JSON document. It must be valid JSON; if any syntax errors are encountered during the processing of the document, the user-agent will discard the document and proceed as through the realm has no account management features. A server may provide localized versions of the document; user-agents should respect standard HTTP content negotiation practices (e.g. Accept headers) and standard HTTP content encoding principles apply for international text.
Top-level Attributes of the Document
methods: An object mapping profile names to objects. Each profile object maps method names to Method Descriptions (see section 4.2 below). The profile names are drawn from the list of Supported Account Managment Profiles; each profile defines a list of supported methods.
signature: maybe?
Method Descriptions
Each <profile name> element may contain any number of these method descriptions. Each method description must contain these properties:
method: One of the HTTP methods, e.g. GET or POST
path: An absolute path, which will be combined with the scheme and net-location provided in the domain attribute of the document to produce a URL. The path may contain the "?", "=", and "&" characters; it must not contain the "#" character, and if it does, the "#" character and all characters after it MUST be removed by the user-agent.
params: A dictionary of name-value pairs. The names that are legal here are defined by each method description; the value of each pair defines the name that will be used to submit that value. For example, in the connect method description, a dictionary entry of "username":"un" indicates that the username associated with the connection will be submitted as the "un" parameter.
The meaning of each method is determined by each profile. For the Username-Password Form Profile, see section 5.1 below.
Method status actions
Some methods allow customizable actions depending on success, failure, or other method-specific statuses.
The status action is a semicolon-delimited string. The first term of the status action is the status action name, and it must be one of the values load-url, reload, or do-nothing. Following the name are key-value pairs in the form <name>=<value>. The value may optionally be quoted with single or double quotes; if it is, the value may contain semicolons. If the value is not quoted, and semicolon in the value MUST be interpreted as a field delimiter. The list of valid key-value pairs depends on the status action name used:
- load-url
- url=<url to load>
- reload
- None
- do-nothing
- None
For example, in an onsuccess handler in the connect method:
onsuccess: load-url; url="/logged-in.html"
Profiles
Username-Password Form Profile
The Username-Password Form Profile is used for domains that maintain user records keyed on username, with a single password used as the credential for access. The profile is appropriate for domains that are keyed on unique user identifiers other than free-form passwords; in particular, it is appropriate for an email-address-and-password domain.
The profile name identifier for the Username-Password Form Profile is username-password-form.
The methods allowed in this profile are connect, disconnect, register, changepassword, sessionstatus, accountstatus. See the sections below for a definition of each method.
connect
Used to establish a user session with the domain. In common usage, submitting the request to the defined endpoint will cause a cookie to be set on the user-agent.
- Required properties
- params:
- username: Parameter name for the user's username.
- password: Parameter name for the user's password.
- Optional properties
- onsuccess: status-action
- onfailure: status-action
- Response interpretation
- The user-agent MUST verify the session status as specified in section 3.3.
- If the status could not be determined or is not active, or in the event of any 4xx or 5xx response or transport-level error, the user-agent MUST execute the onfailure action if specified. If not present, the user-agent SHOULD reload the current page.
- Otherwise, the user-agent MUST execute the onsuccess action if specified. If not present, the user-agent SHOULD reload the current page.
disconnect
Terminates an existing user session with the domain. In common usage, submitting the request to the defined endpoint will cause a cookie to be cleared on the user-agent.
- Required properties
- None.
- Optional properties
- onsuccess: status-action
- onfailure: status-action
- Response interpretation
- The user-agent MUST verify the session status as specified in section 3.3.
- If the status could not be determined or is not none, or in the event of any 4xx or 5xx response or transport-level error, the user-agent MUST execute the onfailure action if specified. If not present, the user-agent SHOULD reload the current page.
- Otherwise, the user-agent MUST execute the onsuccess action if specified. If not present, the user-agent SHOULD reload the current page.
register
Establishes a new ID and secret with the domain. Both usernames and email addresses are supported ID types.
- Required properties
- id-type: Type of identifier to use. Supported types are username and email.
- Optional properties
- params:
- id: The parameter name to send the ID in. Defaults to id.
- secret: The parameter name to send the secret in. Defaults to secret.
- id-maxlength: How many characters long the id can be. Default is 16.
- secret-type: Type of secret to use. The only supported type at this time is random, which is the default.
- secret-minlength: Minimum number of characters long the secret is allowed to be.
- secret-maxlength: How many characters long the secret should be. Defaults to 16.
- onsuccess: status-action
- onfailure: status-action
- Response interpretation
- A 2xx response is a success, the user agent SHOULD save the ID and secret for future use, and it MUST execute the onsuccess status action, if present.
- A 4xx response is a verification failure; see the section Verification error handling below. The user agent SHOULD, if possible, address the problem and retry the query. Note that the onfailure status action should not be executed in this case.
- Any other response, or upon any 4xx response that the user agent cannot correct, the user agent MUST execute the onfailure status action, if present. If onfailure is not present, it SHOULD reload the current page.
Note that it is possible for the user agent to prompt the user after receiving a 4xx response. In the event that the user cancels the operation, that shall be considered a failure and the user agent SHOULD execute the onfailure action.
Verification error handling
The server may reject an id/secret pair for a variety of reasons. Upon failing to verify the id or secret, the server MUST return status code 400 in its response. The body of the response MUST be a JSON-formatted object with at least one of the following properties:
- id-error: One of the literal strings "invalid-character", "over-max-length", "under-min-length", "id-already-in-use"
- secret-error: One of the literal strings "invalid-character", "over-max-length", "under-min-length"
For example:
{ "id-error": "over-max-length", "secret-error": "invalid-character" }
changepassword
Used to change the password associated with a username.
- Required properties
- username: Parameter name for the username.
- old_password: Parameter name for the old password.
- new_password: Parameter name for the new password.
- Optional properties
- new_password_verify: If present, the new password will also be submitted using this parameter name.
- Response interpretation
(fixme)
sessionstatus
Defines a way for a user-agent to determine its current session status.
- Required properties
- None.
- Optional properties
- onfailure: status-action
- Response interpretation
- The user-agent MUST verify the session status as specified in section 3.3.
- If the status could not be determined, or in the event of any 4xx or 5xx response or transport-level error, the user-agent MUST execute the onfailure action if specified. If not present, the user-agent SHOULD reload the current page. Regardless of the onfailure action, the user-agent SHOULD act as though the user is not logged in, but MAY, if it has a mechanism for doing so, indicate that the user's session status is in an error state.
accountstatus
Defines an endpoint used by the user-agent to retrieve the status of the account bound to the current session. The user-agent SHOULD NOT invoke the accountstatus method until it has successfully executed a connect method.
- Required properties
- None
- Optional properties
- None
- Response interpretation
A 2xx response may be interpreted by the user-agent by following the Data Identifiers in Content rules (section 7.1) described below. Any 4xx or 5xx response will be interpreted as an error.
Servers should return a 403 error if they expected a session for the accountstatus page and the user-agent failed to establish one.
Implementation Considerations
- Embedded Resources
The user-agent MUST NOT take Account Management steps for resources that are embedded in a document. This includes IFRAMEs, scripts, CSS stylesheets, images, and data retrieved by plugins.
- Respect for AUTOCOMPLETE=FALSE
It is conventional for websites to indicate that they wish to disable autocompletion of forms by placing the AUTOCOMPLETE attribute with a value of FALSE into the FORM element.
User-agents that implement Account Management features SHOULD respect this value as an indication by a website that it wishes not to participate in implementations of this protocol.
- HTTP Basic/Digest Access Authentication
Most common browser implementations of HTTP Access Authentication (RFC 2617) do not include the ability for the user to disconnect (stop sending the Authentication header). Since connect/disconnect are central metaphors to this specification, user agents SHOULD perform an HTTP method call for disconnect if it is so defined (see section 5.2.2).
Security Considerations
Rough notes on threats:
Information Disclosure Threat: User asks to create an account on Alice, but attacker gets them to create an account with Bob.
How: Inject an AccountManagement header, or META into a page at Alice, or compromise Alice's HostMeta. Or poison DNS on a non-SSL URL. When user requests account, Bob phishes Alice-domain data.
Countermeasures:
- Don't allow cross-domain AM realm (problem: Large, multi-domain sites like Yahoo! want it)
- Require strict hierarchical AM realm (problem: nobody with a content.host.com runs logins on host.com)
- Sign AMCD - but for what signing authority? If you can inject an AM header, you can lie there.
Sounds like the only safe approach is to require additional security if you want a cross-domain AM realm - forbid by default. But if we're putting something on both ends of the transaction, the attacker could do the same.
One countermeasure would be to provide a way to disable content-based (or even header-based) AM discovery (like CSP). That way even if you compromised Alice's content you couldn't do anything. If we have DNS-based host-meta discovery you can't reach anything good unless you compromise DNS.
Variant - same site: Alice and Bob are on the same domain, and we're counting on META or HTTP headers to indicate which realm we're in. e.g. http://host.com/~alice and http://host.com/~bob - Bob hacks Alice and sets her AM to http://host.com/~bob/account_mgmt. That one is pretty tough.
Credential Theft Threat: User asks to log into Alice, but actually sends their credentials to Bob.
How: Inject an AM header or META, or compromise HostMeta, or poison DNS for non-SSL.
Counterfeit registration - is this a threat?: Bob injects content onto a page that fools the browser into thinking it is undergoing a registration procedure (i.e. through FORM rel attribute injection, perhaps with hidden username and password fields). When the browser reaches the next page, it creates a username-password record for the site that has a value known to Bob.
Does this accomplish anything useful? All Bob has done is scribble over the password stored already for Alice. Right now this looks like vandalism rather than a serious attack.
How to handle periodic credential challenges: Some websites (e.g. commerce and financial applications) require additional credential challenges, even after a user correctly responds to a session-establishment challenge.
Appendix A: Account Management Control Document Example
{ "methods": { "http-auth": { "connect": { "method": "GET", "path": "/signin/" }, "disconnect": { "method": "GET", "path": "/signout/" } } "username-password-form": { "connect": { "method":"POST", "path":"/signin/", "params": { "username":"unam", "password":"pwd" } }, "disconnect": { "method":"POST", "path":"/signout/" }, "register": { "method":"POST", "path":"/register/", "type": "email" }, "changepassword": { "method":"POST", "path":"/changepass/", "params": { "username":"unam", "old_password":"old_pwd", "password":"pwd", "password_verify":"pwd2" } }, "sessionstatus": { "method":"GET", "path":"/sessionstatus" }, "accountstatus": { "method":"GET", "path":"/account_status" } } } }
Appendix B: Host-meta example
<?xml version='1.0' encoding='UTF-8'?> <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'> <Link rel='http://services.mozilla.com/amcd/0.1' href='/path/to/your/amcd'/> </XRD>