Identity/BrowserID: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 170: Line 170:


The User-Agent plays an important role in 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.
The User-Agent plays an important role in 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.
A compliant BrowserID User-Agent must implement the <tt>navigator.id</tt> object, which serves both for issuing assertions and exposing a provisioning flow to identity providers.


=== Issuing Assertions ===
=== Issuing Assertions ===


A compliant BrowserID User-Agent must implement the <tt>navigator.id</tt> object, with API calls as described here.
The User Agent MUST offer the following API call:


<tt>navigator.id.get(object options);</tt>
<tt>navigator.id.get(object options);</tt>
Line 180: Line 182:


# Establish the origin of the requesting site (including scheme and non-standard port).
# Establish the origin of the requesting site (including scheme and non-standard port).
# Check local BrowserID store for known identities that have been successfully used previously. The User Agent MAY suggest a preferred identity out of that list based on heuristics or other internal state, e.g. the email last used on that site.
# Check local BrowserID store for known identities that have been successfully used previously.
# 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.
# Present the list of known identities. The User Agent MAY suggest a preferred identity out of that list based on heuristics or other internal state, e.g. the email last used on that site.
# If no email identities are known, the User-Agent MAY assist the user in any way it sees fit. [xxx ?]
# When the user selects an Identity:
# 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.
## check that the associated certificate is still valid. If not, initiate a provisioning workflow for that Identity, then continue once it returns successfully.
# 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.
## generate an Identity Assertion using the requesting site's origin as audience and the current time. Bundle with the associated certificate to create a Backed Identity Assertion, and fire a <tt>login</tt> event on the <tt>navigator.id</tt> object with a serialization of the Backed Identity Assertion in the <tt>assertion</tt> field of the event, then terminate the login workflow.
# Execute the navigator.id.onVerifiedEmail callback and provide the newly-created Identity Assertion as an argument.
# If no Identities are known, or if the user wishes to use a new Identity, the User Agent should prompt the user for this new identity and use it to initiate a Provisioning workflow (see below). Once provisioning has completed, the User Agent SHOULD present the updated list of identities to the user.
# If, at any point, the user cancels the login process, fire a <tt>loginCancelled</tt> event on the <tt>navigator.id</tt> object and terminate the login workflow.


The User Agent MUST fire one of two events on the <tt>navigator.id</tt> object:
By the end of the process, the User Agent MUST fire one of two events on the <tt>navigator.id</tt> object:


* A <tt>loginCancelled</tt> event if the user chose not to log in.
* A <tt>loginCancelled</tt> event if the user chose not to log in.

Revision as of 23:14, 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 plays an important role in 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.

A compliant BrowserID User-Agent must implement the navigator.id object, which serves both for issuing assertions and exposing a provisioning flow to identity providers.

Issuing Assertions

The User Agent MUST offer the following API call:

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. When this happens, the User Agent SHOULD pursue the following actions:

  1. Establish the origin of the requesting site (including scheme and non-standard port).
  2. Check local BrowserID store for known identities that have been successfully used previously.
  3. Present the list of known identities. The User Agent MAY suggest a preferred identity out of that list based on heuristics or other internal state, e.g. the email last used on that site.
  4. When the user selects an Identity:
    1. check that the associated certificate is still valid. If not, initiate a provisioning workflow for that Identity, then continue once it returns successfully.
    2. generate an Identity Assertion using the requesting site's origin as audience and the current time. Bundle with the associated certificate to create a Backed Identity Assertion, and fire a login event on the navigator.id object with a serialization of the Backed Identity Assertion in the assertion field of the event, then terminate the login workflow.
  5. If no Identities are known, or if the user wishes to use a new Identity, the User Agent should prompt the user for this new identity and use it to initiate a Provisioning workflow (see below). Once provisioning has completed, the User Agent SHOULD present the updated list of identities to the user.
  6. If, at any point, the user cancels the login process, fire a loginCancelled event on the navigator.id object and terminate the login workflow.

By the end of the process, 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 User Agent 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 with parameters based on the provisioning context. The email parameter MUST be the email address which the user-agent is attempting to provision. The cert_duration_s parameter should be the requested validity duration for the certificate, which the User Agent SHOULD determine based on the security level of the session. For example, public computers should have very short certificate validity.

navigator.id.genKeyPair(object callback);

The User Agent SHOULD expect the callback to accept parameter pubkey, a serialized public-key string as per the above public-key spec.

In response to this call, the User Agent MUST generate a fresh keypair associated with the email address for this provisioning context. The secret key should be stored internally, and the callback should be invoked with the serialized public-key as sole argument.

navigator.id.registerCertificate(certificate);

The User Agent SHOULD expect the certificate to be a valid serialized certificate, as per the above spec. The User Agent SHOULD expect the trust root for this certificate to comply with the characteristics described in the "Acceptable Trust Paths" section.

The User Agent MUST associate this certificate with the email address for this provisioning context and store this association internally for later issuance of Backed Identity Assertions.

navigator.id.raiseProvisioningFailure(string reason);

The User Agent MUST interrupt this provisioning workflow and return with a failure for the given reason.

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:

  1. Create, if it has not already done so, a local data store that will persist beyond the current page view, keyed on email identity.
  2. 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.
  3. 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.
  4. Produce an asymmetric keypair compatible with the JSON Web Key specification [JWK] and store it in the local data store.
  5. Return the public key to the JavaScript runtime of the web page through the provided callback.
  6. 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?).
  7. Save the new certificate, as well as the refreshURL and errorURL arguments of the registerVerifiedEmailCertificate function.


Certificate Refresh

  1. 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.
  2. 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.
  3. 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.
  4. 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:

  1. 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.
  2. 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?)
  3. If the Identity Assertion's signature does not verify against the public-key within the last Identity Certificate, reject the assertion.
  4. 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.
  5. 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.
  6. 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

References