Services/Identity/Spec: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(Deprecate; point to BrowserID)
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{| class="fullwidth-table"
|-
| '''Note: The Verified Email Protocol has been deprecated. Please check the [[Identity/BrowserID|BrowserID]] protocol.'''
|}<br>
= Verified Email Protocol Specification =
= Verified Email Protocol Specification =


Line 12: Line 17:


;relying party
;relying party
:see audience.
:see audience.  The relying party is the server that receives an identity assertion and makes a validity determination about it.


;identity assertion
;identity assertion
:A cryptographically signed document which proves to a particular audience that the current browser session is associated with an identity.
:A cryptographically-signed document which proves to a particular audience that the current browser session is associated with an identity.


;primary authority
;primary authority
Line 22: Line 27:
;secondary authority
;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.
: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.
;JWT
:JSON Web Token, a protocol for cryptographically-signed JSON; see [[MozillaID/JWT]]
== 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/HTML_Client]] document.
== Identity Assertions ==
Identity Assertions are [[MozillaID/JWT|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 ==
== Relying Party JavaScript API ==
Line 64: Line 129:


;verify
;verify
type: POST
* type: POST
SSL: required
* SSL: required
path: /1/verify
* path: /1/verify
 
* parameters:
parameters:
** audience: relying party
* audience: relying party
** identity_assertion: A JWT encoding the identity assertion
* identity_assertion: encoded identity assertion block
* returns:
 
** *SUCCESS* if identity assertion is valid and was issued to audience
returns:
** *INVALID* if identity assertion is invalid or does not match audience
* *SUCCESS* if identity assertion is valid and was issued to audience
** *PARSE_ERROR* parameters are empty or malformed
* *INVALID* if identity assertion is invalid or does not match audience
* *PARSE_ERROR* parameters are empty or malformed
 
== Server ==
 
Pages ID service must implement:
 
* Provide a login page to the user sets a cookie which allows the page to make an XHR request to return an Identity Assertion for that user.
* Provide account creation page(s) to create a new account.
* Provide an account recovery page to send a verification token via email
* Provide disclosure dialog page
 
=== ID Server Cookies: ===
ID Server cookies are used by the ''service.js'' (see Sec. 41.5.2) script inside of the server provided frame to allow for continuous end-customer service. These cookies are permanent and contains and interal "freshness date" for when to become "passive"
 
==== ID Active Session:  ====
User has actively logged in to id.moz
 
provides the ability for JS Library contained in secured iframe to request an Identity Assertion
 
'''TTL:''' (TBD)
 
 
==== ID Passive Session:  ====
(Active cookie freshness expired. Need to re-auth)
 
Active Session has expired
 
Requires user action before setting to Acitve Session
 
'''TTL''': (TBD)
 
=== Server API Endpoints  ===
==== General ====
All API endpoints are SSL only and require a POST. All calls are made XMLHTTPRequest POST and return JSON objects unless otherwise specified.
 
Unless a callback is specified, the request will use standard HTTP status codes to indicate errors.
 
JSON responses (unless otherwise specified) follow the format of:
 
{"success":True|False,
  "error": {  ''// Only present if "success" is false''
    "code": ''Numeric Code (reflecting the HTTP Status code)'',
    "reason": ''Human Readable error reason'' },
  ''Data''}
 
"error" only exists if there was an error with the transaction.
 
"Data" is short-hand for the function specific data elements returned. See individual functions for return results.
 
==== Service APIs ====
The following API calls are made by the ''service.js ''(see Sec. 41.5.2) code inside the trusted iframe back to the ID Server. The API calls shall check the origin of the requests to ensure that they are from the mozilla.com served iframe. See Status (Sec. 1.8) for a description of the return status types.
 
===== https://servername/1/logged_in =====
Is the user logged into Mozilla ID service (Is the Active_Session cookie valid)
 
''Parameters:''
 
none.
 
''Returns'':
 
returns *SUCCESS*
 
''Errors'':
 
If there is no Active Session, returns *LOGIN ERROR*
 
===== https://server/1/get_default_email =====
''Parameters'':
 
audience: RP
 
''Returns'':
 
Return the default email associated with this RP
 
''Errors'':
 
If there is no active session, fails with *LOGIN ERROR*
 
===== https://servername/1/get_emails =====
''Parameters'':
 
audience: RP
 
''Returns'':
 
(TBD) returns a JSON block of candidate email addresses indicating which email may have been previously used with this site and which email is "preferred"
 
''Errors'':
 
If there is no active session, fails with *LOGIN ERROR*
 
===== https://servername/1/get_identity_assertion =====
This is the Identity Assertion Request (IAR). It returns an Identity Assertion for the given audience and email.
 
''Parameters'':
 
audience: requesting site (to come from trusted iframe)
 
email: user email address to use for this assertion.
 
''Returns'':ver
 
Returns Identity Assertion. (as decribed in Sec 1.3)
 
''Errors'':
 
If there is no Active Session, the IAR will fail with a '''<nowiki>*LOGIN ERROR*</nowiki>''', and the JS Library should prompt for login.
 
 
===== https://server/1/remove_association =====
removes the "automatic" flag, requiring user to confirm access to the site, and specify the preferred email (if more than one is available)
 
''Parameter'':
 
audience: RP
 
''Returns'':
 
<nowiki>*</nowiki>'''SUCCESS*, FAILURE*'''
 
''Errors'':
 
If there is no active session, fails with *LOGIN ERROR*
 
== Identity Assertions ==
Identity Assertions (IAs) are JWT-signed JSON bundles (see Sec. 1.7) which, after disclosure to a site, can be used to verify (via signature checking, or a pingback to the IA issuer) that the current session has verified a given email.
 
=== Identity Assertion JSON Content ===
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
 
 
== Protocol Flow ==
A web page (destination.com) includes a JavaScript library which injects a new method (navigator.id.getVerifiedEmail). When the destination.com executes that method (and gives it a callback, since it's asynchronous), the method will open a hidden iframe to the Identity Server at a well-known location (over SSL) which implements a API over PostMessage.
 
 
Since the trusted iframe also implements a JS library, we distinguish between the two by calling the one on destination.com the wrapper JS library. The one inside the trusted iframe is called the service JS library.
 
 
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 wrapper API calls natively in the browser (i.e., implement the service library natively in the client).
 
 
=== Service API ===
<nowiki>*** PostMessage API ***</nowiki>
 
 
see: jschannel
 
...
 
- how does it open a popup? does it need to talk to the wrapper to request a popup?
 
- how does it report failure to the wrapper API?
 
* how does it communicate with a popup?
*
 
1. page calls wrapper::getVerifiedEmail(cb)
 
2. wrapper::getVerifedEmail() calls service js to determine the current user's email
 
if customer
 
3. service js determines if user has active session
 
if no, then get an active session by use of a pop-up
 
(if service js fails to establish an active session, then return a failure)
 
4. service js determines if there is a default email already set to be disclosed to this RP
 
if no, then
 
make an API call to the ID server to fetch the list of possible email addresses to use, and show a pop-up to let the user decide if/what to disclose to the RP
 
if user cancels, return a failure (the same failure!)
 
5. once the service js has established the desired email to be disclosed, make an IAR (identity assertion request) to the ID server to obtain an IA that will be returned to the page
 
6. the wrapper gets back the IA from the service JS and calls the callback with status and IA.
 
 
== Identity Assertion Request (IAR) ==
An IAR is the call the JS library does, from a trusted and authenticated iframe, to acquire an Identity Assertion (IA) for a given email address and requesting site (RP). The JS library must ensure the user has consented to the disclosure of information to the RP before making this call. See below for the IA format.
 
 
Note that:
 
* IAs are returned only if authorized by cookie (in a trusted iframe).
* IAs should be requested by the JS library only after it has determined that the user wishes to disclose their email to the site.
 
== JSON Web Token (JWT) format ==
JWT is a simple way to encode signed JSON blobs. It consists of 3 sections:
 
 
* Header
* Payload
* Signature<br/>
 
 
All three sections are serialized and base64-encoded, and separated by dots. See the spec for more information:
 
http://self-issued.info/docs/draft-jones-json-web-token.htm
 
 
JSON Package is signed by converting the JSON Package to a base64 string, and then run through HMAC SHA1 using a private key stored on the server.
 
 
The public key may be published in a well known location for remote clients to verify the Package independently. (if we use asymmetric keys)
 
 
Provide a validation page for info.
 
 
== States: ==
Samples of the following return status messages.
 
SUCCESS
 
{"success": True,
''Data...''}
 
 
LOGIN ERROR
 
{"success": False,
  "error": {"code": 401,
    "reason": ''TBD''}}
 
PARSE_ERROR
 
{"success": False,
  "error": {"code": 400,
    "reason": TBD}}
 
INVALID (server to server)
 
{"success": False,
    "error": { "code": 403,
    "reason":""}}

Latest revision as of 19:20, 3 April 2012

Note: The Verified Email Protocol has been deprecated. Please check the BrowserID protocol.


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. The relying party is the server that receives an identity assertion and makes a validity determination about it.
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.
JWT
JSON Web Token, a protocol for cryptographically-signed JSON; see MozillaID/JWT

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/HTML_Client 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: A JWT encoding the identity assertion
  • 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