Services/Identity/Spec: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 25: Line 25:
== Protocol Flow ==
== Protocol Flow ==


There are two ways for the protocol to operate, on current-generation browsers and on smart clients. Current-generation browsers are supported by means of a JavaScript library which creates an identical DOM API as a smart client would have. Thus, it makes no difference to relying parties--but the legacy scenario creates a dependency on a live service.
;Setup


;Current-generation client flow
A relying party declares its ability to accept verified emails by setting the ''onVerifiedEmail'' handler:
 
A relying party includes a JavaScript library which injects new APIs into the DOM if they do not already exist (navigator.id.*). The relying party executes code like:


  navigator.id.onVerifiedEmail = function(identity_assertion) {
  navigator.id.onVerifiedEmail = function(identity_assertion) {
Line 35: Line 33:
  });
  });


And also creates a "Sign In button on their page which, when clicked by a user, invokes the ''navigator.id.getVerifiedEmail()'' method. This method will start the verified email disclosure process.
;Requesting a verified email
 
The relying party may then execute the ''getVerifiedEmail'' method, which could be the result of the user clicking a 'Sign In' button, for example. This method informs the user agent that the relying party requires a verified email before proceeding, and should therefore request one from the user as soon as possible:
 
navigator.id.getVerifiedEmail();


Behind the scenes, the JavaScript library has created a hidden iframe to the ''secondary authority'' server (using SSL). When the getVerifiedEmail method executes, it sends a PostMessage to the hidden secondary authority iframe requesting an identity assertion for the relying party.
;Receiving and verifying the ''identity assertion''


Another JavaScript library inside the secondary authority iframe is responsible for responding to these PostMessage requests, as well as for communicating with the secondary authority's server using an internal API.
Once the user agent has acquired an ''identity assertion'' (most likely after prompting the user, and requesting an assertion from a primary or secondary authority), it executes the ''onVerifiedEmail'' handler, with the ''identity assertion'' as an argument.


This inner library first ensures the user has an active session with the secondary authority itself. If it doesn't, it opens a pop-up window for the user to sign into the secondary authority, or create a new account.
The relying party may then send the ''identity assertion'' to their server, where it can be cryptographically verified, or sent to the issuer of the assertion for verification.


After the user is signed into the secondary authority, the inner library requests a list of verified email addresses from the secondary authority. It then displays a pop-up window so the user can choose which email to disclose to the relying party.
;Declaring an active session


Once the user has chosen an email, the inner library requests an identity assertion from the secondary authority, scoped to the relying party, and returns the assertion via PostMessage to the relying party.
After verifying the assertion, the relying party should consider the browser session to be active (authenticated), and would reflect that by setting the ''sessions'' property:


The JS library included by the relying party receives the identity assertion via PostMessage, and executes the navigator.id.onVerifiedEmail callback.
navigator.id.sessions = [{...}];


The relying party may then send the assertion to their own server, and either cryptographically verify the assertion (it will be signed by the secondary authority's public key), or send it to the secondary authority over SSL for on-line verification. After the assertion is verified, the relying party may consider the session with the browser it came from to be ''active'', and set a cookie in the same way it would do today after a user signs in.
Setting a session object informs the user agent that there is an active session, how long to consider it active for, and gives the user agent a method to terminate the session (if the user wishes to do so).


Client-side, the relying party may set the navigator.id.sessions array with a Session object that informs the user agent that there is an active session, how long to consider it active for, and with a method for the user agent to terminate the session (if the user wishes to do so).
;Graceful degradation


Note that the wrapper JS library won't inject the getVerifiedEmail() method if it already exists, and thus a native client could implement the same API calls natively in the browser.
Note that this API is specifically designed so it can be implemented by a browser, or injected by a script loaded from content (by the relying party). In the latter case, the script would open an iframe to a trusted domain and communicate with it via PostMessage. Such a script would not inject the API if it already existed, thus enabling graceful degradation on current-generation browsers without interfering with the ability to provide native support for this protocol. For more details, see the [[MozillaID/InternalSpec]] document.


== Identity Assertions ==
== Identity Assertions ==

Revision as of 23:44, 8 March 2011

Verified Email Protocol Specification

The verified email protocol enables a Web site to request an email address belonging to the user associated with the current browser session. The email address is delivered (after user consent) inside a cryptographically signed document called an identity assertion, which the Web site's servers can use to verify ownership of the email. Verification can also be delegated to a trusted 3rd party, allowing the Web site to be written without any specialized cryptographic code beyond SSL.

Terms

identity
An email address which identifies a user in a universally-recognizable way.
audience
The audience is the Web site to whom a verified email proof is issued. It is also called the relying party, because it relies on others to obtain this information.
relying party
see audience.
identity assertion
A cryptographically signed document which proves to a particular audience that the current browser session is associated with an identity.
primary authority
The service from whom a user acquires an email address. The primary authority may create assertions about any identity in their domain.
secondary authority
A 3rd party service trusted by a relying party to issue identity assertions in lieu of a service which has not yet deployed infrastructure to issue identity assertions on their own.

Protocol Flow

Setup

A relying party declares its ability to accept verified emails by setting the onVerifiedEmail handler:

navigator.id.onVerifiedEmail = function(identity_assertion) {
  /* XHR identity_assertion to relying party server */
});
Requesting a verified email

