The openid2rp module also includes a stand-alone server, as an example
+A *user* tries to authenticate to a *Relying Party (RP)*, referring to an
+OpenID *Provider (OP)* for verification. The objective is to assert
+that the user owns his *claimed identifier*. He can either type in
+that claimed identifier during login, or select a *provider
+For any identifier entered by the user, *normalization* must be
+performed. This will add an http: prefix, missing slashes,
+etc. Identity comparison should always use normalized identifiers.
+The relying party first performs *discovery*, determining whether the
+user-entered identifier is a claimed identifier or a provider
+identifier, where the provider is located, and what *op_local
+identifier* the provider may actually be able to validate. Discovery
+gives users the opportunity to switch providers without changing
+After discovery, the RP creates an *association* with the provider
+which produces an *association handle* and a *mac key* (MAC = Message
+Authenticity Code). As information is also transmitted through the
+user's browser, this assocation guarantees that the user won't be able
The application can use the following API:
Callers must check openid.response_nonce for replay attacks.
+Response Utility Functions
+.. function:: parse_nonce(nonce) -> (timestamp, ID)
+ Split a response_nonce value into a datetime.datetime timestamp,
+ and the provider nonce ID. Applications should set a reasonable
+ conservative timeout (e.g. one hour) for the transmission of a
+ nonce from the provider to the RP. Nonces older than now()-timeout
+ can be discarded as replays right away. Younger nonces should be
+ checked against the replay cache. Cache entries older than the
+ timeout can be discarded.
+.. function:: get_namespaces(response) -> dict
+ Return a dictionary of namespace : prefix mappings, to be used
+ for additional attributes.
+.. function:: get_ax(response, ns, validated) -> dict
+ Return a dictionary of attribute exchange (AX) properties,
+ in the type-url : value format.
+.. function:: get_email(response) -> str
+ Return the user's proposed email address. It first tries the simple
+ registration attribute (SREG), and then the axschema AX attribute.
+ Return None if neither is available.
+.. function:: get_username(response) -> str
+ Propose a username for the user. It may return the SREG nickname as
+ a string, the AX first/last names as a tuple, or None.
+Applications might be interested in the following response
+fields. Before trusting a specific field, they should verify that the
+* openid.mode: should be "id_res", and not "cancel"; this is checked
+* openid.claimed_id: Claimed identifier as returned from the
+ provider. If the original user-supplied identifier entered by the
+ user was an OP identifier, then this is the value identifying the
+ user. If it was a claimed identifier, then the provider is generally
+ not able to verify the claim for this identifier. The RP should
+ create a separate session for each such identifier, and verify that
+ the session is associated with the same identifier as returned in
+* openid.identity: OP-local identifier as returned from the
+ provider. This shouldn't be used for identification of the user.
+* openid.response_nonce: Nonce to prevent replay attacks. Applications
+ should establish a replay cache, detecting when the same nonce is
+ provided twice by the user's browser.
+* openid.signed: list of signed fields; converted into a Python list
+* openid.sreg.*: simple registration (SREG) properties returned by the
+ OP. This library requests as required parameters nickname and email,
+ and no optional parameters. Possible keys are:
+* AX attributes, as processed by
+ get_ax. http://www.axschema.org/types/ is a registry for attribute types.