Proposed Specification for New Consumer-Server Commnunications

Nathan D. Bowen nbowen+yadis at
Wed Jun 8 14:37:40 PDT 2005

The old communication between the server and consumer could be described as:

Request: The Consumer requests a DSA public key from the Server by 
adding the GET parameter openid.mode of value getpubkey

Response: The Server returns the DSA public key in PEM format.

The new communication, could be described more as "establishing an 
association" than as "getting a key", and the communication is 
necessarily more complex.

It should be easier to discuss these things if we all share a vocabulary 
for them.

I'll take a stab here:

Establishing Consumer-Server Associations

Before a Consumer can redirect UserAgents to retrieve identification 
tokens from a remote Server, the Consumer must have already established 
an association with that Server.

The Consumer-to-Server association:
    1) provides the Server with a configuration to use when generating 
identification tokens for the Consumer over a specific timespan.
    2) provides the Consumer with a handle by which to reference the 
association in future requests.


A Consumer requests an association with a Server by initiating an HTTP 
request to the Server, with the details of the requested association 
specified the GET parameters.

The Consumer indicates that it is requesting an association with the 
Server by providing:

    Parameter: openid.mode
    Value: 'associate'

The Consumer specifies the method by which the Server should produce 
identification tokens intended for the Consumer. Currently, the only 
supported identification token format is "HMAC-SHA1", so including this 
parameter is optional.

    Parameter: openid.id_token_format
    Value: 'HMAC-SHA1'

The other parameters of an association request are dependent on the 
chosen format.

* For HMAC-SHA1:

HMAC-SHA1 will require a secret to be shared between the Consumer and 
Server for the duration of the association. A Diffie-Hellman key 
exchange protects this secret in transit. The consumer provides the 
shared Diffie-Hellman parameters along with its own Diffie-Hellman 
public integer.

    Parameter: openid.dh_modulus
    Value: BASE64(BTWOC(modulus))
    Parameter: openid.dh_generator
    Value: BASE64(BTWOC(generator))
    Parameter: openid.dh_consumer_public
    Value: BASE64(BTWOC(consumer's public value))


The Server configures an association with the Consumer using the 
requested configuration parameters, communicates any parameters the 
Consumer will need for the chosen identification token format, and 
supplies a handle by which the association can be identified in the 
future. The parameters are supplied in the response one-per-line, in the 

name: value

Regardless of the specifics of the association, the Consumer needs to 
know the handle by which to refer to this association in the future, as 
well as the timespan for which the association will be effective.

    Parameter: openid.association_handle
    Value: handle
    Parameter: openid.association_issuetime
    Value: UTC date and time of issue
    Parameter: openid.association_expires
    Value: UTC date and time this association will expire
    Parameter: openid.association_replacetime
    Value: UTC date and time on which the server
        recommends initiating a new association

Since the consumer may not have specified a preference for the 
identification token format, the server states which format this 
association will use. Again, only HMAC-SHA1 is currently supported.

    Parameter: openid.id_token_format
    Value: 'HMAC-SHA1'
The other parameters of an association response are dependent on the 
chosen format.

* For HMAC-SHA1:

The Server needs to communicate its Diffie-Hellman public integer 
(generated with the Consumer-provided parameters).

    Parameter: openid.dh_server_public
    Value: BASE64(BTWOC(server's public value))

The Consumer needs to know what shared secret will be used for identity 
tokens created under this association.

    Parameter: openid.encrypted_hmac_secret
    Value: base64(SHA1(BTWOC(DH_secret_integer)) XOR hmac_secret)

Generaton of the hmac_secret is left up to the server implementation. 
Some methods that are in use include:

    1) Use the DH private integer directly -- use 
SHA1(BTWOC(DH_secret_integer)) as the hmac_secret (producing an 
encrypted_hmac_secret of 0)

    2) Use a "get_secret" method that can calculate secrets from 
handles, e.g., LiveJournal's LJ::get_secret, which allows a secret to be 
retrieved by a handle without requiring all known secrets to be 
explicitly stored.

More information about the yadis mailing list