The relying party may then execute the getVerifiedEmail method, which could be the result of the user clicking a 'Sign In' button, for example. This method informs the user agent that the relying party requires a verified email before proceeding, and should therefore request one from the user as soon as possible:

navigator.id.getVerifiedEmail();
Receiving and verifying the identity assertion

Once the user agent has acquired an identity assertion (most likely after prompting the user, and requesting an assertion from a primary or secondary authority), it executes the onVerifiedEmail handler, with the identity assertion as an argument.

The relying party may then send the identity assertion to their server, where it can be cryptographically verified, or sent to the issuer of the assertion for verification.

Declaring an active session

After verifying the assertion, the relying party should consider the browser session to be active (authenticated), and would reflect that by setting the sessions property:

navigator.id.sessions = [{...}];

Setting a session object informs the user agent that there is an active session, how long to consider it active for, and gives the user agent a method to terminate the session (if the user wishes to do so).

Graceful degradation

Note that this API is specifically designed so it can be implemented by a browser, or injected by a script loaded from content (by the relying party). In the latter case, the script would open an iframe to a trusted domain and communicate with it via PostMessage. Such a script would not inject the API if it already existed, thus enabling graceful degradation on current-generation browsers without interfering with the ability to provide native support for this protocol. For more details, see the MozillaID/InternalSpec document.

Identity Assertions

Identity Assertions are JWT-signed JSON bundles which, after disclosure to a site, can be used to verify (via signature checking, or a pingback to the assertion's issuer) that the current session has verified a given email.

All Idenitity Assertions have in their JSON payload the following fields (all are required):

  • type: always set to "server-signed"
  • issuer: issuing authority, RP will use it to verify they trust the issuer as well as verify the IA (A domain, with a Well Known URL for validation)
    • rationale: having it be a domain defines the authority. If a site wishes to validate, they would do so using a well known address (TBD). This also prevents potential spoofing if a Authorize structure is presented (e.g. name:"Mozilla.com", url:"evilonastick.com")
  • audience: who the IA is intended for, RP will verify to make sure it's not being subject to a replay attack with an IA for another site
  • valid-until: a timestamp in the future at which point the IA will no longer be considered valid.
  • email: the email of the user

Sample Identity Assertion Object:

{
  type: "server-signed",
  issuer: "identity.mozilla.com",
  audience: "destination.com",
  valid-until: <format TBD>,
  email: "alice@site.com"
}

Relying Party JavaScript API

This API is what a relying party uses to request an identity assertion to be issued to it.

The API is constructed to also allow an identity assertion to be proactively delivered by a user agent to the relying party, for sites that (for example) allow user personalization, but do not require it.

navigator.id.onVerifiedEmail = function(status, identity_assertion) {};
Sets the callback to be run when getVerifiedEmail completes (after an Identity Assertion is given back to the page). Note that a smart client could use this to set a chrome level button
navigator.id.getVerifiedEmail();
Causes an email disclosure widget to appear. This is used by a relying party to request an identity assertion (for example, if an identity assertion is required before being able to proceed to a particular section of a site).
navigator.id.sessions = [session1, session2, ...];
Sets the current sessions at the site. This API allows the user agent to be notified of active and passive sessions, and gives it the tools to act on them (e.g., terminate a session). See the session object for more information.
Session objects

Session objects are JavaScript objects with the following properties. All are required:

  • id: email corresponding to the session
  • status: active (current active session), passive (expired session)
  • expires: time at which the browser should assume the session will expire. that is, the browser will assume an active session is still active until this time.
  • terminate: function the object should invoke to terminate this session.

Sample object:

{
  id: "alice@site.com",
  status: "active",
  expires: <format tbd>,
  terminate: function() { /* XHR to server to invalidate cookie */ }
}

Secondary Authority Verification API

Secondary authorities must implement the following API in order to verify identity assertions.

verify
  • type: POST
  • SSL: required
  • path: /1/verify
  • parameters:
    • audience: relying party
    • identity_assertion: encoded identity assertion block
  • returns:
    • *SUCCESS* if identity assertion is valid and was issued to audience
    • *INVALID* if identity assertion is invalid or does not match audience
    • *PARSE_ERROR* parameters are empty or malformed