Identity/BrowserID: Difference between revisions
(→API) |
|||
| Line 185: | Line 185: | ||
* A <tt>login</tt> event if the user chose to log in. This event MUST include the Backed Identity Assertion in the <tt>assertion</tt> property. | * A <tt>login</tt> event if the user chose to log in. This event MUST include the Backed Identity Assertion in the <tt>assertion</tt> property. | ||
XXX: should we provide error information if it's not just a user cancel? | |||
==== Provisioning ==== | |||
The User Agent should support a provisioning workflow when a user wants to authenticate with a new email address. A provisioning workflow is initiated with some context: | |||
* the email address being provisioned | |||
* information about the security status of the session (user's own computer, shared computer, public computer, ...) | |||
During a provisioning action, the User Agent MUST support the following API calls: | |||
<tt>navigator.id.beginProvisioning(object callback)</tt> | <tt>navigator.id.beginProvisioning(object callback)</tt> | ||
The callback function SHOULD accept parameters <tt>email</tt> and <tt>cert_duration_s</tt>. | The callback function SHOULD expect the callback function to accept parameters <tt>email</tt> and <tt>cert_duration_s</tt>. | ||
In response to this call, the user agent should invoke the callback | |||
<tt>navigator.id.genKeyPair(object callback);</tt> | <tt>navigator.id.genKeyPair(object callback);</tt> | ||
Revision as of 20:01, 19 January 2012
MediaWiki editor tip: If you aren't seeing numbered section headings in the body of this document, you can force them to appear by logging in and clicking the "My preferences" link, at left, and select "Auto-number headings"
- DRAFT
IN PROGRESS
This document is in progress. Please consult:
Past blog posts contain a lot of information, for example: BrowserID Design for Privacy
Overview
This specification, BrowserID, defines a mechanism for websites to request, from the user via her user-agent, a signed assertion of email-address ownership. Web sites can use this mechanism to register users on their first visit and log them back in on their subsequent visits. The trust path for these assertions of email-address ownership is designed to be federated and decentralized: individual domains can certify their own users. A fallback secondary authentication mechanism is defined to bootstrap the protocol for domains that do not yet support it.
Terms
- Identity
- An email address controlled by the user.
- Public Key
- The public portion of an asymmetric cryptographic keypair used in a digital signature algorithm.
- Identity Certificate
- A digitally signed statement that binds a given public-key to a given Identity.
- Primary Authority
- A signer of Identity Certificates for identities that are directly within this authority's domain, e.g. example.com certifies *@example.com.
- Secondary Authority
- A signer of Identity Certificates for identities that are not directly within this authority's domain.
- Audience/Relying Party
- A system, typically a web site, that needs to verify an Identity.
- Identity Assertion
- A digitally signed statement that a login is requested to a particular relying party.
- Backed Identity Assertion
- An Identity Assertion combined with the requisite Identity Certificates that enable a Relying Party to fully verify the Identity Assertion.
Objects / Messages
BrowserID defines messages using the JOSE specifications for signing JSON-formatted objects.
Public Key
A BrowserID public key is a JSON object that includes fields:
- alg the algorithm for which this key was generated, using JOSE taxonomy
- additional fields specified by the algorithm, e.g. n and e for RSA public keys.
For example:
{
"alg": "RS256",
"n" : "4b3c34...",
"e" : "93bc32...",
}
This data structure should move to JSON Web Keys.
Identity Certificate
An Identity Certificate is a JWT object with the following claims:
- exp the expiration as per JWT
- iss the domain of the issuer as per JWT
- public-key the serialized public key as defined above
- principal the principal being certified.
The principal is a JSON object that indicates the type of principal, e.g.
{"email": "bob@example.com"}
or
{"host": "intermediate.example.com"}
A complete JWT set of claims then looks like:
{
"iss": "example.com",
"exp": "1313971280961",
"public-key": {
"alg": "RS256",
"n" : "4b3c34...",
"e" : "93bc32...",
},
"principal": {
"email": "john@example.com"
}
}
Which, when signed, becomes a base64url-encoded data structure which looks like (with linebreaks and truncated values for for easier reading):
eyJhbGciOiJSUzI1NiJ9. eyJpc3MiOiJicm93c2VyaWQub3JnIiwiZXhwIjoxM... hv5wVN0HPINUZlLi4SJo9RzJhMU5_6XZsltYWODDD...
The JOSE spec currently does not specify a certificate format beyond JWS signatures. If it eventually does, we will consider moving to it.
Identity Assertion
An Identity Assertion is a JWT with the following claims:
- exp for expiration
- aud for the relying party (audience.)
An assertion might look like (with line breaks for readability):
eyJhbGciOiJSUzY0In0. eyJleHAiOjEzMjAyODA1Nzk0MzcsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6MTAwMDEifQ. JmEBqwOH_qzw6_EHsCRB-CeShGyQ2y0bpapARZ308_8uT6TCWrKBpB8L2bFnMb664lz1nGytkBXF-tTIzGCOjg
which is a JWT with header:
{"alg": "RS64"}
and a payload of:
{"exp":1320280579437,"aud":"http://localhost:10001"}
Backed Identity Assertion
A Backed Identity Assertion is a combination of an Identity Assertion and a singe sequence of Identity Certificates that verifiably tie the assertion to an issuing domain. Most often, a backed identity assertion is a single certificate tying a public-key to an Identity, signed by the domain, and an Identity Assertion signed by the just-certified public key.
A Backed Identity Assertion is:
<cert-1>~...<cert-n>~<identityAssertion>
where each cert and the identity assertion are base64url-encoded data structures, as defined above.
Main Protocol Flow
This section is informative.
Consider a web site, http://example.com, receiving a visit from a user. This web site wishes to obtain the user's verified email address using BrowserID. The user in question, for the purposes of this description, is Alice. Alice owns two email addresses, alice@homedomain and alice@workdomain.
- example.com presents a login button with a JavaScript click handler.
- when Alice clicks the login button, example.com's click handler invokes
navigator.id.get();
- Alice is presented with a user-agent dialog that lets her select which email to present to example.com.
- If Alice chooses to cancel the transaction, a loginCancelled event is fired on the navigator.id object, which example.com can choose to listen for.
- If Alice chooses to authenticate using one of her email addresses, a login event is fired on the navigator.id object, which example.com should listen for. The event's assertion property is filled with a Backed Identity Assertion.
- example.com should take this assertion and pass it back to its server. This can be accomplished with an AJAX request. For example, using jQuery:
function gotAssertion(assertion) {
if (!assertion) {
alert('you canceled login!');
} else {
$.post("/verifyAssertion", {assertion: assertion}, afterVerifyAssertion);
}
}
This assertion is a Backed Identity Assertion, as defined above. We call it assertion here for simplicity, since the Relying Party typically need only pass this assertion to a verifier service without worrying about the specific assertion contents.
Identity Provisioning Flow
This section is informative.
User-Agent Compliance
This section is normative.
The User-Agent is critical for BrowserID support. Here, we define, normatively, the API that user agents MUST implement, including specific behaviors in response to these API calls. Relying Parties and Identity Providers can safely skip this section.
API
A compliant BrowserID User-Agent must implement the navigator.id object, with API calls as described here.
navigator.id.get(object options);
The Relying Party MAY call the navigator.id.get method when it wishes to request that the User Agent generate an identity assertion as soon as it can. The User Agent SHOULD immediately seek to generate an Identity Assertion and complete it with appropriate certificates to form a Backed Identity Assertion. This is likely to require prompting the user, and the User Agent may do this in whatever way it deems appropriate.
The User Agent MUST fire one of two events on the navigator.id object:
- A loginCancelled event if the user chose not to log in.
- A login event if the user chose to log in. This event MUST include the Backed Identity Assertion in the assertion property.
XXX: should we provide error information if it's not just a user cancel?
Provisioning
The User Agent should support a provisioning workflow when a user wants to authenticate with a new email address. A provisioning workflow is initiated with some context:
- the email address being provisioned
- information about the security status of the session (user's own computer, shared computer, public computer, ...)
During a provisioning action, the User Agent MUST support the following API calls:
navigator.id.beginProvisioning(object callback)
The callback function SHOULD expect the callback function to accept parameters email and cert_duration_s.
In response to this call, the user agent should invoke the callback
navigator.id.genKeyPair(object callback);
The callback function SHOULD accept parameter pubkey, a serialized public-key string as per the above public-key spec.
navigator.id.registerCertificate(certificate);
The certificate parameter MUST be a valid serialized certificate, as per the above spec. The trust root for this certificate SHOULD comply with the characteristics described in the "Acceptable Trust Paths" section below.
navigator.id.raiseProvisioningFailure(string reason);
The reason parameter MUST be a string that can be reported to the user regarding the reason why a certificate failed to be provisioned.
WebIDL:
module navigator {
module id {
void beginProvisioning(object callback);
void genKeyPair(string email, object callback);
void registerCertificate(string certificate, string updateURL);
void raiseProvisioningFailure(string reason);
}
};
FIXME: the below needs complete revision
To process a request for identity registration from a web page, a User-Agent MUST:
- Create, if it has not already done so, a local data store that will persist beyond the current page view, keyed on email identity.
- Check the local data store for whether a certificate for the email address already exists and is valid. If so, the User-Agent SHOULD NOT proceed with key generation, and instead immediately call the provided callback to genKeyPair with a null argument.
- If no certificate already exists, the User-Agent MAY notify the user that a new email identity is being registered with the User-Agent. If the email identity has a domain that is different from the Identity Authority, the User-Agent SHOULD notify the user and seek confirmation.
- Produce an asymmetric keypair compatible with the JSON Web Key specification [JWK] and store it in the local data store.
- Return the public key to the JavaScript runtime of the web page through the provided callback.
- At a future point, when the registerCertificate function is called by a web page, the User Agent MUST verify that the public key in the Identity Certificate matches the already-stored keypair for the email identity in question. If it does not match, the User-Agent SHOULD reject the certificate and (do what?).
- Save the new certificate, as well as the refreshURL and errorURL arguments of the registerVerifiedEmailCertificate function.
Identity Assertion Generation
To process a request for a verified email, a User-Agent MUST:
- Reliably establish the full domain of the requesting site (including scheme and non-standard port).
- Check a local data store for previously established identity associations for the requesting site. If one or more associations are found, the User-Agent MAY ask the user for which identity to use, or automatically choose one based on some criteria (e.g., last-used).
- If no associations are found, the User-Agent SHOULD ask the user for what to do, by presenting a list of known email identities to choose from.
- If no email identities are known, the User-Agent MAY assist the user in any way it sees fit. [xxx ?]
- Verify the expiry date of the certificate associated with the identity of the previously-chosen association. If the certificate has expired, or would expire before the intended validity period of the assertion to be generated, the User-Agent MUST follow the steps in the CERTIFICATE REFRESH section of this specification.
- Create an Identity Assertion object for the chosen identity, scoped to the full domain of the requesting site (including scheme and non-standard port), and sign it with the private key associated with the chosen identity.
- Execute the navigator.id.onVerifiedEmail callback and provide the newly-created Identity Assertion as an argument.
Certificate Refresh
- To refresh a certificate, the User-Agent MUST fetch the resource located at the refresh URL provided by the Identity Authority in the registerVerifiedEmailCertificate for the certificate to be refreshed. The User-Agent SHOULD NOT display this resource to the user.
- If the server returns with an error status when loaded (in the 4xx or 5xx range), certificate refresh has failed. The User-Agent SHOULD notify the user and load the error URL associated with the certificate at registration time. This resource SHOULD be visible to the user, who is expected to interact with the Identity Authority to resolve the problem.
- If the server returns with 2xx status, the loaded resource is expected to follow the steps under section 1.4 (Identity Registration) to sign new keys for the user.
- The User Agent MUST maintain the resource loaded and operational for at least 30 seconds since last activity (network or JavaScript) to allow the Identity Authority to register multiple certificates if it wishes.
Primary Authority Compliance
This section is normative.
Declaring Support for Verified Email
Certifying Users
Assertion Verification
Backed Identity Assertions SHOULD NOT be verified in the client, in JavaScript or otherwise, since client runtimes may be altered to circumvent such verification. Instead, Backed Identity Assertions SHOULD be sent to a trusted server for verification.
To verify a Backed Identity Assertion, a Relying Party SHOULD perform the following checks:
- If the exp date of the assertion is earlier than the current time by more than a certain interval, the assertion has expired and must be rejected. A Relying Party MAY choose the length of that interval, though it is recommended that it be less than 5 minutes.
- If the audience field of the assertion does not match the Relying Party's origin (including scheme and optional non-standard port), reject the assertion. A domain that includes the standard port, of 80 for HTTP and 443 for HTTPS, SHOULD be treated as equivalent to a domain that matches the protocol but does not include the port. (XXX: Can we find an RFC that defines this equality test?)
- If the Identity Assertion's signature does not verify against the public-key within the last Identity Certificate, reject the assertion.
- If there is more than one Identity Certificate, then reject the assertion unless each certificate after the first one is properly signed by the prior certificate's public key.
- If the first certificate (or only certificate when there is only one) is not properly signed by the expected issuer's public key, reject the assertion. The expected issuer is either the domain of the certified email address in the last certificate, or the issuer listed in the first certificate if the email-address domain does not support BrowserID.
- If the expected issuer was designated by the certificate rather than discovered given the user's email address, then the issuer SHOULD be browserid.org, otherwise reject the assertion.
Note that a relying party may, at its discretion, use a verification service that performs these steps and returns a summary of results. In that case, the verification service MUST perform all the checks described here. In order to perform audience checking, the verification service must be told what audience to expect by the relying party.
Security Considerations
things to write about:
- certificate validity period
- UAs reusing a key to get a new certificate
- timing attacks
- javascript implementations, good RNGs