summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-11-22 07:27:31 -0800
committerAndrew <andrewarnott@gmail.com>2008-11-22 07:27:31 -0800
commite9379729042a5ca7312df00d81f42370a83df0d1 (patch)
tree0d239a61f133ba126baf03fb285432bd5abe87f6
parent70d616e4153a79fa0dcddd6db5aff57c6627ed2f (diff)
downloadDotNetOpenAuth-e9379729042a5ca7312df00d81f42370a83df0d1.zip
DotNetOpenAuth-e9379729042a5ca7312df00d81f42370a83df0d1.tar.gz
DotNetOpenAuth-e9379729042a5ca7312df00d81f42370a83df0d1.tar.bz2
Added the CheckIdRequest message, Realm, and the OpenID spec documents.
-rw-r--r--doc/specs/openid-attribute-exchange-1_0.html1157
-rw-r--r--doc/specs/openid-authentication-1_1.html1593
-rw-r--r--doc/specs/openid-authentication-2_0.html4172
-rw-r--r--doc/specs/openid-provider-authentication-policy-extension-1_0-02.html1137
-rw-r--r--doc/specs/openid-simple-registration-extension-1_0.html389
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs68
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs105
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RealmTests.cs224
-rw-r--r--src/DotNetOpenAuth.sln9
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj2
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs154
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs27
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx9
-rw-r--r--src/DotNetOpenAuth/OpenId/Realm.cs339
-rw-r--r--src/DotNetOpenAuth/UriUtil.cs25
16 files changed, 9410 insertions, 2 deletions
diff --git a/doc/specs/openid-attribute-exchange-1_0.html b/doc/specs/openid-attribute-exchange-1_0.html
new file mode 100644
index 0000000..5df3ea9
--- /dev/null
+++ b/doc/specs/openid-attribute-exchange-1_0.html
@@ -0,0 +1,1157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en"><head><title>Final: OpenID Attribute Exchange 1.0 - Final</title>
+
+<meta http-equiv="Expires" content="Wed, 05 Dec 2007 17:48:00 +0000">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="description" content="OpenID Attribute Exchange 1.0 - Final">
+<meta name="generator" content="xml2rfc v1.33pre5 (http://xml.resource.org/)">
+<style type="text/css"><!--
+ body {
+ font-family: verdana, charcoal, helvetica, arial, sans-serif;
+ font-size: small; color: #000; background-color: #FFF;
+ margin: 2em;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
+ font-weight: bold; font-style: normal;
+ }
+ h1 { color: #900; background-color: transparent; text-align: right; }
+ h3 { color: #333; background-color: transparent; }
+
+ td.RFCbug {
+ font-size: x-small; text-decoration: none;
+ width: 30px; height: 30px; padding-top: 2px;
+ text-align: justify; vertical-align: middle;
+ background-color: #000;
+ }
+ td.RFCbug span.RFC {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: bold; color: #666;
+ }
+ td.RFCbug span.hotText {
+ font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: normal; text-align: center; color: #FFF;
+ }
+
+ table.TOCbug { width: 30px; height: 15px; }
+ td.TOCbug {
+ text-align: center; width: 30px; height: 15px;
+ color: #FFF; background-color: #900;
+ }
+ td.TOCbug a {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
+ font-weight: bold; font-size: x-small; text-decoration: none;
+ color: #FFF; background-color: transparent;
+ }
+
+ td.header {
+ font-family: arial, helvetica, sans-serif; font-size: x-small;
+ vertical-align: top; width: 33%;
+ color: #FFF; background-color: #666;
+ }
+ td.author { font-weight: bold; font-size: x-small; margin-left: 4em; }
+ td.author-text { font-size: x-small; }
+
+ /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
+ a.info {
+ /* This is the key. */
+ position: relative;
+ z-index: 24;
+ text-decoration: none;
+ }
+ a.info:hover {
+ z-index: 25;
+ color: #FFF; background-color: #900;
+ }
+ a.info span { display: none; }
+ a.info:hover span.info {
+ /* The span will display just on :hover state. */
+ display: block;
+ position: absolute;
+ font-size: smaller;
+ top: 2em; left: -5em; width: 15em;
+ padding: 2px; border: 1px solid #333;
+ color: #900; background-color: #EEE;
+ text-align: left;
+ }
+
+ a { font-weight: bold; }
+ a:link { color: #900; background-color: transparent; }
+ a:visited { color: #633; background-color: transparent; }
+ a:active { color: #633; background-color: transparent; }
+
+ p { margin-left: 2em; margin-right: 2em; }
+ p.copyright { font-size: x-small; }
+ p.toc { font-size: small; font-weight: bold; margin-left: 3em; }
+ table.toc { margin: 0 0 0 3em; padding: 0; border: 0; vertical-align: text-top; }
+ td.toc { font-size: small; font-weight: bold; vertical-align: text-top; }
+
+ ol.text { margin-left: 2em; margin-right: 2em; }
+ ul.text { margin-left: 2em; margin-right: 2em; }
+ li { margin-left: 3em; }
+
+ /* RFC-2629 <spanx>s and <artwork>s. */
+ em { font-style: italic; }
+ strong { font-weight: bold; }
+ dfn { font-weight: bold; font-style: normal; }
+ cite { font-weight: normal; font-style: normal; }
+ tt { color: #036; }
+ tt, pre, pre dfn, pre em, pre cite, pre span {
+ font-family: "Courier New", Courier, monospace; font-size: small;
+ }
+ pre {
+ text-align: left; padding: 4px;
+ color: #000; background-color: #CCC;
+ }
+ pre dfn { color: #900; }
+ pre em { color: #66F; background-color: #FFC; font-weight: normal; }
+ pre .key { color: #33C; font-weight: bold; }
+ pre .id { color: #900; }
+ pre .str { color: #000; background-color: #CFF; }
+ pre .val { color: #066; }
+ pre .rep { color: #909; }
+ pre .oth { color: #000; background-color: #FCF; }
+ pre .err { background-color: #FCC; }
+
+ /* RFC-2629 <texttable>s. */
+ table.all, table.full, table.headers, table.none {
+ font-size: small; text-align: center; border-width: 2px;
+ vertical-align: top; border-collapse: collapse;
+ }
+ table.all, table.full { border-style: solid; border-color: black; }
+ table.headers, table.none { border-style: none; }
+ th {
+ font-weight: bold; border-color: black;
+ border-width: 2px 2px 3px 2px;
+ }
+ table.all th, table.full th { border-style: solid; }
+ table.headers th { border-style: none none solid none; }
+ table.none th { border-style: none; }
+ table.all td {
+ border-style: solid; border-color: #333;
+ border-width: 1px 2px;
+ }
+ table.full td, table.headers td, table.none td { border-style: none; }
+
+ hr { height: 1px; }
+ hr.insert {
+ width: 80%; border-style: none; border-width: 0;
+ color: #CCC; background-color: #CCC;
+ }
+--></style></head><body>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<table summary="layout" border="0" cellpadding="0" cellspacing="0" width="66%"><tbody><tr><td><table summary="layout" border="0" cellpadding="2" cellspacing="1" width="100%">
+<tbody><tr><td class="header">Final</td><td class="header">D. Hardt</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">J. Bufu</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">Sxip Identity</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">J. Hoyt</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">JanRain</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">December 5, 2007</td></tr>
+</tbody></table></td></tr></tbody></table>
+<h1><br>OpenID Attribute Exchange 1.0 - Final</h1>
+
+<h3>Abstract</h3>
+
+<p>
+ OpenID Attribute Exchange is an OpenID service extension for
+ exchanging identity information between endpoints. Messages for
+ retrieval and storage of identity information are provided.
+
+</p><a name="toc"></a><br><hr>
+<h3>Table of Contents</h3>
+<p class="toc">
+<a href="#anchor1">1.</a>&nbsp;
+Terminology<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor2">1.1.</a>&nbsp;
+Definitions and Conventions<br>
+<a href="#anchor3">2.</a>&nbsp;
+Overview<br>
+<a href="#anchor4">3.</a>&nbsp;
+Information Model<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#identifier-definition">3.1.</a>&nbsp;
+Subject Identifier<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#attribute-name-definition">3.2.</a>&nbsp;
+Attribute Type Identifier<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#attribute-value-definition">3.3.</a>&nbsp;
+Attribute Value<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#attribute-specific-encodings">3.3.1.</a>&nbsp;
+Attribute-Specific Encodings<br>
+<a href="#anchor5">4.</a>&nbsp;
+Discovery<br>
+<a href="#fetch">5.</a>&nbsp;
+Fetch Message<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#fetch_request">5.1.</a>&nbsp;
+Fetch Request Format<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#fetch_response">5.2.</a>&nbsp;
+Fetch Response Format<br>
+<a href="#store">6.</a>&nbsp;
+Store Message<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#store_request">6.1.</a>&nbsp;
+Store Request Format<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#store_response">6.2.</a>&nbsp;
+Store Response Format<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor6">6.2.1.</a>&nbsp;
+Storage Success<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor7">6.2.2.</a>&nbsp;
+Storage Failure<br>
+<a href="#anchor8">7.</a>&nbsp;
+Security Considerations<br>
+<a href="#anchor9">8.</a>&nbsp;
+Acknowledgements<br>
+<a href="#rfc.references1">9.</a>&nbsp;
+References<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#rfc.references1">9.1.</a>&nbsp;
+Normative References<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#rfc.references2">9.2.</a>&nbsp;
+Non-normative References<br>
+<a href="#rfc.authors">§</a>&nbsp;
+Authors' Addresses<br>
+</p>
+<br clear="all">
+
+<a name="anchor1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1"></a><h3>1.&nbsp;
+Terminology</h3>
+
+<p>
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+ NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
+ "OPTIONAL" in this document are to be interpreted as described
+ in <a class="info" href="#RFC2119">[RFC2119]<span> (</span><span class="info">Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels,” March&nbsp;1997.</span><span>)</span></a>.
+
+</p>
+<a name="anchor2"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1.1"></a><h3>1.1.&nbsp;
+Definitions and Conventions</h3>
+
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>User:</dt>
+<dd>
+ Also referred to as "End User" or "Subject".
+ A person with a digital identity who participates in
+ OpenID-based identity information exchanges using their
+ client software, typically a web browser.
+
+</dd>
+<dt>Identity Data:</dt>
+<dd>
+ A property of a digital identity in which the Property
+ Name and Property Value are represented as a name-value
+ pair.
+
+</dd>
+<dt>Attribute</dt>
+<dd>
+ The base of the information model used to describe the
+ Identity Data, for the purpose of exchanging it.
+
+</dd>
+<dt>Persona:</dt>
+<dd>
+ A subset of the user's identity data. A user can have
+ multiple personas as part of their identity. For example,
+ a user might have a work persona and a home persona.
+
+</dd>
+<dt>OpenID Provider:</dt>
+<dd>
+ Also called "OP" or "Server". An OpenID Authentication
+ server on which a Relying Party relies for an assertion
+ that the end user controls an Identifier.
+
+</dd>
+<dt>Relying Party:</dt>
+<dd>
+ Also called "RP" or "Consumer". A Web application that
+ wants proof that the end user controls an Identifier,
+ and requests identity data associated with the end user.
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+ All OpenID Attribute Exchange messages MUST contain the
+ following extension namespace declaration, as specified
+ in the Extensions section of OpenID-Authentication-2.0:
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.&lt;extension_alias&gt;=http://openid.net/srv/ax/1.0
+
+</pre></div>
+<p>
+ The actual extension namespace alias should be determined
+ on a per-message basis by the party composing the messages,
+ in such a manner as to avoid conflicts between multiple
+ extensions. For the purposes of this document, the extension
+ namespace alias for the attribute exchange service will be "ax".
+
+</p>
+<a name="anchor3"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.2"></a><h3>2.&nbsp;
+Overview</h3>
+
+<p>
+ The attribute exchange service extension is identified by the
+ URI "http://openid.net/srv/ax/1.0". This URI MUST be specified in the extension
+ namespace declaration.
+
+</p>
+<p>
+ An attribute is a unit of personal identity information that
+ is identified by a unique URI. It may refer to any kind of
+ information. A reference example of defining attribute types
+ is provided by <a class="info" href="#OpenID.axschema">[OpenID.axschema]<span> (</span><span class="info">Hardt, D., “Schema for OpenID Attribute Exchange,” May&nbsp;2007.</span><span>)</span></a>.
+
+</p>
+<p>
+ This service extension defines two message types for
+ transferring attributes: fetch (see <a class="info" href="#fetch">Section&nbsp;5<span> (</span><span class="info">Fetch Message</span><span>)</span></a>)
+ and store (see <a class="info" href="#store">Section&nbsp;6<span> (</span><span class="info">Store Message</span><span>)</span></a>). Fetch retrieves
+ attribute information from an OpenID Provider, while store
+ saves or updates attribute information on the OpenID
+ Provider. Both messages originate from the Relying Party
+ and are passed to the OpenID Provider via the user agent
+ as per the OpenID Authentication protocol specification.
+
+</p>
+<p>
+ The request parameters detailed here MUST be sent using the
+ <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a> extension mechanism.
+
+</p>
+<a name="anchor4"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3"></a><h3>3.&nbsp;
+Information Model</h3>
+
+<p>
+ The OpenID Attribute Exchange service extension provides a
+ mechanism for moving identity information between sites, as
+ such its information model is simple:
+ </p>
+<blockquote class="text">
+<p>An attribute is associated with a Subject Identifier
+</p>
+<p>An attribute has a type identifier and a value
+</p>
+<p>An attribute type identifier is a URI
+</p>
+<p>An attribute value can be any kind of data.
+</p>
+</blockquote><p>
+
+</p>
+<a name="identifier-definition"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.1"></a><h3>3.1.&nbsp;
+Subject Identifier</h3>
+
+<p>
+ An identifier for a set of attributes. It MUST be a URI. The
+ subject identifier corresponds to the end-user identifier in
+ the authentication portion of the messages. In other words,
+ the subject of the identity attributes in the attribute
+ exchange part of the message is the same as the end-user in
+ the authentication part. The subject identifier is not
+ included in the attribute exchange.
+
+</p>
+<a name="attribute-name-definition"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.2"></a><h3>3.2.&nbsp;
+Attribute Type Identifier</h3>
+
+<p>
+ An attribute type identifier MUST be a URI, which is used
+ for referring to property values.
+
+</p>
+<p>
+ If an attribute type identifier URI can be resolved then it
+ MAY be dereferenced to retrieve a description of the
+ property. OpenID Providers can use the metadata obtained
+ through dereferencing new or unknown attribute types to
+ dynamically assist the user in providing the attribute.
+
+</p>
+<p>
+ This provides for flexibility and extensibility. Flexibility
+ in that both URNs and URLs can be used to refer to property
+ values. Extensibility allows any individual site, or
+ consortium of sites, to define their own attribute types
+ with agreements on the syntax and semantics of their
+ associated attribute values.
+
+</p>
+<p>
+ <a class="info" href="#OpenID.axschema">[OpenID.axschema]<span> (</span><span class="info">Hardt, D., “Schema for OpenID Attribute Exchange,” May&nbsp;2007.</span><span>)</span></a> outlines an example method
+ of defining new attribute type URIs, and also provides a set
+ of attribute types with their associated metadata schema and
+ data formats.
+
+</p>
+<a name="attribute-value-definition"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.3"></a><h3>3.3.&nbsp;
+Attribute Value</h3>
+
+<p>
+ A attribute value MUST be a <a class="info" href="#RFC3629">UTF-8<span> (</span><span class="info">Yergeau, F., “UTF-8, a transformation format of ISO 10646,” November&nbsp;2003.</span><span>)</span></a> [RFC3629]
+ string. In order to comply with the data formats defined by
+ the underlying <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>
+ protocol, attribute values MUST NOT contain newlines
+ (UCS codepoint 10, "\n").
+
+</p>
+<p>
+ OpenID Attribute Exchange can be used to transfer any kind
+ of data. If the data contains newlines, is not a UTF-8 string
+ or it is so desired by the parties transferring the data,
+ the data MUST be encoded to a UTF-8 string without newlines.
+
+</p>
+<a name="attribute-specific-encodings"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.3.1"></a><h3>3.3.1.&nbsp;
+Attribute-Specific Encodings</h3>
+
+<p>
+ Attribute-specific encodings can be defined using the
+ attribute metadata descriptions and may be applied by
+ the protocol layer above OpenID Attribute Exchange.
+
+</p>
+<p>
+ Optionally, attribute-specific encodings may use language
+ tags <a class="info" href="#OpenID.value-lang-1.0">[OpenID.value‑lang‑1.0]<span> (</span><span class="info">Wahl, M., “Language Tags for OpenID Values,” April&nbsp;2007.</span><span>)</span></a> for
+ localization.
+
+</p>
+<a name="anchor5"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4"></a><h3>4.&nbsp;
+Discovery</h3>
+
+<p>
+ Discovery of the attribute exchange service extension is
+ achieved via the mechanism described in <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>. The attribute exchange
+ namespace "http://openid.net/srv/ax/1.0" SHOULD be listed as an &lt;xrd:Type&gt;
+ child element of the &lt;xrd:Service&gt; element in the XRDS
+ discovery document.
+
+</p>
+<a name="fetch"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5"></a><h3>5.&nbsp;
+Fetch Message</h3>
+
+<p>
+ The fetch message is used to retrieve personal identity
+ attributes from an OpenID Provider.
+
+</p>
+<a name="fetch_request"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1"></a><h3>5.1.&nbsp;
+Fetch Request Format</h3>
+
+<p>
+ With the exception of "openid.ax.mode", all of the following
+ request fields are OPTIONAL, though at least one of
+ "openid.ax.required" or "openid.ax.if_available" MUST be
+ specified in the request, and any attribute alias present in a
+ "openid.ax.required" or "openid.ax.if_available" parameter MUST
+ have an associated "openid.ax.type.&lt;alias&gt;" parameter.
+ The supported length for attribute aliases MUST be at least
+ 32 characters.
+
+</p>
+<p>
+ Multiple attribute aliases in the "openid.ax.required" and
+ "openid.ax.if_available" directives are separated with a
+ comma, ",".
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.ax.mode</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ REQUIRED. Value: "fetch_request".
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.type.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The value of this parameter specifies the type identifier
+ URI of a requested attribute. The &lt;alias&gt; will
+ further be used to identify the attribute being exchanged.
+
+</p>
+<p>
+ Attribute aliases MUST NOT contain newline and colon characters,
+ as specified in the Data Formats / Protocol Messages section of
+ <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>; they also MUST
+ NOT contain commas (",") and periods (".").
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.required</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Value: an attribute alias, or a list of aliases
+ corresponding to the URIs defined by
+ "openid.ax.type.&lt;alias&gt;" parameters. Multiple
+ attribute aliases are separated with a comma, ",".
+
+</p>
+<p>
+ By requesting attributes using this field, a hint is sent
+ to the OP about the RP's requirements for offering certain
+ functionality and should be used by the OP to help the
+ user decide what attributes to release. RP's requirements
+ should not be enforced by the OP.
+
+</p>
+<p>
+ The RP should offer, out of band of attribute exchange,
+ an alternate method of collecting the attributes it needs,
+ if they weren't obtained via attribute exchange.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.if_available</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Value: an attribute alias, or a list of aliases
+ corresponding to the URIs defined by
+ "openid.ax.type.&lt;alias&gt;" parameters. Multiple
+ attribute aliases are separated with a comma, ",".
+
+</p>
+<p>
+ Attributes requested using this field are deemed
+ optional by the RP; the RP should be able to complete
+ the interaction with the user even if values are not
+ provided by the OP for the optional attributes.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.count.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The number of values for the specified attribute
+ alias the Relying Party wishes to receive from the OpenID
+ Provider. If present, the value MUST be greater than zero,
+ or the special value "unlimited" which signifies that the
+ RP is requesting as many values as the OP has for the
+ attribute. If absent, exactly one value is requested.
+
+</p>
+<p>
+ OpenID Providers MAY return less than or the exact
+ number of values speficied by this field for the
+ associated attribute, but MUST NOT return more than
+ the number of requested values for the attribute.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.update_url</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ If present, the OpenID Provider may re-post the fetch
+ response message to the specified URL at some time
+ after the initial response has been sent, using a
+ OpenID Authentication Positive Assertion. If the
+ OpenID Provider supports this feature it MUST return
+ the parameter as part of the fetch response message.
+ If it does not support this feature it may legally
+ ignore this parameter.
+
+</p>
+<p>
+ The value of the "openid.ax.update_url" field MUST
+ be used as value for "openid.return_to" field of the
+ underlying OpenID Authentication Positive Assertion
+ of the fetch response update.
+
+</p>
+<p>
+ The "openid.ax.update_url" value MUST also match the
+ realm specified in the underlying OpenID message of the
+ fetch request, if a "openid.realm" field is present.
+ The matching rules are the ones specified in the
+ "Realms" section of the OpenID Authentication protocol.
+
+</p>
+<p>
+ This "unsolicited" response message would be
+ generated in response to an attribute information
+ update, and would contain the updated data. The OP
+ should obtain the user's consent for resending the
+ updated data to the RPs, as with any OpenID Positive
+ Assertion.
+
+</p>
+<p>
+ The relying party may include transaction data encoded
+ in the URL such that it contains enough information to
+ match the attribute information to the identity subject.
+ Additional information may be encoded in the URL by the
+ relying party as necessary.
+
+</p>
+<p>
+ If an RP wishes to receive no further updates for an
+ attribute, it MAY return the HTTP 404 response code to
+ the corresponding "update_url". OPs MAY decide to
+ stop sending updates after encountering 404 response
+ codes.
+
+</p>
+</blockquote>
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+ This example requests the required full name and gender
+ information, and the optional favourite dog and movie
+ information. The Relying Party is interested in up to three
+ favorite movies associated with the subject identifier.
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.ax=http://openid.net/srv/ax/1.0
+openid.ax.mode=fetch_request
+openid.ax.type.fname=http://example.com/schema/fullname
+openid.ax.type.gender=http://example.com/schema/gender
+openid.ax.type.fav_dog=http://example.com/schema/favourite_dog
+openid.ax.type.fav_movie=http://example.com/schema/favourite_movie
+openid.ax.count.fav_movie=3
+openid.ax.required=fname,gender
+openid.ax.if_available=fav_dog,fav_movie
+openid.ax.update_url=http://idconsumer.com/update?transaction_id=a6b5c41
+
+</pre></div>
+<a name="fetch_response"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2"></a><h3>5.2.&nbsp;
+Fetch Response Format</h3>
+
+<p>
+ The fetch response message supplies the information
+ requested in the fetch request. Each attribute is supplied
+ with the assigned alias prefixed by "openid.ax.value." as the
+ lvalue and the attribute value as the rvalue. Attribute
+ types are also returned in the "openid.ax.type.&lt;alias&gt;"
+ parameters. The supported length for attribute aliases MUST
+ be at least 32 characters.
+
+</p>
+<p>
+ With the exception of "openid.ax.mode", all of the following
+ request fields are OPTIONAL, though any attribute value
+ present in a "openid.ax.value.&lt;alias&gt;" parameter MUST
+ have an associated "openid.ax.type.&lt;alias&gt;" parameter.
+
+</p>
+<p>
+ If a value was not supplied or available from the user,
+ the associated "openid.ax.value.&lt;alias&gt;" field
+ SHOULD NOT be included by the OP in the fetch response.
+ An "openid.ax.count.&lt;alias&gt;" with a value of "0"
+ together with its corresponding "openid.ax.type.&lt;alias&gt;"
+ field MAY be included to explicitly state that no values
+ are provided for an attribute.
+
+</p>
+<p>
+ Validation of the received data should be performed out of band
+ of attribute exchange by the RP.
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.ax.mode</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ REQUIRED. Value: "fetch_response".
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.type.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The value of this parameter specifies the type identifier
+ URI for an attribute in the fetch response.
+ The &lt;alias&gt; will further be used to identify
+ the attribute being exchanged.
+
+</p>
+<p>
+ Attribute aliases MUST NOT contain newline and colon characters,
+ as specified in the Data Formats / Protocol Messages section of
+ <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>; they also MUST
+ NOT contain commas (",") and periods (".").
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.count.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The number of values returned for the attribute referred
+ to as &lt;alias&gt;.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.value.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Assigns a value to the attribute referred to as
+ &lt;alias&gt;. This parameter format MUST be used if
+ "openid.ax.count.&lt;alias&gt;" is not sent.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.value.&lt;alias&gt;.&lt;number&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Assigns a value to the attribute referred to as
+ &lt;alias&gt;. This parameter format MUST be used
+ if "openid.ax.count.&lt;alias&gt;" is sent and at least
+ one value is provided for the associated attribute.
+
+</p>
+<p>
+ The &lt;number&gt; uniquely identifies the index of
+ the value, ranging from one to the value specified by
+ "openid.ax.count.&lt;alias&gt;". The number of
+ parameters MUST be equal to the value specified by
+ "openid.ax.count.&lt;alias&gt;". The OP is not
+ required to preserve the order of attribute values
+ among fetch responses.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.update_url</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Returns the "update_url" parameter specified in the
+ request. If the OpenID Provider receives an
+ "update_url" parameter and it intends to support the
+ attribute update feature, it MUST present the
+ "update_url" parameter and value as part of the fetch
+ response message.
+
+</p>
+</blockquote>
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+ A fetch response message may also be sent to the
+ "update_url" specified in <a class="info" href="#fetch_request">Section&nbsp;5.1<span> (</span><span class="info">Fetch Request Format</span><span>)</span></a> in response to attribute value
+ updates on the OpenID Provider.
+
+</p>
+<p>
+ The response to the previous request example, in which the
+ required full name information, and the optional favourite
+ dog information are supplied. Even though three movie names
+ were requested, the OP supplied only two values.
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.ax=http://openid.net/srv/ax/1.0
+openid.ax.mode=fetch_response
+openid.ax.type.fname=http://example.com/schema/fullname
+openid.ax.type.gender=http://example.com/schema/gender
+openid.ax.type.fav_dog=http://example.com/schema/favourite_dog
+openid.ax.type.fav_movie=http://example.com/schema/favourite_movie
+openid.ax.value.fname=John Smith
+openid.ax.count.gender=0
+openid.ax.value.fav_dog=Spot
+openid.ax.count.fav_movie=2
+openid.ax.value.fav_movie.1=Movie1
+openid.ax.value.fav_movie.2=Movie2
+openid.ax.update_url=http://idconsumer.com/update?transaction_id=a6b5c41
+
+</pre></div>
+<a name="store"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6"></a><h3>6.&nbsp;
+Store Message</h3>
+
+<p>
+ The store message is used to store personal identity
+ information to the OpenID Provider; it provides the means
+ for an RP to transfer to the OP attributes that the user
+ may consider useful, such as by providing them to other RPs.
+ The supported length for attribute aliases MUST be at least
+ 32 characters.
+
+</p>
+<p>
+ The manner in which the OP processes the attribute payload in a
+ store request if out of scope of this document.
+
+</p>
+<a name="store_request"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.1"></a><h3>6.1.&nbsp;
+Store Request Format</h3>
+
+<p>
+ With the exception of "openid.ax.mode", all of the following
+ request fields are OPTIONAL. Any alias referred to in a
+ "openid.ax.value.&lt;alias&gt;" or
+ "openid.ax.value.&lt;alias&gt;.&lt;number&gt;" parameter MUST
+ have an associated "openid.ax.type.&lt;alias&gt;" parameter.
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.ax.mode</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ REQUIRED. Value: "store_request".
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.type.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The value of this parameter specifies the type identifier
+ URI for an attribute in the sore request.
+ The &lt;alias&gt; will further be used to identify
+ the attribute being exchanged.
+
+</p>
+<p>
+ Attribute aliases MUST NOT contain newline and colon characters,
+ as specified in the Data Formats / Protocol Messages section of
+ <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>; they also MUST
+ NOT contain commas (",") and periods (".").
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.count.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ The number of values sent for the attribute referred to
+ as &lt;alias&gt;. If present, it MUST be greater than
+ zero.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.value.&lt;alias&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Assigns a value to the attribute referred to as
+ &lt;alias&gt;. This parameter format MUST be used if
+ "openid.ax.count.&lt;alias&gt;" is not sent.
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.value.&lt;alias&gt;.&lt;number&gt;</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ Assigns a value to the attribute referred to as
+ &lt;alias&gt;. The &lt;number&gt; uniquely identifies the
+ index of the value, ranging from one to the value specified
+ by "openid.ax.count.&lt;alias&gt;". This parameter format
+ MUST be used if "openid.ax.count.&lt;alias&gt;" is sent,
+ and the number of these parameters MUST be equal to the
+ value specified by "openid.ax.count.&lt;alias&gt;".
+
+</p>
+</blockquote>
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.ax=http://openid.net/srv/ax/1.0
+openid.ax.mode=store_request
+openid.ax.type.fname=http://example.com/schema/fullname
+openid.ax.value.fname=Bob Smith
+openid.ax.type.fav_movie=http://example.com/schema/favourite_movie
+openid.ax.count.fav_movie=2
+openid.ax.value.fav_movie.1=Movie1
+openid.ax.value.fav_movie.2=Movie2
+
+</pre></div>
+<a name="store_response"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.2"></a><h3>6.2.&nbsp;
+Store Response Format</h3>
+
+<a name="anchor6"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.2.1"></a><h3>6.2.1.&nbsp;
+Storage Success</h3>
+
+<p>
+ The successful store operation is indicated by the mode
+ parameter in the store response:
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.ax.mode</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ REQUIRED. Value: "store_response_success".
+
+</p>
+</blockquote>
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.ax=http://openid.net/srv/ax/1.0
+openid.ax.mode=store_response_success
+
+</pre></div>
+<a name="anchor7"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.2.2"></a><h3>6.2.2.&nbsp;
+Storage Failure</h3>
+
+<p>
+ A storage failure response has the following format:
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.ax.mode</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ REQUIRED. Value: "store_response_failure".
+
+</p>
+</blockquote>
+
+</dd>
+<dt>openid.ax.error</dt>
+<dd>
+
+<blockquote class="text">
+<p>
+ OPTIONAL. Parameter describing the error condition
+ leading to the failure response, intended to be
+ presented to the user. The locale of the message
+ should match the locale of the HTTP message.
+
+</p>
+</blockquote>
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<p>
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+openid.ns.ax=http://openid.net/srv/ax/1.0
+openid.ax.mode=store_response_failure
+openid.ax.error=General storage failure
+
+</pre></div>
+<a name="anchor8"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7"></a><h3>7.&nbsp;
+Security Considerations</h3>
+
+<p>
+ OpenID Attribute Exchange is an OpenID extension, and thus uses
+ OpenID Authentication request and response messages for exchanging
+ attributes.
+
+</p>
+<p>
+ See the "Security Considerations" section of
+ <a class="info" href="#OpenID.authentication-2.0">[OpenID.authentication‑2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007.</span><span>)</span></a>.
+
+</p>
+<a name="anchor9"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8"></a><h3>8.&nbsp;
+Acknowledgements</h3>
+
+<p>
+ John Merrells and other contributors to the document
+ 'draft-merrells-dix'. Portions of that document were
+ re-used for this one.
+
+</p>
+<p>
+ Mark Wahl advised on how to deal with issues concerning the
+ encoding of attributes.
+
+</p>
+<a name="rfc.references"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9"></a><h3>9.&nbsp;
+References</h3>
+
+<a name="rfc.references1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>9.1.&nbsp;Normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="OpenID.authentication-2.0">[OpenID.authentication-2.0]</a></td>
+<td class="author-text">specs@openid.net, “OpenID Authentication 2.0 - Final,” August&nbsp;2007 (<a href="http://www.openid.net/specs/openid-authentication-2_0.txt">TXT</a>, <a href="http://www.openid.net/specs/openid-authentication-2_0.html">HTML</a>).</td></tr>
+<tr><td class="author-text" valign="top"><a name="OpenID.value-lang-1.0">[OpenID.value-lang-1.0]</a></td>
+<td class="author-text"><a href="mailto:mark.wahl@informed-control.com">Wahl, M.</a>, “<a href="http://www.ldap.com/1/spec/schema/openid-value-lang-1_0-00.html">Language Tags for OpenID Values</a>,” April&nbsp;2007.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2119">[RFC2119]</a></td>
+<td class="author-text"><a href="mailto:sob@harvard.edu">Bradner, S.</a>, “<a href="http://tools.ietf.org/html/rfc2119">Key words for use in RFCs to Indicate Requirement Levels</a>,” BCP&nbsp;14, RFC&nbsp;2119, March&nbsp;1997 (<a href="ftp://ftp.isi.edu/in-notes/rfc2119.txt">TXT</a>, <a href="http://xml.resource.org/public/rfc/html/rfc2119.html">HTML</a>, <a href="http://xml.resource.org/public/rfc/xml/rfc2119.xml">XML</a>).</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3629">[RFC3629]</a></td>
+<td class="author-text">Yergeau, F., “<a href="http://tools.ietf.org/html/rfc3629">UTF-8, a transformation format of ISO 10646</a>,” STD&nbsp;63, RFC&nbsp;3629, November&nbsp;2003 (<a href="ftp://ftp.isi.edu/in-notes/rfc3629.txt">TXT</a>).</td></tr>
+</tbody></table>
+
+<a name="rfc.references2"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>9.2.&nbsp;Non-normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="OpenID.axschema">[OpenID.axschema]</a></td>
+<td class="author-text"><a href="mailto:dick@sxip.com">Hardt, D.</a>, “<a href="http://www.axschema.org/">Schema for OpenID Attribute Exchange</a>,” May&nbsp;2007.</td></tr>
+</tbody></table>
+
+<a name="rfc.authors"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Authors' Addresses</h3>
+<table border="0" cellpadding="0" cellspacing="0" width="99%">
+<tbody><tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Dick Hardt</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Sxip Identity</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">798 Beatty Street</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Vancouver, BC V6B 2M1</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">CA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:dick@sxip.com">dick@sxip.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Johnny Bufu</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Sxip Identity</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">798 Beatty Street</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Vancouver, BC V6B 2M1</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">CA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:johnny@sxip.com">johnny@sxip.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Josh Hoyt</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">JanRain</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">5331 SW Macadam Ave. #375</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Portland, OR 97239</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">US</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:josh@janrain.com">josh@janrain.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://janrain.com/">http://janrain.com/</a></td></tr>
+</tbody></table>
+
+</body></html> \ No newline at end of file
diff --git a/doc/specs/openid-authentication-1_1.html b/doc/specs/openid-authentication-1_1.html
new file mode 100644
index 0000000..9a2708b
--- /dev/null
+++ b/doc/specs/openid-authentication-1_1.html
@@ -0,0 +1,1593 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en"><head><title>OpenID Authentication 1.1</title>
+
+
+<meta http-equiv="Expires" content="Tue, 13 Jun 2006 19:04:16 +0000">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="description" content="OpenID Authentication 1.1">
+<meta name="generator" content="xml2rfc v1.30 (http://xml.resource.org/)">
+<style type="text/css">
+<!--
+ body {
+ font-family: verdana, charcoal, helvetica, arial, sans-serif;
+ margin: 2em;
+ font-size: small ; color: #000000 ; background-color: #ffffff ; }
+ .title { color: #990000; font-size: x-large ;
+ font-weight: bold; text-align: right;
+ font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
+ background-color: transparent; }
+ .filename { color: #666666; font-size: 18px; line-height: 28px;
+ font-weight: bold; text-align: right;
+ font-family: helvetica, arial, sans-serif;
+ background-color: transparent; }
+ td.rfcbug { background-color: #000000 ; width: 30px ; height: 30px ;
+ text-align: justify; vertical-align: middle ; padding-top: 2px ; }
+ td.rfcbug span.RFC { color: #666666; font-weight: bold; text-decoration: none;
+ background-color: #000000 ;
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-size: x-small ; }
+ td.rfcbug span.hotText { color: #ffffff; font-weight: normal; text-decoration: none;
+ text-align: center ;
+ font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-size: x-small ; background-color: #000000; }
+ /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
+ div#counter{margin-top: 100px}
+
+ a.info{
+ position:relative; /*this is the key*/
+ z-index:24;
+ text-decoration:none}
+
+ a.info:hover{z-index:25; background-color:#990000 ; color: #ffffff ;}
+
+ a.info span{display: none}
+
+ a.info:hover span.info{ /*the span will display just on :hover state*/
+ display:block;
+ position:absolute;
+ font-size: smaller ;
+ top:2em; left:2em; width:15em;
+ padding: 2px ;
+ border:1px solid #333333;
+ background-color:#eeeeee; color:#990000;
+ text-align: left ;}
+
+ A { font-weight: bold; }
+ A:link { color: #990000; background-color: transparent ; }
+ A:visited { color: #333333; background-color: transparent ; }
+ A:active { color: #333333; background-color: transparent ; }
+
+ p { margin-left: 2em; margin-right: 2em; }
+ p.copyright { font-size: x-small ; }
+ p.toc { font-size: small ; font-weight: bold ; margin-left: 3em ;}
+ table.toc { margin: 0 0 0 3em; padding: 0; border: 0; vertical-align: text-top; }
+ td.toc { font-size: small; font-weight: bold; vertical-align: text-top; }
+
+ span.emph { font-style: italic; }
+ span.strong { font-weight: bold; }
+ span.verb, span.vbare { font-family: "Courier New", Courier, monospace ; }
+
+ span.vemph { font-style: italic; font-family: "Courier New", Courier, monospace ; }
+ span.vstrong { font-weight: bold; font-family: "Courier New", Courier, monospace ; }
+ span.vdeluxe { font-weight: bold; font-style: italic; font-family: "Courier New", Courier, monospace ; }
+
+ ol.text { margin-left: 2em; margin-right: 2em; }
+ ul.text { margin-left: 2em; margin-right: 2em; }
+ li { margin-left: 3em; }
+
+ pre { margin-left: 3em; color: #333333; background-color: transparent;
+ font-family: "Courier New", Courier, monospace ; font-size: small ;
+ text-align: left;
+ }
+
+ h3 { color: #333333; font-size: medium ;
+ font-family: helvetica, arial, sans-serif ;
+ background-color: transparent; }
+ h4 { font-size: small; font-family: helvetica, arial, sans-serif ; }
+
+ table.bug { width: 30px ; height: 15px ; }
+ td.bug { color: #ffffff ; background-color: #990000 ;
+ text-align: center ; width: 30px ; height: 15px ;
+ }
+ td.bug A.link2 { color: #ffffff ; font-weight: bold;
+ text-decoration: none;
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
+ font-size: x-small ; background-color: transparent }
+
+ td.header { color: #ffffff; font-size: x-small ;
+ font-family: arial, helvetica, sans-serif; vertical-align: top;
+ background-color: #666666 ; width: 33% ; }
+ td.author { font-weight: bold; margin-left: 4em; font-size: x-small ; }
+ td.author-text { font-size: x-small; }
+ table.full { vertical-align: top ; border-collapse: collapse ;
+ border-style: solid solid solid solid ;
+ border-color: black black black black ;
+ font-size: small ; text-align: center ; }
+ table.headers, table.none { vertical-align: top ; border-collapse: collapse ;
+ border-style: none;
+ font-size: small ; text-align: center ; }
+ table.full th { font-weight: bold ;
+ border-style: solid ;
+ border-color: black black black black ; }
+ table.headers th { font-weight: bold ;
+ border-style: none none solid none;
+ border-color: black black black black ; }
+ table.none th { font-weight: bold ;
+ border-style: none; }
+ table.full td {
+ border-style: solid solid solid solid ;
+ border-color: #333333 #333333 #333333 #333333 ; }
+ table.headers td, table.none td { border-style: none; }
+
+ hr { height: 1px }
+-->
+</style></head><body>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<table summary="layout" border="0" cellpadding="0" cellspacing="0" width="66%"><tbody><tr><td><table summary="layout" border="0" cellpadding="2" cellspacing="1" width="100%">
+<tbody><tr><td class="header">&nbsp;</td><td class="header">D. Recordon</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">B. Fitzpatrick</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">May 2006</td></tr>
+</tbody></table></td></tr></tbody></table>
+<div align="right"><span class="title"><br>OpenID Authentication 1.1</span></div>
+
+<h3>Abstract</h3>
+
+<p>OpenID Authenticaion provides a way to prove that an End User
+ owns an Identity URL. It does this without passing around their
+ password, email address, or anything they don't want it
+ to.
+</p>
+<p>OpenID is completely decentralized meaning that anyone
+ can choose to be a Consumer or Identity Provider without having
+ to register or be approved by any central authority. End User's
+ can pick which Identity Provider they wish to use and preserve
+ their Identity as they move between Providers.
+</p>
+<p>While nothing in the protocol requires JavaScript or modern
+ browsers, the authentication scheme plays nicely with
+ "AJAX"-style setups, so an End User can prove their Identity to
+ a Consumer without having to leave the page they are on.
+</p>
+<p>The OpenID Authentication specification does not provide any
+ mechanism to exchange profile information, though Consumers of
+ an Identity can learn more about an End User from any public,
+ semantically interesting documents linked thereunder (FOAF, RSS,
+ Atom, vCARD, etc.). Extensions are being built on top of the
+ foundation created by OpenID Authentication to provide
+ mechanisms to exchange profile information.
+</p><a name="toc"></a><br><hr>
+<h3>Table of Contents</h3>
+<p class="toc">
+<a href="#anchor1">1.</a>&nbsp;
+Requirements Notation<br>
+<a href="#anchor2">2.</a>&nbsp;
+Terminology<br>
+<a href="#anchor3">3.</a>&nbsp;
+Overview<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor4">3.1.</a>&nbsp;
+Transforming a HTML Document Into an Identifier<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#delegating_authentication">3.1.1.</a>&nbsp;
+Delegating Authentication<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor6">3.2.</a>&nbsp;
+Submitting a Claimed Identifier<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor8">3.3.</a>&nbsp;
+Consumer Site Fetches the Identifier URL<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#smart_vs_dumb">3.4.</a>&nbsp;
+Smart vs Dumb Mode<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor11">3.5.</a>&nbsp;
+Consumer Verifies the Identifier<br>
+<a href="#anchor12">4.</a>&nbsp;
+Modes<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mode_associate">4.1.</a>&nbsp;
+associate<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor13">4.1.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor14">4.1.2.</a>&nbsp;
+Response Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor15">4.1.3.</a>&nbsp;
+Extra Notes<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mode_checkid_immediate">4.2.</a>&nbsp;
+checkid_immediate<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor16">4.2.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor17">4.2.2.</a>&nbsp;
+Response Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor21">4.2.3.</a>&nbsp;
+Extra Notes<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mode_checkid_setup">4.3.</a>&nbsp;
+checkid_setup<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor22">4.3.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor23">4.3.2.</a>&nbsp;
+Respone Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor26">4.3.3.</a>&nbsp;
+Extra Notes<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#mode_check_authentication">4.4.</a>&nbsp;
+check_authentication<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor27">4.4.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor28">4.4.2.</a>&nbsp;
+Response Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor29">4.4.3.</a>&nbsp;
+Extra Notes<br>
+<a href="#anchor30">5.</a>&nbsp;
+Security Considerations<br>
+<a href="#defaults">Appendix&nbsp;A.</a>&nbsp;
+Default Values<br>
+<a href="#pvalue">Appendix&nbsp;A.1.</a>&nbsp;
+Diffie-Hellman P Value<br>
+<a href="#anchor31">Appendix&nbsp;B.</a>&nbsp;
+Error Responses<br>
+<a href="#anchor32">Appendix&nbsp;C.</a>&nbsp;
+Key-Value Format<br>
+<a href="#limits">Appendix&nbsp;D.</a>&nbsp;
+Limits<br>
+<a href="#anchor33">Appendix&nbsp;E.</a>&nbsp;
+Misc<br>
+<a href="#rfc.references1">6.</a>&nbsp;
+Normative References<br>
+<a href="#rfc.authors">§</a>&nbsp;
+Authors' Addresses<br>
+</p>
+<br clear="all">
+
+<a name="anchor1"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1"></a><h3>1.&nbsp;Requirements Notation</h3>
+
+<p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
+ "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" in this document are to be interpreted as
+ described in <a class="info" href="#RFC2119">[RFC2119]<span> (</span><span class="info">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels,” .</span><span>)</span></a>.
+</p>
+<a name="anchor2"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.2"></a><h3>2.&nbsp;Terminology</h3>
+
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>End User:</dt>
+<dd>The actual human user who wants to
+ prove their Identity to a Consumer.
+</dd>
+<dt>Identifier:</dt>
+<dd>An Identifier is just a URL. The whole
+ flow of the OpenID Authentication protocol is about proving
+ that an End User is, owns, a URL.
+</dd>
+<dt>Claimed Identifier:</dt>
+<dd>An Identifier that the End
+ User says they own, though that has not yet been verified by
+ the Consumer.
+</dd>
+<dt>Verified Identifier:</dt>
+<dd>An Identifier that the
+ End User has proven to a Consumer that they own.
+</dd>
+<dt>Consumer:</dt>
+<dd>A web service that wants proof that
+ the End User owns the Claimed Identifier.
+</dd>
+<dt>Identity Provider:</dt>
+<dd>Also called "IdP" or
+ "Server". This is the OpenID Authentication server
+ that a Consumer contacts for cryptographic proof that the
+ End User owns the Claimed Identifier.
+ <br>
+
+ How the End User authenticates to their Identity Provider is
+ outside of the scope of OpenID Authenticaiton.
+
+</dd>
+<dt>User-Agent:</dt>
+<dd>The End User's web browser. No
+ special plug-ins or JavaScript required.
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor3"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3"></a><h3>3.&nbsp;Overview</h3>
+
+<a name="anchor4"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.1"></a><h3>3.1.&nbsp;Transforming a HTML Document Into an Identifier</h3>
+
+<p>In order for a Consumer to know the Identity Provider
+ authoritative for an Identifier, the End User must add markup to
+ the HEAD section of the HTML document located at their
+ URL. The host of the HTML document is NOT REQUIRED to also be
+ the End User's Identity Provider; the Identifier URL and
+ Identity Provider can be fully decoupled services.
+</p>
+<p>To use http://example.com/ as the End User's Identifier
+ http://openid.example.com as their Identity Provider, the
+ following tag would be added to the HEAD section of the HTML
+ document returned when fetching their Identifier URL.
+</p>
+<p>&lt;link rel="openid.server"
+ href="http://openid.example.com/"&gt;
+</p>
+<a name="delegating_authentication"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.1.1"></a><h3>3.1.1.&nbsp;Delegating Authentication</h3>
+
+<p>If the End User's host is not capable of running an
+ Identity Provider, or the End User wishes to use one running
+ on a different host, they will need to delegate their
+ authentication. For example, if they want to use their
+ website, http://www.example.com/, as their Identifier, but
+ don't have the means, or desire, to run an Identity
+ Provider.
+</p>
+<p>If they have a LiveJournal account (say, user
+ "exampleuser"), and know that LiveJournal provides an OpenID
+ Identity Provider and that it'll assert that they control
+ the Identifier http://exampleuser.livejournal.com/ they would
+ be able to delegate their authentication to LiveJournal's
+ Identity Provider..
+</p>
+<p>So, to use www.example.com as their Identifier, but have
+ Consumers actually verify
+ http://exampleuser.livejournal.com/ with the Identity
+ Provider located at
+ http://www.livejournal.com/openid/server.bml, they'd add the
+ following tags to the HEAD section of the HTML document
+ returned when fetching their Identifier URL.
+</p>
+<p>&lt;link rel="openid.server"
+ href="http://www.livejournal.com/openid/server.bml"&gt;
+</p>
+<p>&lt;link rel="openid.delegate"
+ href="http://exampleuser.livejournal.com/"&gt;
+</p>
+<p>Now, when a Consumer sees that, it'll talk to
+ http://www.livejournal.com/openid/server.bml and ask if
+ the End User is exampleuser.livejournal.com, never mentioning
+ www.example.com anywhere on the wire.
+</p>
+<p>The main advantage of this is that an End User can keep
+ their Identifier over many years, even as services come and
+ go; they'll just keep changing who they delegate to.
+</p>
+<a name="anchor5"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.1.2"></a><h3>3.1.2.&nbsp;Important Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>The declared openid.server URL MAY contain existing
+ query parameters and they MUST be properly preserved when
+ appending extra query parameters. For example, not adding
+ a second question mark if one already exists.
+</li>
+<li>The openid.server and openid.delegate URLs MUST
+ be absolute URLs. Consumers MUST NOT attempt to
+ resolve relative URLs.
+</li>
+<li>The openid.server and openid.delegate URLs MUST
+ NOT include entities other than &amp;, &lt;, &gt;,
+ and ". Other characters that would not be
+ valid in the HTML document or that cannot be
+ represented in the document's character encoding
+ MUST be escaped using the %xx mechanism as described
+ in <a class="info" href="#RFC2396">[RFC2396]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a>.
+</li>
+</ul><p>
+
+</p>
+<a name="anchor6"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.2"></a><h3>3.2.&nbsp;Submitting a Claimed Identifier</h3>
+
+<p>Continuing this example, the End User visits a Consumer
+ site which supports OpenID Authentication. The Consumer
+ presents the End User with a form field for them to enter
+ their Identifier URL.
+</p>
+<p>
+
+</p><p>For Example:
+</p><pre> ----------------------------------
+ |[logo]example.com | [Login Button]
+ ----------------------------------
+</pre>
+
+
+<a name="anchor7"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.2.1"></a><h3>3.2.1.&nbsp;Important Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>It is RECOMMENDED that every Consumer place the
+ <a href="http://openid.net/login-bg.gif">OpenID
+ logo</a> at the beginning of the form field where the
+ End User enters their Identifier URL.
+</li>
+<li>The End User is NOT REQUIRED to prefix
+ their Identifier URL with "http://" or postfix it with a
+ trailing slash. Consumers MUST canonicalize the Identifier
+ URL, following redirects, and note the final URL.
+ The final, canonicalized URL is the End User's
+ Identifier.
+</li>
+<li>It is RECOMMENDED that the form field be named
+ "openid_url" so User-Agent's will auto-complete the End
+ User's Identifier URL in the same way the eCommerce world
+ tends to use conventions like "address1" and
+ "address2".
+</li>
+</ul><p>
+
+</p>
+<a name="anchor8"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.3"></a><h3>3.3.&nbsp;Consumer Site Fetches the Identifier URL</h3>
+
+<p>Now the Consumer site fetchs the document located at the End
+ User's Claimed Identifier. The Consumer then parses the HEAD
+ section for the "openid.server" and the optional
+ "openid.delegate" declarations.
+</p>
+<a name="anchor9"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.3.1"></a><h3>3.3.1.&nbsp;Important Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>The End User could be malicious and try to make the
+ Consumer connect to an internal network, tarpit, etc. It
+ is RECOMMENDED that Consumers use a paranoid HTTP library like <a href="http://search.cpan.org/%7Ebradfitz/LWPx-ParanoidAgent-1.02/lib/LWPx/ParanoidAgent.pm">LWPx::ParanoidAgent</a> that protects against these sorts of attacks.
+</li>
+<li>Consumers MUST implement support for <a class="info" href="#delegating_authentication">Delegation<span> (</span><span class="info">Delegating Authentication</span><span>)</span></a>.
+</li>
+</ul><p>
+
+</p>
+<a name="smart_vs_dumb"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.4"></a><h3>3.4.&nbsp;Smart vs Dumb Mode</h3>
+
+<p>OpenID Authentication supports both a "smart mode" and
+ "dumb mode" to accomodate Consumers of differing
+ capabilities. A smart Consumer does a little more work at the
+ beginning to save itself work later, but requires local
+ caching of state information. A dumb Consumer is completely
+ stateless, but requires extra an HTTP request.
+</p>
+<a name="anchor10"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.4.1"></a><h3>3.4.1.&nbsp;Important Notes for Smart Mode</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>It's RECOMMENDED that a Consumer first submit an
+ <a class="info" href="#mode_associate">associate request<span> (</span><span class="info">associate</span><span>)</span></a>
+ to the End User's Identity Provider and request a shared
+ secret if the Consumer does not already have one
+ cached. This shared secret SHOULD be used as the
+ HMAC-SHA1 key in future identity check requests until it
+ expires.
+</li>
+<li>The shared secret can be exchanged either in
+ plain-text or encrypted with a Diffie-Hellman-negotiated
+ secret. Note that if Diffie-Hellman is used, it's only
+ used in the associate mode. The <a class="info" href="#mode_checkid_immediate">checkid_immediate<span> (</span><span class="info">checkid_immediate</span><span>)</span></a>
+ and <a class="info" href="#mode_checkid_setup">checkid_setup<span> (</span><span class="info">checkid_setup</span><span>)</span></a>
+ modes assume the Consumer already has a shared secret,
+ regardless of how it got it.
+</li>
+</ul><p>
+
+</p>
+<a name="anchor11"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3.5"></a><h3>3.5.&nbsp;Consumer Verifies the Identifier</h3>
+
+<p>The Consumer now constructs a URL to the Identity
+ Provider's <a class="info" href="#mode_checkid_immediate">checkid_immediate<span> (</span><span class="info">checkid_immediate</span><span>)</span></a> (or
+ <a class="info" href="#mode_checkid_setup">checkid_setup<span> (</span><span class="info">checkid_setup</span><span>)</span></a>) URLs
+ and sends the User-Agent to it.
+</p>
+<p>By sending the User-Agent there, the End User's cookies and
+ whatever other login credentials are sent back to their
+ trusted Identity Provider. The Identity Provider does its
+ work, appends its response onto the supplied openid.return_to
+ URL, and sends the User-Agent back to the Consumer.
+</p>
+<a name="anchor12"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4"></a><h3>4.&nbsp;Modes</h3>
+
+<a name="mode_associate"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1"></a><h3>4.1.&nbsp;associate</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Description: Establish a shared secret between Consumer
+ and Identity Provider.
+</li>
+<li>HTTP method: POST
+</li>
+<li>Flow: Consumer -&gt; IdP -&gt; Consumer
+</li>
+</ul><p>
+
+</p>
+<a name="anchor13"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.1"></a><h3>4.1.1.&nbsp;Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "associate"
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_type
+
+<blockquote class="text">
+<p>Value: Preferred association type
+</p>
+<p>Default: "HMAC-SHA1"
+</p>
+<p>Note: Optional; Currently only one value.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.session_type
+
+<blockquote class="text">
+<p>Value: Blank or "DH-SHA1"
+</p>
+<p>Default: Blank. (cleartext)
+</p>
+<p>Note: It is RECOMMENDED that DH-SHA1 mode is used
+ to encrypt the shared secret.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.dh_modulus
+
+<blockquote class="text">
+<p>Value: base64(btwoc(p))
+</p>
+<p>Note: See <a class="info" href="#pvalue">Appendix&nbsp;A.1<span> (</span><span class="info">Diffie-Hellman P Value</span><span>)</span></a> for default p value.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.dh_gen
+
+<blockquote class="text">
+<p>Value: base64(btwoc(g))
+</p>
+<p>Default: g = 2
+</p>
+<p>Note: Only if using DH-SHA1 session_type. Should
+ be specified if openid.dh_modulus is specified.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.dh_consumer_public
+
+<blockquote class="text">
+<p>Value: base64(btwoc(g ^ x mod p))
+</p>
+<p>Note: REQUIRED if using DH-SHA1 session_type.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor14"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.2"></a><h3>4.1.2.&nbsp;Response Parameters</h3>
+
+<p>Response format: Key-Value Pairs
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ assoc_type
+
+<blockquote class="text">
+<p>Value: The association type for the returned handle.
+</p>
+<p>Note: The only current mode is HMAC-SHA1, and all
+ Consumers MUST support it. When caching, the
+ Consumer MUST map an assoc_handle to both its secret
+ and its assoc_type.
+</p>
+</blockquote>
+
+</li>
+<li>
+ assoc_handle
+
+<blockquote class="text">
+<p>Value: The association handle to be provided in future
+ transactions.
+</p>
+<p>Note: Consumers MUST NOT reuse this association
+ handle after the corresponding expires_in value.
+</p>
+</blockquote>
+
+</li>
+<li>
+ expires_in
+
+<blockquote class="text">
+<p>Value: The number of seconds this association
+ handle is good for in base10 ASCII.
+</p>
+</blockquote>
+
+</li>
+<li>
+ session_type
+
+<blockquote class="text">
+<p>Value: The encryption mode that the Provider chose. MAY be
+ blank, absent, or "DH-SHA1".
+</p>
+</blockquote>
+
+</li>
+<li>
+ dh_server_public
+
+<blockquote class="text">
+<p>Value: base64(btwoc(g ^ y mod p))
+</p>
+<p>Description: The Provider's <a class="info" href="#RFC2631">Diffie-Hellman public key<span> (</span><span class="info">Rescorla, E., “Diffie-Hellman Key Agreement Method,” .</span><span>)</span></a> [RFC2631], if
+ using DH-SHA1.
+</p>
+</blockquote>
+
+</li>
+<li>
+ enc_mac_key
+
+<blockquote class="text">
+<p>Value: base64(SHA1(btwoc(g ^ (xy) mod p)) XOR secret(assoc_handle))
+</p>
+<p>Description: The encrypted shared secret, if using
+ DH-SHA1.
+</p>
+</blockquote>
+
+</li>
+<li>
+ mac_key
+
+<blockquote class="text">
+<p>Value: base64(secret(assoc_handle))
+</p>
+<p>Description: The plaintext shared secret, if not
+ using DH-SHA1.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor15"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.3"></a><h3>4.1.3.&nbsp;Extra Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>A Consumer can ask a server for DH-SHA1 encryption and
+ get back a plaintext secret. If this troubles you, don't
+ use the handle and instead use dumb mode with that
+ Identity Provider.
+ <br>
+<br>
+
+ If somebody sniffed the plaintext secret, it won't
+ matter, since you'll never accept queries using that
+ association handle. If the Identity Provider can't do
+ DH-SHA1, it's probably limited in some way, but using
+ dumb mode is still safe, if not a little slower.
+</li>
+<li>If the Identity Provider chooses the server private
+ key 1 &lt;= y &lt; p-1. The shared DH-SHA1 secret is
+ thus g ^ xy mod p = (g ^ x) ^ y mod p = (g ^ y) ^ x mod
+ p. For more information, read the <a href="http://search.cpan.org/%7Ebtrott/Crypt-DH-0.06/lib/Crypt/DH.pm">Crypt::DH docs.</a>
+</li>
+<li>The underlying mac_key MUST be the same length as the
+ output of H, the hash function - in this instance, 160
+ bits (20 bytes) for DH-SHA1.
+</li>
+<li>If the Provider does not support DH-SHA1, they WILL ignore
+ the DH-SHA1 fields in the request and reply exactly as to a
+ non-DH-SHA1 request.
+</li>
+<li>When using DH-SHA1, the resulting key SHOULD be treated
+ as a binary string.
+</li>
+<li>Most integers are represented in big-endian signed two's
+ complement, Base64 encoded. In other words, btwoc is a
+ function that takes a bigint and returns its shortest
+ big-endian two's complement notation
+</li>
+</ul><p>
+
+</p>
+<a name="mode_checkid_immediate"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2"></a><h3>4.2.&nbsp;checkid_immediate</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Description: Ask an Identity Provider if a End User owns the
+ Claimed Identifier, getting back an immediate "yes" or "can't say"
+ answer.
+</li>
+<li>HTTP method: GET
+</li>
+<li>Flow: Consumer -&gt; User-Agent -&gt; IdP -&gt; User-Agent -&gt;
+ Consumer
+</li>
+</ul><p>
+
+</p>
+<a name="anchor16"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.1"></a><h3>4.2.1.&nbsp;Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "checkid_immediate"
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>Value: Claimed Identifier
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>Value: The assoc_handle from the associate request.
+</p>
+<p>Note: Optional; Consumer MUST use
+ check_authentication if an association handle isn't
+ provided or the Identity Provider feels it is invalid.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>Value: URL where the Provider SHOULD return the
+ User-Agent back to.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.trust_root
+
+<blockquote class="text">
+<p>Value: URL the Provider SHALL ask the End User to trust.
+</p>
+<p>Default: return_to URL
+</p>
+<p>Optional; the URL which the End User SHALL
+ actually see to approve.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor17"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.2"></a><h3>4.2.2.&nbsp;Response Parameters</h3>
+
+<p>Response format: query string arguments
+</p>
+<a name="anchor18"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.2.1"></a><h3>4.2.2.1.&nbsp;Always Sent</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "id_res"
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor19"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.2.2"></a><h3>4.2.2.2.&nbsp;Sent on Failed Assertion</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.user_setup_url
+
+<blockquote class="text">
+<p>Value: URL to redirect User-Agent to so the End
+ User can do whatever's necessary to fulfill the
+ assertion.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor20"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.2.3"></a><h3>4.2.2.3.&nbsp;Sent on Positive Assertion</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>Value: Verified Identifier
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>Value: Opaque association handle being used to
+ find the HMAC key for the signature.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>Value: Verbatim copy of the return_to URL
+ parameter sent in the request, before the Provider
+ modified it.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.signed
+
+<blockquote class="text">
+<p>Value: Comma-seperated list of signed fields.
+</p>
+<p>Note: Fields without the "openid." prefix that
+ the signature covers. For example,
+ "mode,identity,return_to".
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.sig
+
+<blockquote class="text">
+<p>Value: base64(HMAC(secret(assoc_handle), token_contents)
+</p>
+<p>Note: Where token_contents is a key-value
+ format string of all the signed keys and values in
+ this response. They MUST be in the same order as
+ listed in the openid.signed field. Consumer SHALL
+ recreate the token_contents string prior to
+ checking the signature. See <a class="info" href="#limits">Appendix&nbsp;D<span> (</span><span class="info">Limits</span><span>)</span></a>.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.invalidate_handle
+
+<blockquote class="text">
+<p>Value: Optional; The association handle sent in
+ the request if the Provider did not accept or
+ recognize it.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor21"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2.3"></a><h3>4.2.3.&nbsp;Extra Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>This mode is commonly used for "AJAX"-style
+ setups. The more classic mode to check a Claimed
+ Identifier is <a class="info" href="#mode_checkid_setup">checkid_setup<span> (</span><span class="info">checkid_setup</span><span>)</span></a>.
+</li>
+<li>An Identity Provider SHOULD only assert URLs that it
+ manages/produces directly. If a End User wants to assert
+ other URLs outside of that Identity Provider's realm,
+ they MUST use <a class="info" href="#delegating_authentication">delegation<span> (</span><span class="info">Delegating Authentication</span><span>)</span></a>.
+</li>
+<li>The openid.return_to URL provided MAY contain an
+ existing query string, and the Provider MUST preserve it
+ when appending the response parameters. OpenID Consumer's
+ SHOULD add a self-signed nonce with
+ Consumer-local timestamp in the openid.return_to URL
+ parameters to prevent replay attacks. Details of that
+ are left up to the Consumer.
+ <br>
+<br>
+
+ However, because the openid.return_to URL is signed by
+ the Idenity Provide, a Consumer can make sure outside
+ parties haven't sent id_res responses with mismatching
+ openid.return_to URLs and signatures.
+</li>
+<li>If the Identity Provider didn't accept/recognize the
+ provided assoc_handle for whatever reason, it'll choose
+ its own to use, and copy the one provided back into
+ openid.invalidate_handle, to tell the Consumer to stop
+ using it. The Consumer SHOULD then send it along in a
+ <a class="info" href="#mode_check_authentication">check_authentication<span> (</span><span class="info">check_authentication</span><span>)</span></a>
+ request to verify it actually is no longer valid.
+</li>
+<li>If the Identifier assertion fails, the Identity
+ Provider provides the openid.user_setup_url for where
+ the End User can do whatever's necessary to fulfill the
+ assertion, be it login, setup permissions, etc. The
+ server SHOULD return a URL which doesn't imply anything
+ about what's needed, so the Consumer is left in the dark
+ about why the assertion failed.
+ <br>
+<br>
+
+ The Identity Provider handling SHOULD eventually return
+ the End User to the openid.return_to URL, acting like a
+ checkid_setup response, with either a "id_res" or "cancel"
+ mode.
+</li>
+<li>The openid.return_to URL MUST descend from the
+ openid.trust_root, or the Identity Provider SHOULD
+ return an error. Namely, the URL scheme and port MUST
+ match. The path, if present, MUST be equal to or below
+ the value of openid.trust_root, and the domains on both
+ MUST match, or, the openid.trust_root value contain a
+ wildcard like http://*.example.com. The wildcard SHALL
+ only be at the beginning. It is RECOMMENDED Identity
+ Provider's protect their End Users from requests for
+ things like http://*.com/ or http://*.co.uk/.
+</li>
+<li>In the response, the Identity Provider's signature
+ MUST cover openid.identity and openid.return_to.
+</li>
+</ul><p>
+
+</p>
+<a name="mode_checkid_setup"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3"></a><h3>4.3.&nbsp;checkid_setup</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Description: Ask an Identity Provider if a End User owns the
+ Claimed Identifier, but be willing to wait for the reply.
+ The Consumer will pass the User-Agent to the Identity
+ Provider for a short period of time which will return
+ either a "yes" or "cancel" answer.
+</li>
+<li>HTTP method: GET
+</li>
+<li>Flow: Consumer -&gt; User-Agent -&gt; [IdP -&gt; User-Agent
+ -&gt;]+ Consumer
+</li>
+</ul><p>
+
+</p>
+<a name="anchor22"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3.1"></a><h3>4.3.1.&nbsp;Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "checkid_setup"
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>Value: Claimed Identifier
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>Value: The assoc_handle from the associate request.
+</p>
+<p>Note: Optional; Consumer MUST use
+ check_authentication if an association handle isn't
+ provided or the Identity Provider feels it is invalid.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>Value: URL where the Provider SHOULD return the
+ User-Agent back to.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.trust_root
+
+<blockquote class="text">
+<p>Value: URL the Provider SHALL ask the End User to trust.
+</p>
+<p>Default: return_to URL
+</p>
+<p>Optional; the URL which the End User SHALL
+ actually see to approve.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor23"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3.2"></a><h3>4.3.2.&nbsp;Respone Parameters</h3>
+
+<p>Response format: query string arguments
+</p>
+<a name="anchor24"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3.2.1"></a><h3>4.3.2.1.&nbsp;Always Sent</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "id_res" or "cancel"
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor25"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3.2.2"></a><h3>4.3.2.2.&nbsp;Sent on Positive Assertion</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>Value: Verified Identifier
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>Value: Opaque association handle being used to
+ fine the HMAC key for the signature.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>Value: Verbatim copy of the return_to URL
+ parameter sent in the request, before the Provider
+ modified it.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.signed
+
+<blockquote class="text">
+<p>Value: Comma-seperated list of signed fields.
+</p>
+<p>Note: Fields without the "openid." prefix that
+ the signature covers. For example,
+ "mode,identity,return_to".
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.sig
+
+<blockquote class="text">
+<p>Value: base64(HMAC(secret(assoc_handle), token_contents)
+</p>
+<p>Note: Where token_contents is a key-value
+ format string of all the signed keys and values in
+ this response. They MUST be in the same order as
+ listed in the openid.signed field. Consumer SHALL
+ recreate the token_contents string prior to
+ checking the signature. See <a class="info" href="#limits">Appendix&nbsp;D<span> (</span><span class="info">Limits</span><span>)</span></a>.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.invalidate_handle
+
+<blockquote class="text">
+<p>Value: Optional; The association handle sent in
+ the request if the Provider did not accept or
+ recognize it.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor26"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.3.3"></a><h3>4.3.3.&nbsp;Extra Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>In the response, the Identity Provider's signature
+ MUST cover openid.identity and openid.return_to.
+</li>
+<li>In a lot of cases, the Consumer won't get a cancel mode; the
+ End User will just quit or press back within their
+ User-Agent. But if it is returned, the Consumer SHOULD
+ return to what it was doing. In the case of a cancel
+ mode, the rest of the response parameters will be
+ absent.
+</li>
+</ul><p>
+
+</p>
+<a name="mode_check_authentication"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.4"></a><h3>4.4.&nbsp;check_authentication</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Description: Ask an Identity Provider if a message is
+ valid. For dumb, stateless Consumers or when verifying an
+ invalidate_handle response.
+ <br>
+<br>
+
+ <span class="strong">WARNING: Only validates signatures
+ with stateless association handles. Identity Providers
+ MUST NOT ever validate a signature for an association
+ handle whose secret has been shared with anybody. They
+ MUST differentiate its stateless vs. associated
+ association handles, and only offer check_authentication
+ service on the stateless handles.</span>
+
+</li>
+<li>HTTP method: POST
+</li>
+<li>Flow: Consumer -&gt; IdP -&gt; Consumer
+</li>
+</ul><p>
+
+</p>
+<a name="anchor27"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.4.1"></a><h3>4.4.1.&nbsp;Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "check_authentication"
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>Value: The association handle from checkid_setup
+ or checkid_immediate response.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.sig
+
+<blockquote class="text">
+<p>Value: The signature from the checkid_setup or
+ checkid_immediate request the Consumer wishes to
+ verify.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.signed
+
+<blockquote class="text">
+<p>Value: The list of signed fields from the checkid_setup
+ or checkid_immediate request the Consumer wishes to
+ verify the signature of.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.*
+
+<blockquote class="text">
+<p>Value: The Consumer MUST send all the openid.* response
+ parameters from the openid.signed list which they'd
+ previously gotten back from a checkid_setup or
+ checkid_immediate request, with their values being
+ exactly what were returned from the Provider.
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.invalidate_handle
+
+<blockquote class="text">
+<p>Value: Optional; association handle returned via
+ invalidate_handle.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor28"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.4.2"></a><h3>4.4.2.&nbsp;Response Parameters</h3>
+
+<p>Response format: Key-Value Pairs
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "id_res"
+</p>
+</blockquote>
+
+</li>
+<li>
+ is_valid
+
+<blockquote class="text">
+<p>Value: "true" or "false"
+</p>
+<p>Description: Boolean; whether the signature is
+ valid.
+</p>
+</blockquote>
+
+</li>
+<li>
+ invalidate_handle
+
+<blockquote class="text">
+<p>Value: opaque association handle
+</p>
+<p>Description: If present, the Consumer SHOULD
+ uncache the returned association handle.
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor29"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.4.3"></a><h3>4.4.3.&nbsp;Extra Notes</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Identity Providers MUST implement this mode for error
+ recovery and dumb Consumers, which can't keep state
+ locally, but it's RECOMMENDED that it is used as little
+ as possible, as it shouldn't be necessary most the
+ time. It's good for debugging, though, as you develop
+ your Consumer library.
+</li>
+<li>If you got an invalidate_handle response during a
+ checkid_setup or checkid_immediate request, that means
+ the Identity Provider didn't recognize the association
+ handle, maybe it lost it, and had to pick its own.
+ <br>
+<br>
+
+ This means the Consumer will have to fallback to dumb
+ mode, since you don't have the shared secret which the
+ Identity Provider is using. While doing this
+ check_authentication request, also send along the
+ invalidate_handle response from the Identity Provider
+ and it'll be checked to see if it actually is
+ missing/bogus.
+</li>
+<li>When verifying the signature using openid.* query
+ values, the openid.mode value must be changed to
+ "id_res".
+</li>
+</ul><p>
+
+</p>
+<a name="anchor30"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5"></a><h3>5.&nbsp;Security Considerations</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>While the OpenID Authentication protocol often refers to
+ using HTTP, HTTPS can be used for additional security. It is
+ RECOMMENDED it is used during the <a class="info" href="#mode_associate">associate mode<span> (</span><span class="info">associate</span><span>)</span></a> and helps to
+ protect against man in the middle, DNS, and some phishing
+ attacks.
+</li>
+<li>Consumers SHOULD NOT use IFrames or popup's when requesting
+ an End User login via OpenID.
+</li>
+</ul><p>
+
+</p>
+<a name="defaults"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A"></a><h3>Appendix A.&nbsp;Default Values</h3>
+
+<a name="pvalue"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.1"></a><h3>Appendix A.1.&nbsp;Diffie-Hellman P Value</h3>
+
+<p>
+ 1551728981814736974712322577637155\
+ 3991572480196691540447970779531405\
+ 7629378541917580651227423698188993\
+ 7278161526466314385615958256881888\
+ 8995127215884267541995034125870655\
+ 6549803580104870537681476726513255\
+ 7470407658574792912915723345106432\
+ 4509471500722962109419434978392598\
+ 4760375594985848253359305585439638443
+
+</p>
+<a name="anchor31"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.B"></a><h3>Appendix B.&nbsp;Error Responses</h3>
+
+<p>This section pertains to protocol/run-time errors, not
+ authentication errors. Authentication errors are defined in
+ the protocol.
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>No error codes have been defined; just unstructured natural
+ language error text.
+</li>
+<li>If it's a GET request with bad arguments, but a valid
+ openid.return_to URL, the Identity Provider SHALL redirect
+ the User-Agent with openid.mode=error and
+ openid.error=Error+Text set.
+</li>
+<li>If it's a GET request with bad arguments, and no valid
+ openid.return_to URL, the Identity Provider SHALL return a
+ "400 Bad Request" with any content-type and error message it
+ wants.
+</li>
+<li>If it's a GET request with no arguments, the Identity
+ Provider SHALL show a 200 text/html error saying "This is an
+ OpenID server endpoint. For more information, see
+ http://openid.net/".
+</li>
+<li>If it's a POST request with bad/no arguments, the
+ Identity Provider SHALL return a 400 Bad Eequest with the
+ Key-Value response format containing a single key "error"
+ with the natural language text. The Identity Provider can
+ add any additonal keys it wishes in this case.
+</li>
+</ul><p>
+
+</p>
+<a name="anchor32"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.C"></a><h3>Appendix C.&nbsp;Key-Value Format</h3>
+
+<p>Lines of:
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>some_key:some value
+</li>
+<li>There MUST NOT be a space before or after the colon.
+</li>
+<li>Newline characters MUST be Unix-style, just ASCII character 10
+ ("\n").
+</li>
+<li>Newlines MUST BE at end of each line as well as between lines.
+</li>
+<li>MIME type is unspecified, but text/plain is
+ RECOMMENDED.
+</li>
+<li>Character encoding MUST BE UTF-8.
+</li>
+</ul><p>
+
+</p>
+<a name="limits"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.D"></a><h3>Appendix D.&nbsp;Limits</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Identifier URL: 255 max bytes
+</li>
+<li>Identity Provider URL: 2047 max bytes, after Consumer-added
+ URL arguments. The raw endpoint URL SHOULD be kept well
+ below this.
+</li>
+<li>return_to URL: 2047 max bytes, after Identity Provider
+ added URL arguments. The raw return_to URL SHOULD be kept
+ well below this.
+</li>
+<li>assoc_handle: 255 characters or less, and consist only of
+ ASCII characters in the range 33-126 inclusive (ie printable
+ non-whitespace characters).
+</li>
+</ul><p>
+
+</p>
+<a name="anchor33"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.E"></a><h3>Appendix E.&nbsp;Misc</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>Timestamps must be in w3c format, and must be in the UTC
+ timezone, indicated with a "Z". For example:
+ 2005-05-15T17:11:51Z
+</li>
+</ul><p>
+
+</p>
+<a name="rfc.references1"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>6.&nbsp;Normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="RFC2119">[RFC2119]</a></td>
+<td class="author-text">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels.”</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2396">[RFC2396]</a></td>
+<td class="author-text">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax.”</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2631">[RFC2631]</a></td>
+<td class="author-text">Rescorla, E., “Diffie-Hellman Key Agreement Method.”</td></tr>
+</tbody></table>
+
+<a name="rfc.authors"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Authors' Addresses</h3>
+<table border="0" cellpadding="0" cellspacing="0" width="99%">
+<tbody><tr><td class="author-text">&nbsp;</td>
+<td class="author-text">David
+ Recordon</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:drecordon@verisign.com">drecordon@verisign.com</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Brad
+ Fitzpatrick</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:brad@danga.com">brad@danga.com</a></td></tr>
+</tbody></table>
+
+</body></html> \ No newline at end of file
diff --git a/doc/specs/openid-authentication-2_0.html b/doc/specs/openid-authentication-2_0.html
new file mode 100644
index 0000000..3e0afed
--- /dev/null
+++ b/doc/specs/openid-authentication-2_0.html
@@ -0,0 +1,4172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en"><head><title>Final: OpenID Authentication 2.0 - Final</title>
+
+<meta http-equiv="Expires" content="Wed, 05 Dec 2007 17:38:41 +0000">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="description" content="OpenID Authentication 2.0 - Final">
+<meta name="generator" content="xml2rfc v1.32 (http://xml.resource.org/)">
+<style type="text/css"><!--
+ body {
+ font-family: verdana, charcoal, helvetica, arial, sans-serif;
+ font-size: small; color: #000; background-color: #FFF;
+ margin: 2em;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
+ font-weight: bold; font-style: normal;
+ }
+ h1 { color: #900; background-color: transparent; text-align: right; }
+ h3 { color: #333; background-color: transparent; }
+
+ td.RFCbug {
+ font-size: x-small; text-decoration: none;
+ width: 30px; height: 30px; padding-top: 2px;
+ text-align: justify; vertical-align: middle;
+ background-color: #000;
+ }
+ td.RFCbug span.RFC {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: bold; color: #666;
+ }
+ td.RFCbug span.hotText {
+ font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: normal; text-align: center; color: #FFF;
+ }
+
+ table.TOCbug { width: 30px; height: 15px; }
+ td.TOCbug {
+ text-align: center; width: 30px; height: 15px;
+ color: #FFF; background-color: #900;
+ }
+ td.TOCbug a {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
+ font-weight: bold; font-size: x-small; text-decoration: none;
+ color: #FFF; background-color: transparent;
+ }
+
+ td.header {
+ font-family: arial, helvetica, sans-serif; font-size: x-small;
+ vertical-align: top; width: 33%;
+ color: #FFF; background-color: #666;
+ }
+ td.author { font-weight: bold; font-size: x-small; margin-left: 4em; }
+ td.author-text { font-size: x-small; }
+
+ /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
+ a.info {
+ /* This is the key. */
+ position: relative;
+ z-index: 24;
+ text-decoration: none;
+ }
+ a.info:hover {
+ z-index: 25;
+ color: #FFF; background-color: #900;
+ }
+ a.info span { display: none; }
+ a.info:hover span.info {
+ /* The span will display just on :hover state. */
+ display: block;
+ position: absolute;
+ font-size: smaller;
+ top: 2em; left: -5em; width: 15em;
+ padding: 2px; border: 1px solid #333;
+ color: #900; background-color: #EEE;
+ text-align: left;
+ }
+
+ a { font-weight: bold; }
+ a:link { color: #900; background-color: transparent; }
+ a:visited { color: #633; background-color: transparent; }
+ a:active { color: #633; background-color: transparent; }
+
+ p { margin-left: 2em; margin-right: 2em; }
+ p.copyright { font-size: x-small; }
+ p.toc { font-size: small; font-weight: bold; margin-left: 3em; }
+ table.toc { margin: 0 0 0 3em; padding: 0; border: 0; vertical-align: text-top; }
+ td.toc { font-size: small; font-weight: bold; vertical-align: text-top; }
+
+ ol.text { margin-left: 2em; margin-right: 2em; }
+ ul.text { margin-left: 2em; margin-right: 2em; }
+ li { margin-left: 3em; }
+
+ /* RFC-2629 <spanx>s and <artwork>s. */
+ em { font-style: italic; }
+ strong { font-weight: bold; }
+ dfn { font-weight: bold; font-style: normal; }
+ cite { font-weight: normal; font-style: normal; }
+ tt { color: #036; }
+ tt, pre, pre dfn, pre em, pre cite, pre span {
+ font-family: "Courier New", Courier, monospace; font-size: small;
+ }
+ pre {
+ text-align: left; padding: 4px;
+ color: #000; background-color: #CCC;
+ }
+ pre dfn { color: #900; }
+ pre em { color: #66F; background-color: #FFC; font-weight: normal; }
+ pre .key { color: #33C; font-weight: bold; }
+ pre .id { color: #900; }
+ pre .str { color: #000; background-color: #CFF; }
+ pre .val { color: #066; }
+ pre .rep { color: #909; }
+ pre .oth { color: #000; background-color: #FCF; }
+ pre .err { background-color: #FCC; }
+
+ /* RFC-2629 <texttable>s. */
+ table.all, table.full, table.headers, table.none {
+ font-size: small; text-align: center; border-width: 2px;
+ vertical-align: top; border-collapse: collapse;
+ }
+ table.all, table.full { border-style: solid; border-color: black; }
+ table.headers, table.none { border-style: none; }
+ th {
+ font-weight: bold; border-color: black;
+ border-width: 2px 2px 3px 2px;
+ }
+ table.all th, table.full th { border-style: solid; }
+ table.headers th { border-style: none none solid none; }
+ table.none th { border-style: none; }
+ table.all td {
+ border-style: solid; border-color: #333;
+ border-width: 1px 2px;
+ }
+ table.full td, table.headers td, table.none td { border-style: none; }
+
+ hr { height: 1px; }
+ hr.insert {
+ width: 80%; border-style: none; border-width: 0;
+ color: #CCC; background-color: #CCC;
+ }
+--></style></head><body>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<table summary="layout" border="0" cellpadding="0" cellspacing="0" width="66%"><tbody><tr><td><table summary="layout" border="0" cellpadding="2" cellspacing="1" width="100%">
+<tbody><tr><td class="header">Final</td><td class="header"> specs@openid.net</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">December 5, 2007</td></tr>
+</tbody></table></td></tr></tbody></table>
+<h1><br>OpenID Authentication 2.0 - Final</h1>
+
+<h3>Abstract</h3>
+
+<p>
+ OpenID Authentication provides a way to prove that an end user
+ controls an Identifier. It does this without the Relying Party
+ needing access to end user credentials such as a password or
+ to other sensitive information such as an email address.
+
+</p>
+<p>
+ OpenID is decentralized. No central authority must approve or
+ register Relying Parties or OpenID Providers. An end user
+ can freely choose which OpenID Provider to use, and can
+ preserve their Identifier if they switch OpenID Providers.
+
+</p>
+<p>
+ While nothing in the protocol requires JavaScript or modern
+ browsers, the authentication scheme plays nicely with
+ "AJAX"-style setups. This means an end user can prove their
+ Identity to a Relying Party without having to leave their
+ current Web page.
+
+</p>
+<p>
+ OpenID Authentication uses only standard HTTP(S) requests and
+ responses, so it does not require any special capabilities of
+ the User-Agent or other client software. OpenID is not tied to
+ the use of cookies or any other specific mechanism of Relying
+ Party or OpenID Provider session management. Extensions to
+ User-Agents can simplify the end user interaction, though are
+ not required to utilize the protocol.
+
+</p>
+<p>
+ The exchange of profile information, or the exchange of other
+ information not covered in this specification, can be addressed
+ through additional service types built on top of this
+ protocol to create a framework. OpenID Authentication is
+ designed to provide a base service to enable portable,
+ user-centric digital identity in a free and decentralized manner.
+
+</p><a name="toc"></a><br><hr>
+<h3>Table of Contents</h3>
+<p class="toc">
+<a href="#anchor1">1.</a>&nbsp;
+Requirements Notation and Conventions<br>
+<a href="#terminology">2.</a>&nbsp;
+Terminology<br>
+<a href="#anchor2">3.</a>&nbsp;
+Protocol Overview<br>
+<a href="#anchor3">4.</a>&nbsp;
+Data Formats<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor4">4.1.</a>&nbsp;
+Protocol Messages<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#btwoc">4.2.</a>&nbsp;
+Integer Representations<br>
+<a href="#anchor6">5.</a>&nbsp;
+Communication Types<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#direct_comm">5.1.</a>&nbsp;
+Direct Communication<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#indirect_comm">5.2.</a>&nbsp;
+Indirect Communication<br>
+<a href="#generating_signatures">6.</a>&nbsp;
+Generating Signatures<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor11">6.1.</a>&nbsp;
+Procedure<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sign_algos">6.2.</a>&nbsp;
+Signature Algorithms<br>
+<a href="#anchor12">7.</a>&nbsp;
+Initiation and Discovery<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#initiation">7.1.</a>&nbsp;
+Initiation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#normalization">7.2.</a>&nbsp;
+Normalization<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#discovery">7.3.</a>&nbsp;
+Discovery<br>
+<a href="#associations">8.</a>&nbsp;
+Establishing Associations<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor17">8.1.</a>&nbsp;
+Association Session Request<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor20">8.2.</a>&nbsp;
+Association Session Response<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#assoc_types">8.3.</a>&nbsp;
+Association Types<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#assoc_sess_types">8.4.</a>&nbsp;
+Association Session Types<br>
+<a href="#requesting_authentication">9.</a>&nbsp;
+Requesting Authentication<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor27">9.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#realms">9.2.</a>&nbsp;
+Realms<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor28">9.3.</a>&nbsp;
+Immediate Requests<br>
+<a href="#responding_to_authentication">10.</a>&nbsp;
+Responding to Authentication Requests<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#positive_assertions">10.1.</a>&nbsp;
+Positive Assertions<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#negative_assertions">10.2.</a>&nbsp;
+Negative Assertions<br>
+<a href="#verification">11.</a>&nbsp;
+Verifying Assertions<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#verify_return_to">11.1.</a>&nbsp;
+Verifying the Return URL<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#verify_disco">11.2.</a>&nbsp;
+Verifying Discovered Information<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#verify_nonce">11.3.</a>&nbsp;
+Checking the Nonce<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#verifying_signatures">11.4.</a>&nbsp;
+Verifying Signatures<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#identifying">11.5.</a>&nbsp;
+Identifying the end user<br>
+<a href="#extensions">12.</a>&nbsp;
+Extensions<br>
+<a href="#rp_discovery">13.</a>&nbsp;
+Discovering OpenID Relying Parties<br>
+<a href="#compat_mode">14.</a>&nbsp;
+OpenID Authentication 1.1 Compatibility<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor34">14.1.</a>&nbsp;
+Changes from OpenID Authentication 1.1<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor38">14.2.</a>&nbsp;
+Implementing OpenID Authentication 1.1 Compatibility<br>
+<a href="#security_considerations">15.</a>&nbsp;
+Security Considerations<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor41">15.1.</a>&nbsp;
+Preventing Attacks<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor43">15.2.</a>&nbsp;
+User-Agents<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor44">15.3.</a>&nbsp;
+User Interface Considerations<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor45">15.4.</a>&nbsp;
+HTTP and HTTPS URL Identifiers<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor46">15.5.</a>&nbsp;
+Denial of Service Attacks<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor47">15.6.</a>&nbsp;
+Protocol Variants<br>
+<a href="#anchor48">Appendix&nbsp;A.</a>&nbsp;
+Examples<br>
+<a href="#normalization_example">Appendix&nbsp;A.1.</a>&nbsp;
+Normalization<br>
+<a href="#anchor49">Appendix&nbsp;A.2.</a>&nbsp;
+OP-Local Identifiers<br>
+<a href="#XRDS_Sample">Appendix&nbsp;A.3.</a>&nbsp;
+XRDS<br>
+<a href="#anchor50">Appendix&nbsp;A.4.</a>&nbsp;
+HTML Identifier Markup<br>
+<a href="#anchor51">Appendix&nbsp;A.5.</a>&nbsp;
+XRI CanonicalID<br>
+<a href="#pvalue">Appendix&nbsp;B.</a>&nbsp;
+Diffie-Hellman Key Exchange Default Value<br>
+<a href="#anchor52">Appendix&nbsp;C.</a>&nbsp;
+Acknowledgements<br>
+<a href="#rfc.references1">16.</a>&nbsp;
+Normative References<br>
+<a href="#rfc.authors">§</a>&nbsp;
+Author's Address<br>
+</p>
+<br clear="all">
+
+<a name="anchor1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1"></a><h3>1.&nbsp;
+Requirements Notation and Conventions</h3>
+
+<p>
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
+ "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" in this document are to be interpreted as
+ described in <a class="info" href="#RFC2119">[RFC2119]<span> (</span><span class="info">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels,” .</span><span>)</span></a>.
+
+</p>
+<p>
+ Throughout this document, values are quoted to indicate that
+ they are to be taken literally. When using these values in
+ protocol messages, the quotes MUST NOT be used as part of the
+ value.
+
+</p>
+<a name="terminology"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.2"></a><h3>2.&nbsp;
+Terminology</h3>
+
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>Identifier:</dt>
+<dd>
+ An Identifier is either a "http" or "https" URI, (commonly
+ referred to as a "URL" within this document), or an <a class="info" href="#XRI_Syntax_2.0">XRI<span> (</span><span class="info">Reed, D. and D. McAlpin, “Extensible Resource Identifier (XRI) Syntax V2.0,” .</span><span>)</span></a> [XRI_Syntax_2.0]. This document defines
+ various kinds of Identifiers, designed for use in different
+ contexts.
+
+</dd>
+<dt>User-Agent:</dt>
+<dd>
+ The end user's Web browser which implements HTTP/1.1 <a class="info" href="#RFC2616">[RFC2616]<span> (</span><span class="info">Fielding,
+R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T.
+Berners-Lee, “Hypertext Transfer Protocol -- HTTP/1.1,” .</span><span>)</span></a>.
+
+</dd>
+<dt>Relying Party:</dt>
+<dd>
+ RP. A Web application that wants proof that the end user
+ controls an Identifier.
+
+</dd>
+<dt>OpenID Provider:</dt>
+<dd>
+ OP. An OpenID Authentication server on which a Relying
+ Party relies for an assertion that the end user controls
+ an Identifier.
+
+</dd>
+<dt>OP Endpoint URL:</dt>
+<dd>
+ The URL which accepts OpenID Authentication protocol messages,
+ obtained by performing discovery on the User-Supplied
+ Identifier. This value MUST be an absolute HTTP or HTTPS URL.
+
+</dd>
+<dt>OP Identifier:</dt>
+<dd>
+ An Identifier for an OpenID Provider.
+
+</dd>
+<dt>User-Supplied Identifier:</dt>
+<dd>
+ An Identifier that was presented by the end user to the
+ Relying Party, or selected by the user at the OpenID
+ Provider. During the initiation phase of the protocol,
+ an end user may enter either their own Identifier or an OP
+ Identifier. If an OP Identifier is used, the OP may then
+ assist the end user in selecting an Identifier to share with
+ the Relying Party.
+
+</dd>
+<dt>Claimed Identifier:</dt>
+<dd>
+ An Identifier that the end user claims to own; the overall
+ aim of the protocol is verifying this claim. The Claimed
+ Identifier is either:
+
+<ul class="text">
+<li>
+ The Identifier obtained by <a class="info" href="#normalization">normalizing<span> (</span><span class="info">Normalization</span><span>)</span></a> the User-Supplied Identifier, if it
+ was an URL.
+
+</li>
+<li>
+ The <a class="info" href="#canonicalid">CanonicalID<span> (</span><span class="info">XRI and the CanonicalID Element</span><span>)</span></a>, if it
+ was an XRI.
+
+</li>
+</ul>
+
+</dd>
+<dt>OP-Local Identifier:</dt>
+<dd>
+ An alternate Identifier for an end user that is local to a
+ particular OP and thus not necessarily under the end user's
+ control.
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor2"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3"></a><h3>3.&nbsp;
+Protocol Overview</h3>
+
+<p>
+ </p>
+<ol class="text">
+<li>
+ The end user <a class="info" href="#initiation">initiates
+ authentication<span> (</span><span class="info">Initiation</span><span>)</span></a> by presenting a User-Supplied Identifier
+ to the Relying Party via their User-Agent.
+
+</li>
+<li>
+ After <a class="info" href="#normalization">normalizing<span> (</span><span class="info">Normalization</span><span>)</span></a> the
+ User-Supplied Identifier, the Relying Party <a class="info" href="#discovery">performs discovery<span> (</span><span class="info">Discovery</span><span>)</span></a> on it and
+ establishes the OP Endpoint URL that the end user uses for
+ authentication. It should be noted that the User-Supplied
+ Identifier may be an OP Identifier, as discussed in <a class="info" href="#discovered_info">Section&nbsp;7.3.1<span> (</span><span class="info">Discovered Information</span><span>)</span></a>, which allows selection of a
+ Claimed Identifier at the OP or for the protocol to
+ proceed without a Claimed Identifier if something else
+ useful is being done via an <a class="info" href="#extensions">extension<span> (</span><span class="info">Extensions</span><span>)</span></a>.
+
+</li>
+<li>
+ (optional)
+
+ The Relying Party and the OP establish an <a class="info" href="#associations">association<span> (</span><span class="info">Establishing Associations</span><span>)</span></a> -- a shared
+ secret established using <a class="info" href="#RFC2631">Diffie-Hellman Key Exchange<span> (</span><span class="info">Rescorla, E., “Diffie-Hellman Key Agreement Method,” .</span><span>)</span></a> [RFC2631]. The
+ OP uses an association to sign subsequent messages and the
+ Relying Party to verify those messages; this removes the
+ need for subsequent direct requests to verify the
+ signature after each authentication request/response.
+
+</li>
+<li>
+ The Relying Party redirects the end user's User-Agent to
+ the OP with an OpenID <a class="info" href="#requesting_authentication">Authentication
+ request<span> (</span><span class="info">Requesting Authentication</span><span>)</span></a>.
+
+</li>
+<li>
+ The OP establishes whether the end user is authorized to
+ perform OpenID Authentication and wishes to do so. The
+ manner in which the end user authenticates to their OP and
+ any policies surrounding such authentication is out of
+ scope for this document.
+
+</li>
+<li>
+ The OP redirects the end user's User-Agent back to the
+ Relying Party with either an assertion that <a class="info" href="#positive_assertions">authentication is
+ approved<span> (</span><span class="info">Positive Assertions</span><span>)</span></a> or a message that <a class="info" href="#negative_assertions">authentication failed<span> (</span><span class="info">Negative Assertions</span><span>)</span></a>.
+
+</li>
+<li>
+ The Relying Party <a class="info" href="#verification">verifies<span> (</span><span class="info">Verifying Assertions</span><span>)</span></a> the information received from the OP including
+ checking the Return URL, verifying the discovered
+ information, checking the nonce, and verifying the
+ signature by using either the shared key established
+ during the association or by sending a direct request
+ to the OP.
+
+</li>
+</ol><p>
+
+</p>
+<a name="anchor3"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4"></a><h3>4.&nbsp;
+Data Formats</h3>
+
+<a name="anchor4"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1"></a><h3>4.1.&nbsp;
+Protocol Messages</h3>
+
+<p>
+ The OpenID Authentication protocol messages are
+ mappings of plain-text keys to plain-text values. The keys and
+ values permit the full Unicode character set (UCS). When the
+ keys and values need to be converted to/from bytes, they
+ MUST be encoded using <a class="info" href="#RFC3629">UTF-8<span> (</span><span class="info">Yergeau, F., “UTF-8, a transformation format of Unicode and ISO 10646,” .</span><span>)</span></a> [RFC3629].
+
+</p>
+<p>
+ Messages MUST NOT contain multiple parameters with the same name.
+
+</p>
+<p>
+ Throughout this document, all OpenID message parameters are
+ REQUIRED, unless specifically marked as OPTIONAL.
+
+</p>
+<a name="kvform"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.1"></a><h3>4.1.1.&nbsp;
+Key-Value Form Encoding</h3>
+
+<p>
+ A message in Key-Value form is a sequence of lines. Each
+ line begins with a key, followed by a colon, and the value
+ associated with the key. The line is terminated by a
+ single newline (UCS codepoint 10, "\n"). A key or value
+ MUST NOT contain a newline and a key also MUST NOT contain
+ a colon.
+
+</p>
+<p>
+ Additional characters, including whitespace, MUST NOT be
+ added before or after the colon or newline. The message
+ MUST be encoded in UTF-8 to produce a byte string.
+
+</p>
+<p>
+ Key-Value Form encoding is used for signature calculation
+ and for <a class="info" href="#direct_response">direct
+ responses<span> (</span><span class="info">Direct Response</span><span>)</span></a> to Relying Parties.
+
+</p>
+<a name="http_encoding"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.2"></a><h3>4.1.2.&nbsp;
+HTTP Encoding</h3>
+
+<p>
+ When a message is sent to an HTTP server, it MUST be encoded
+ using a form encoding specified in Section 17.13.4 of
+ <a class="info" href="#HTML401">[HTML401]<span> (</span><span class="info">W3C, “HTML 4.01 Specification,” .</span><span>)</span></a>. Likewise, if the "Content-Type"
+ header is included in the request headers, its value MUST
+ also be such an encoding.
+
+</p>
+<p>
+ All of the keys in the request message MUST be prefixed
+ with "openid.". This prefix prevents interference with
+ other parameters that are passed along with the OpenID
+ Authentication message. When a message is sent as a POST,
+ OpenID parameters MUST only be sent in, and extracted
+ from, the POST body.
+
+</p>
+<p>
+ All messages that are sent as HTTP requests (GET or POST)
+ MUST contain the following fields:
+
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ Value: "http://specs.openid.net/auth/2.0"
+
+</p>
+<p>
+ This particular value MUST be present for the
+ request to be a valid OpenID Authentication 2.0
+ request. Future versions of the specification may
+ define different values in order to allow message
+ recipients to properly interpret the request.
+
+</p>
+<p>
+ If this value is absent or set to one of
+ "http://openid.net/signon/1.1" or
+ "http://openid.net/signon/1.0", then this message
+ SHOULD be interpreted using <a class="info" href="#compat_mode">OpenID Authentication 1.1
+ Compatibility mode<span> (</span><span class="info">OpenID Authentication 1.1 Compatibility</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>
+ Value: Specified individually for each message
+ type.
+
+</p>
+<p>
+ The "openid.mode" parameter allows the recipient
+ of the message to know what kind of message it is
+ processing. If "openid.mode" is absent, the party
+ processing the message SHOULD assume that the
+ request is not an OpenID message.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ This model applies to messages from the User-Agent to both
+ the Relying Party and the OP, as well as messages from the
+ Relying Party to the OP.
+
+</p>
+<a name="anchor5"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.1.3"></a><h3>4.1.3.&nbsp;
+Example</h3>
+
+<p>
+ Non-normative
+
+</p>
+<p>
+ The following examples encode the following information:
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>Key | Value
+--------+---------------------------
+mode | error
+error | This is an example message
+
+</pre></div>
+<p>
+ Key-Value Form encoded:
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>mode:error
+error:This is an example message
+
+</pre></div>
+<p>
+ x-www-urlencoded, as in a HTTP POST body or in a URL's
+ query string (<a class="info" href="#RFC3986">[RFC3986]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a> section 3):
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>openid.mode=error&amp;openid.error=This%20is%20an%20example%20message</pre></div>
+<a name="btwoc"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4.2"></a><h3>4.2.&nbsp;
+Integer Representations</h3>
+
+<p>
+ Arbitrary precision integers MUST be encoded as big-endian
+ signed two's complement binary strings. Henceforth, "btwoc"
+ is a function that takes an arbitrary precision integer and
+ returns its shortest big-endian two's complement
+ representation. All integers that are used with
+ Diffie-Hellman Key Exchange are positive. This means that
+ the left-most bit of the two's complement representation
+ MUST be zero. If it is not, implementations MUST add a zero
+ byte at the front of the string.
+
+</p>
+<p>Non-normative example:
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>Base 10 number | btwoc string representation
+---------------+----------------------------
+0 | "\x00"
+127 | "\x7F"
+128 | "\x00\x80"
+255 | "\x00\xFF"
+32768 | "\x00\x80\x00"
+</pre></div>
+<a name="anchor6"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5"></a><h3>5.&nbsp;
+Communication Types</h3>
+
+<a name="direct_comm"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1"></a><h3>5.1.&nbsp;
+Direct Communication</h3>
+
+<p>
+ Direct communication is initiated by a Relying Party to an
+ OP endpoint URL. It is used for <a class="info" href="#associations">establishing associations<span> (</span><span class="info">Establishing Associations</span><span>)</span></a> and
+ <a class="info" href="#check_auth">verifying authentication
+ assertions<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>.
+
+</p>
+<a name="direct_request"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1.1"></a><h3>5.1.1.&nbsp;
+Direct Request</h3>
+
+<p>
+ The message MUST be encoded as a POST body, as specified
+ by <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+<p>
+ All direct requests are HTTP POSTs, and so
+ contain the required fields listed in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+<a name="direct_response"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1.2"></a><h3>5.1.2.&nbsp;
+Direct Response</h3>
+
+<p>
+ The body of a response to a <a class="info" href="#direct_request">Direct Request<span> (</span><span class="info">Direct Request</span><span>)</span></a> consists of
+ an HTTP Response body in <a class="info" href="#kvform">Key-Value
+ Form<span> (</span><span class="info">Key-Value Form Encoding</span><span>)</span></a>. The content-type of the response SHOULD be
+ "text/plain".
+
+</p>
+<p>
+ All Key-Value form message MUST contain the following field:
+
+ </p>
+<ul class="text">
+<li>
+ ns
+
+<blockquote class="text">
+<p>
+ Value: "http://specs.openid.net/auth/2.0"
+
+</p>
+<p>
+ This particular value MUST be present for the
+ response to be a valid OpenID 2.0 response. Future
+ versions of the specification may define different
+ values in order to allow message recipients to
+ properly interpret the request.
+
+</p>
+<p>
+ If this value is absent or set to one of
+ "http://openid.net/signon/1.1" or
+ "http://openid.net/signon/1.0", then this message
+ SHOULD be interpreted using <a class="info" href="#compat_mode">OpenID Authentication 1.1
+ Compatibility mode<span> (</span><span class="info">OpenID Authentication 1.1 Compatibility</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor7"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1.2.1"></a><h3>5.1.2.1.&nbsp;
+Successful Responses</h3>
+
+<p>
+ A server receiving a valid request MUST send a
+ response with an HTTP status code of 200.
+
+</p>
+<a name="anchor8"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1.2.2"></a><h3>5.1.2.2.&nbsp;
+Error Responses</h3>
+
+<p>
+ If a request is malformed or contains invalid arguments,
+ the server MUST send a response with a status code of
+ 400. The response body MUST be a <a class="info" href="#kvform">Key-Value Form<span> (</span><span class="info">Key-Value Form Encoding</span><span>)</span></a> message with the
+ following fields:
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#direct_response">Section&nbsp;5.1.2<span> (</span><span class="info">Direct Response</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ error
+
+<blockquote class="text">
+<p>
+ Value: A human-readable message indicating the cause
+ of the error.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ contact
+
+<blockquote class="text">
+<p>
+ Value: (optional) Contact address for the
+ administrator of the sever. The contact address
+ may take any form, as it is intended to be
+ displayed to a person.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ reference
+
+<blockquote class="text">
+<p>
+ Value: (optional) A reference token, such
+ as a support ticket number or a URL to a news
+ blog, etc.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+ The OP MAY add additional fields to this response.
+
+</p>
+<a name="indirect_comm"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2"></a><h3>5.2.&nbsp;
+Indirect Communication</h3>
+
+<p>
+ In indirect communication, messages are passed through the
+ User-Agent. This can be initiated by either the Relying
+ Party or the OP. Indirect communication is used for <a class="info" href="#requesting_authentication">authentication
+ requests<span> (</span><span class="info">Requesting Authentication</span><span>)</span></a> and <a class="info" href="#responding_to_authentication">authentication
+ responses<span> (</span><span class="info">Responding to Authentication Requests</span><span>)</span></a>.
+
+</p>
+<p>
+ There are two methods for indirect communication: HTTP
+ redirects and HTML form submission.
+ Both form submission and redirection require that the sender
+ know a recipient URL and that the recipient URL expect
+ indirect messages, as specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>. The initiator of the communication chooses which method
+ of indirect communication is appropriate depending on
+ capabilities, message size, or other external factors.
+
+</p>
+<p>
+ All indirect messages arrive as HTTP requests, and so
+ contain the required fields listed in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+<a name="anchor9"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2.1"></a><h3>5.2.1.&nbsp;
+HTTP Redirect</h3>
+
+<p>
+ Data can be transferred by issuing a 302, 303, or 307 HTTP
+ Redirect to the end user's User-Agent. The redirect URL is
+ the URL of the receiver with the OpenID Authentication
+ message appended to the query string, as specified in
+ <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+<a name="anchor10"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2.2"></a><h3>5.2.2.&nbsp;
+HTML FORM Redirection</h3>
+
+<p>
+ A mapping of keys to values can be transferred by
+ returning an HTML page to the User-Agent that contains an
+ HTML form element. Form submission MAY be automated,
+ for example by using JavaScript.
+
+</p>
+<p>
+ The &lt;form&gt; element's "action" attribute value MUST
+ be the URL of the receiver. Each Key-Value pair MUST be
+ included in the form as an &lt;input&gt; element. The key
+ MUST be encoded as the "name" attribute and the value as
+ the "value" attribute, such that the User-Agent will
+ generate a message as specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a> when the form is submitted. The
+ form MUST include a submit button.
+
+</p>
+<a name="indirect_error"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2.3"></a><h3>5.2.3.&nbsp;
+Indirect Error Responses</h3>
+
+<p>
+ In the case of a malformed request, or one that contains
+ invalid arguments, the OpenID Provider MUST redirect the
+ User-Agent to the "openid.return_to" URL value if the
+ value is present and it is a valid URL.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>
+ Value: "error"
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.error
+
+<blockquote class="text">
+<p>
+ Value: A human-readable message indicating the cause
+ of the error.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.contact
+
+<blockquote class="text">
+<p>
+ Value: (optional) Contact address for the
+ administrator of the sever. The contact address
+ may take any form, as it is intended to be
+ displayed to a person.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.reference
+
+<blockquote class="text">
+<p>
+ Value: (optional) A reference token, such as a
+ support ticket number or a URL to a news blog,
+ etc.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+ The server MAY add additional keys to this response.
+
+</p>
+<p>
+ If the malformed or invalid message is received by the Relying
+ Party, or "openid.return_to" is not present or its value is not
+ a valid URL, the server SHOULD return a response to the
+ end user indicating the error and that it is unable to continue.
+
+</p>
+<a name="generating_signatures"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6"></a><h3>6.&nbsp;
+Generating Signatures</h3>
+
+<p>
+ The most common usage of an association is as a Message
+ Authentication Code (MAC) key used to sign OpenID
+ Authentication messages.
+
+</p>
+<p>
+ When generating MAC keys, the recommendations in <a class="info" href="#RFC1750">[RFC1750]<span> (</span><span class="info">Eastlake, D., Crocker, S., and J. Schiller, “Randomness Recommendations for Security,” .</span><span>)</span></a> SHOULD be followed.
+
+</p>
+<a name="anchor11"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.1"></a><h3>6.1.&nbsp;
+Procedure</h3>
+
+<p>
+ To generate a message signature:
+
+ </p>
+<ol class="text">
+<li>
+ Determine the list of keys to be signed, according to
+ the message to be signed (See <a class="info" href="#positive_assertions">Section&nbsp;10.1<span> (</span><span class="info">Positive Assertions</span><span>)</span></a>). The list of keys to be
+ signed MUST be part of the message. The list is stored
+ with the key "openid.signed". The value is a
+ comma-separated list of keys, with the "openid." prefix
+ stripped. This algorithm is only capable of signing keys
+ that start with "openid."
+
+</li>
+<li>
+ Iterate through the list of keys to be signed in the
+ order they appear in "openid.signed" list. For each
+ key, find the value in the message whose key is equal to
+ the signed list key prefixed with "openid."
+
+</li>
+<li>
+ Convert the list of key/value pairs to be signed to an
+ octet string by encoding with <a class="info" href="#kvform">Key-Value Form Encoding<span> (</span><span class="info">Key-Value Form Encoding</span><span>)</span></a>.
+
+</li>
+<li>
+ Determine the signature algorithm from the <a class="info" href="#associations">association type<span> (</span><span class="info">Establishing Associations</span><span>)</span></a>. Apply
+ the <a class="info" href="#sign_algos">signature algorithm<span> (</span><span class="info">Signature Algorithms</span><span>)</span></a>
+ to the octet string.
+
+</li>
+</ol><p>
+
+</p>
+<a name="sign_algos"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.2"></a><h3>6.2.&nbsp;
+Signature Algorithms</h3>
+
+<p>
+ OpenID Authentication supports two signature algorithms:
+
+ </p>
+<ul class="text">
+<li>HMAC-SHA1 - 160 bit key length (<a class="info" href="#RFC2104">[RFC2104]<span> (</span><span class="info">Krawczyk, H., Bellare, M., and R. Canetti, “HMAC: Keyed-Hashing for Message Authentication,” .</span><span>)</span></a> and <a class="info" href="#RFC3174">[RFC3174]<span> (</span><span class="info">Eastlake, D. and P. Jones, “US Secure Hash Algorithm 1 (SHA1),” .</span><span>)</span></a>)
+</li>
+<li>HMAC-SHA256 - 256 bit key length (<a class="info" href="#RFC2104">[RFC2104]<span> (</span><span class="info">Krawczyk, H., Bellare, M., and R. Canetti, “HMAC: Keyed-Hashing for Message Authentication,” .</span><span>)</span></a> and <a class="info" href="#FIPS180-2">[FIPS180‑2]<span> (</span><span class="info">U.S.
+Department of Commerce and National Institute of Standards and
+Technology, “Secure Hash Signature Standard,” .</span><span>)</span></a>
+</li>
+</ul><p>
+
+ If supported, the use of HMAC-SHA256 is RECOMMENDED.
+
+</p>
+<a name="anchor12"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7"></a><h3>7.&nbsp;
+Initiation and Discovery</h3>
+
+<a name="initiation"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.1"></a><h3>7.1.&nbsp;
+Initiation</h3>
+
+<p>
+ To initiate OpenID Authentication, the Relying Party SHOULD
+ present the end user with a form that has a field for
+ entering a User-Supplied Identifier.
+
+</p>
+<p>
+ The form field's "name" attribute SHOULD have the value
+ "openid_identifier", so that User-Agents can automatically
+ determine that this is an OpenID form. Browser extensions or
+ other software that support OpenID Authentication may not
+ detect a Relying Party's support if this attribute is not
+ set appropriately.
+
+</p>
+<a name="normalization"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.2"></a><h3>7.2.&nbsp;
+Normalization</h3>
+
+<p>
+ The end user's input MUST be normalized into an
+ Identifier, as follows:
+
+</p>
+<p>
+ </p>
+<ol class="text">
+<li>
+ If the user's input starts with the "xri://" prefix,
+ it MUST be stripped off, so that XRIs are used in the
+ canonical form.
+
+</li>
+<li>
+ If the first character of the resulting string is an
+ XRI Global Context Symbol ("=", "@", "+", "$", "!") or "(", as
+ defined in Section 2.2.1 of <a class="info" href="#XRI_Syntax_2.0">[XRI_Syntax_2.0]<span> (</span><span class="info">Reed, D. and D. McAlpin, “Extensible Resource Identifier (XRI) Syntax V2.0,” .</span><span>)</span></a>,
+ then the input SHOULD be treated as an XRI.
+
+</li>
+<li>
+ Otherwise, the input SHOULD be treated as an http URL; if it
+ does not include a "http" or "https" scheme, the Identifier
+ MUST be prefixed with the string "http://". If the URL
+ contains a fragment part, it MUST be stripped off
+ together with the fragment delimiter character "#". See
+ <a class="info" href="#http_s_identifiers">Section&nbsp;11.5.2<span> (</span><span class="info">HTTP and HTTPS URL Identifiers</span><span>)</span></a> for more information.
+
+</li>
+<li>
+ URL Identifiers MUST then be further normalized by both
+ following redirects when retrieving their content and
+ finally applying the rules in Section 6 of <a class="info" href="#RFC3986">[RFC3986]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a> to the final destination URL. This
+ final URL MUST be noted by the Relying Party as the
+ Claimed Identifier and be used when <a class="info" href="#requesting_authentication">requesting
+ authentication<span> (</span><span class="info">Requesting Authentication</span><span>)</span></a>.
+
+</li>
+</ol><p>
+
+ See <a class="info" href="#normalization_example">normalization
+ example<span> (</span><span class="info">Normalization</span><span>)</span></a>.
+
+
+</p>
+<a name="discovery"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3"></a><h3>7.3.&nbsp;
+Discovery</h3>
+
+<p>
+ Discovery is the process where the Relying Party uses the
+ Identifier to look up ("discover") the necessary information
+ for initiating requests. OpenID Authentication has three
+ paths through which to do discovery:
+
+</p>
+<p>
+ </p>
+<ol class="text">
+<li>
+ If the identifier is an XRI, <a class="info" href="#XRI_Resolution_2.0">[XRI_Resolution_2.0]<span> (</span><span class="info">Wachob,
+G., Reed, D., Chasen, L., Tan, W., and S. Churchill, “Extensible
+Resource Identifier (XRI) Resolution V2.0 - Committee Draft 02,” .</span><span>)</span></a>
+ will yield an XRDS document that
+ contains the necessary information. It should also be
+ noted that Relying Parties can take advantage of
+ XRI Proxy Resolvers, such as the one provided by
+ XDI.org at http://www.xri.net. This will remove the need for the RPs to
+ perform XRI Resolution locally.
+
+</li>
+<li>
+ If it is a URL, the <a class="info" href="#Yadis">Yadis
+ protocol<span> (</span><span class="info">Miller, J., “Yadis Specification 1.0,” .</span><span>)</span></a> [Yadis] SHALL be first attempted. If it
+ succeeds, the result is again an XRDS document.
+
+</li>
+<li>
+ If the Yadis protocol fails and no valid XRDS document
+ is retrieved, or no <a class="info" href="#service_elements">Service Elements<span> (</span><span class="info">OpenID Service Elements</span><span>)</span></a> are
+ found in the XRDS document, the URL is retrieved and
+ <a class="info" href="#html_disco">HTML-Based discovery<span> (</span><span class="info">HTML-Based Discovery</span><span>)</span></a>
+ SHALL be attempted.
+
+</li>
+</ol><p>
+
+</p>
+<a name="discovered_info"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.1"></a><h3>7.3.1.&nbsp;
+Discovered Information</h3>
+
+<p>
+ Upon successful completion of discovery, the Relying Party
+ will have one or more sets of the following information
+ (see the <a class="info" href="#terminology">Terminology
+ section<span> (</span><span class="info">Terminology</span><span>)</span></a> for definitions). If more than one set of
+ the following information has been discovered, the
+ precedence rules defined in <a class="info" href="#XRI_Resolution_2.0">[XRI_Resolution_2.0]<span> (</span><span class="info">Wachob,
+G., Reed, D., Chasen, L., Tan, W., and S. Churchill, “Extensible
+Resource Identifier (XRI) Resolution V2.0 - Committee Draft 02,” .</span><span>)</span></a>
+ are to be applied.
+
+ </p>
+<ul class="text">
+<li>OP Endpoint URL
+</li>
+<li>Protocol Version
+</li>
+</ul><p>
+
+ If the end user did not enter an OP Identifier, the
+ following information will also be present:
+
+ </p>
+<ul class="text">
+<li>Claimed Identifier
+</li>
+<li>OP-Local Identifier
+</li>
+</ul><p>
+
+ If the end user entered an OP Identifier, there is no
+ Claimed Identifier. For the purposes of making OpenID
+ Authentication requests, the value
+ "http://specs.openid.net/auth/2.0/identifier_select"
+ MUST be used as both the Claimed Identifier and the
+ OP-Local Identifier when an OP Identifier is entered.
+
+</p>
+<a name="anchor13"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2"></a><h3>7.3.2.&nbsp;
+XRDS-Based Discovery</h3>
+
+<p>
+ If XRI or Yadis discovery was used, the result will be an
+ XRDS Document. This is an XML document with entries for
+ services that are related to the Identifier. It is
+ defined in <a class="info" href="#XRI_Resolution_2.0">Section 3
+ of<span> (</span><span class="info">Wachob,
+G., Reed, D., Chasen, L., Tan, W., and S. Churchill, “Extensible
+Resource Identifier (XRI) Resolution V2.0 - Committee Draft 02,” .</span><span>)</span></a> [XRI_Resolution_2.0]. See <a class="info" href="#XRDS_Sample">Appendix&nbsp;A.3<span> (</span><span class="info">XRDS</span><span>)</span></a> for an
+ example XRDS document.
+
+</p>
+<a name="service_elements"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.1"></a><h3>7.3.2.1.&nbsp;
+OpenID Service Elements</h3>
+
+<a name="anchor14"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.1.1"></a><h3>7.3.2.1.1.&nbsp;
+OP Identifier Element</h3>
+
+<p>
+ An OP Identifier Element is an &lt;xrd:Service&gt;
+ element with the following information:
+
+ </p>
+<blockquote class="text"><dl>
+<dt></dt>
+<dd>
+ An &lt;xrd:Type&gt; tag whose text content is
+ "http://specs.openid.net/auth/2.0/server".
+
+</dd>
+<dt></dt>
+<dd>
+ An &lt;xrd:URI&gt; tag whose text content is the
+ OP Endpoint URL
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor15"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.1.2"></a><h3>7.3.2.1.2.&nbsp;
+Claimed Identifier Element</h3>
+
+<p>
+ A Claimed Identifier Element is an
+ &lt;xrd:Service&gt; element with the following
+ information:
+
+ </p>
+<blockquote class="text"><dl>
+<dt></dt>
+<dd>
+ An &lt;xrd:Type&gt; tag whose text content is
+ "http://specs.openid.net/auth/2.0/signon".
+
+</dd>
+<dt></dt>
+<dd>
+ An &lt;xrd:URI&gt; tag whose text content is the
+ OP Endpoint URL.
+
+</dd>
+<dt></dt>
+<dd>
+ An &lt;xrd:LocalID&gt; tag (optional) whose text
+ content is the OP-Local Identifier.
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="extracting_auth"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.2"></a><h3>7.3.2.2.&nbsp;
+Extracting Authentication Data</h3>
+
+<p>
+ Once the Relying Party has obtained an XRDS document, it
+ MUST first search the document (following the rules
+ described in <a class="info" href="#XRI_Resolution_2.0">[XRI_Resolution_2.0]<span> (</span><span class="info">Wachob,
+G., Reed, D., Chasen, L., Tan, W., and S. Churchill, “Extensible
+Resource Identifier (XRI) Resolution V2.0 - Committee Draft 02,” .</span><span>)</span></a>) for
+ an OP Identifier Element. If none is found, the RP will search
+ for a Claimed Identifier Element.
+
+</p>
+<a name="canonicalid"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.3"></a><h3>7.3.2.3.&nbsp;
+XRI and the CanonicalID Element</h3>
+
+<p>
+ When the Identifier is an XRI, the &lt;xrd:XRD&gt;
+ element that contains the OpenID Authentication
+ &lt;xrd:Service&gt; element MUST also contain a
+ &lt;CanonicalID&gt; element. The content of this element
+ MUST be used as the Claimed Identifier (see <a class="info" href="#identifying">Section&nbsp;11.5<span> (</span><span class="info">Identifying the end user</span><span>)</span></a>). This is a vital security
+ consideration because a primary purpose of the
+ &lt;CanonicalID&gt; element is to assert a persistent
+ identifier that will never be reassigned, thus
+ preventing the possibility of an XRI being ("taken
+ over") by a new registrant.
+
+</p>
+<p>
+ The Relying Party MUST confirm that the provider of the
+ XRD that contains the &lt;CanonicalID&gt; element is
+ authoritative for that Canonical ID and that this XRDS
+ document is authoritative for the OpenID Service
+ Element. Relying Parties should either do this manually
+ or ensure that their resolver does this.
+
+</p>
+<p>
+ When using XRI resolution, the Canonical ID MUST be
+ used as the Claimed Identifier. For an XRI to be a
+ valid Identifier, both the &lt;ProviderID&gt; and
+ &lt;CanonicalID&gt; MUST be present in the discovered
+ XRDS document.
+
+</p>
+<p>
+ When using URL Identifiers, the CanonicalID
+ element MUST be ignored if present.
+
+</p>
+<a name="anchor16"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.2.4"></a><h3>7.3.2.4.&nbsp;
+Additional Information</h3>
+
+<p>
+ The "openid" namespace is no longer used as of OpenID
+ Authentication 2.0. The "xrd" namespace is
+ "xri://$xrd*($v*2.0)".
+
+</p>
+<p>
+ For compatibility with deployed code, it is RECOMMENDED
+ that Relying Parties also accept
+ "http://openid.net/signon/1.0" or
+ "http://openid.net/signon/1.1" for the value of
+ &lt;xrd:Type&gt;, as described in the <a class="info" href="#compat_mode">OpenID Authentication 1.1
+ Compatibility mode<span> (</span><span class="info">OpenID Authentication 1.1 Compatibility</span><span>)</span></a> section. It is RECOMMENDED
+ that Relying Parties supporting OpenID Authentication
+ 2.0 choose to use, if available, endpoints with the type
+ "http://specs.openid.net/auth/2.0/server" and
+ "http://specs.openid.net/auth/2.0/signon", in
+ this order, as specified in <a class="info" href="#extracting_auth">Section&nbsp;7.3.2.2<span> (</span><span class="info">Extracting Authentication Data</span><span>)</span></a>
+
+</p>
+<p>
+ If an OP supports extensions (<a class="info" href="#extensions">Section&nbsp;12<span> (</span><span class="info">Extensions</span><span>)</span></a>), the extensions SHOULD be listed as additional
+ &lt;xrd:Type&gt; child elements of the
+ &lt;xrd:Service&gt; element.
+
+</p>
+<a name="html_disco"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.7.3.3"></a><h3>7.3.3.&nbsp;
+HTML-Based Discovery</h3>
+
+<p>
+ HTML-Based discovery MUST be supported by Relying
+ Parties. HTML-Based discovery is only usable for discovery
+ of Claimed Identifiers. OP Identifiers must be XRIs or
+ URLs that support XRDS discovery.
+
+</p>
+<p>
+ To use HTML-Based discovery, an HTML document MUST be
+ available at the URL of the Claimed Identifier. Within the
+ HEAD element of the document:
+
+ </p>
+<blockquote class="text">
+<p>
+ A LINK element MUST be included with attributes
+ "rel" set to "openid2.provider" and "href" set to an OP
+ Endpoint URL
+
+</p>
+<p>
+ A LINK element MAY be included with attributes
+ "rel" set to "openid2.local_id" and "href" set to the
+ end user's OP-Local Identifier
+
+</p>
+</blockquote><p>
+
+</p>
+<p>
+ The protocol version when HTML discovery is performed is
+ "http://specs.openid.net/auth/2.0/signon".
+
+</p>
+<p>
+ The host of the HTML document MAY be different from the
+ end user's OP's host.
+
+</p>
+<p>
+ The "openid2.provider" and "openid2.local_id" URLs MUST NOT
+ include entities other than "&amp;amp;", "&amp;lt;",
+ "&amp;gt;", and "&amp;quot;". Other characters that would
+ not be valid in the HTML document or that cannot be
+ represented in the document's character encoding MUST be
+ escaped using the percent-encoding (%xx) mechanism
+ described in <a class="info" href="#RFC3986">[RFC3986]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a>.
+
+</p>
+<p>
+ As discussed in the <a class="info" href="#compat_mode">OpenID Authentication 1.1
+ Compatibility mode<span> (</span><span class="info">OpenID Authentication 1.1 Compatibility</span><span>)</span></a> section, these discovery tags
+ are not the same as in previous versions of the protocol.
+ While the same data is conveyed, the names have changed which
+ allows a Relying Party to determine the protocol version
+ being used. A Relying Party MAY encounter a Claimed Identifier
+ which uses HTML-Based Discovery to advertise both version 1.1
+ and 2.0 Providers.
+
+</p>
+<a name="associations"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8"></a><h3>8.&nbsp;
+Establishing Associations</h3>
+
+<p>
+ An association between the Relying Party and the OpenID Provider
+ establishes a shared secret between them, which is used to verify
+ subsequent protocol messages and reduce round trips.
+
+</p>
+<p>
+ It is RECOMMENDED that a Relying Party form associations if it
+ is possible for it to do so. If a Relying Party is incapable
+ of creating or storing associations, <a class="info" href="#check_auth">Section&nbsp;11.4.2<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>
+ provides an alternate verification mechanism referred to as
+ Stateless Mode.
+
+</p>
+<a name="anchor17"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.1"></a><h3>8.1.&nbsp;
+Association Session Request</h3>
+
+<p>
+ An association session is initiated by a <a class="info" href="#direct_comm">direct request<span> (</span><span class="info">Direct Communication</span><span>)</span></a> from a Relying
+ Party to an OP Endpoint URL with the "openid.mode" key
+ having the value of "associate".
+
+</p>
+<a name="anchor18"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.1.1"></a><h3>8.1.1.&nbsp;
+Common Request Parameters</h3>
+
+<p>
+ These parameters are common to all association requests:
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.mode
+
+<blockquote class="text">
+<p> Value: "associate"
+</p>
+</blockquote>
+
+</li>
+<li>openid.assoc_type
+
+<blockquote class="text">
+<p> The preferred association type. The association
+ type defines the algorithm to be used to sign
+ subsequent messages.
+</p>
+<p> Value: A valid association type from <a class="info" href="#assoc_types">Section&nbsp;8.3<span> (</span><span class="info">Association Types</span><span>)</span></a>
+</p>
+</blockquote>
+
+</li>
+<li>openid.session_type
+
+<blockquote class="text">
+<p>
+ The preferred association session type. This
+ defines the method used to encrypt the association's
+ MAC key in transit.
+
+</p>
+<p>
+ Value: A valid association session type from
+ <a class="info" href="#assoc_sess_types">Section&nbsp;8.4<span> (</span><span class="info">Association Session Types</span><span>)</span></a>.
+
+</p>
+<p>
+ Note: Unless using transport layer encryption,
+ "no-encryption" MUST NOT be used.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor19"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.1.2"></a><h3>8.1.2.&nbsp;
+Diffie-Hellman Request Parameters</h3>
+
+<p>
+ The following parameters are common to requests whose
+ requested association session type is "DH-SHA1" or
+ "DH-SHA256":
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.dh_modulus
+
+<blockquote class="text">
+<p>Value: base64(btwoc(p))
+</p>
+<p>Default: See <a class="info" href="#pvalue">Appendix&nbsp;B<span> (</span><span class="info">Diffie-Hellman Key Exchange Default Value</span><span>)</span></a>
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.dh_gen
+
+<blockquote class="text">
+<p>Value: base64(btwoc(g))
+</p>
+<p>Default: g = 2
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.dh_consumer_public
+
+<blockquote class="text">
+<p>Value: base64(btwoc(g ^ xa mod p))
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ See <a class="info" href="#dh_sessions">Section&nbsp;8.4.2<span> (</span><span class="info">Diffie-Hellman Association Sessions</span><span>)</span></a> for more information on
+ these parameters.
+
+</p>
+<p>
+ NOTE: The 'btwoc' function is defined in <a class="info" href="#btwoc">Section&nbsp;4.2<span> (</span><span class="info">Integer Representations</span><span>)</span></a>.
+
+</p>
+<a name="anchor20"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.2"></a><h3>8.2.&nbsp;
+Association Session Response</h3>
+
+<p>
+ An association session response is a direct response from the
+ OP to the Relying Party in <a class="info" href="#kvform">Key-Value
+ Form<span> (</span><span class="info">Key-Value Form Encoding</span><span>)</span></a>.
+
+</p>
+<a name="anchor21"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.2.1"></a><h3>8.2.1.&nbsp;
+Common Response Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#direct_response">Section&nbsp;5.1.2<span> (</span><span class="info">Direct Response</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ assoc_handle
+
+<blockquote class="text">
+<p>
+ The association handle is used as a key to refer
+ to this association in subsequent messages.
+
+</p>
+<p>
+ Value: A string 255 characters or less in length.
+ It MUST consist only of ASCII characters in the
+ range 33-126 inclusive (printable non-whitespace
+ characters).
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ session_type
+
+<blockquote class="text">
+<p>
+ The value of the "openid.session_type" parameter
+ from the request. If the OP is unwilling or
+ unable to support this association type, it MUST
+ return an <a class="info" href="#refuse_assoc">unsuccessful
+ response<span> (</span><span class="info">Unsuccessful Response Parameters</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ assoc_type
+
+<blockquote class="text">
+<p>
+ The value of the "openid.assoc_type" parameter
+ from the request. If the OP is unwilling or
+ unable to support this association type, it MUST
+ return an <a class="info" href="#refuse_assoc">unsuccessful
+ response<span> (</span><span class="info">Unsuccessful Response Parameters</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ expires_in
+
+<blockquote class="text">
+<p>
+ The lifetime, in seconds, of this association.
+ The Relying Party MUST NOT use the association
+ after this time has passed.
+
+</p>
+<p>
+ Value: An integer, represented in base 10 ASCII.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor22"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.2.2"></a><h3>8.2.2.&nbsp;
+Unencrypted Response Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ mac_key
+
+<blockquote class="text">
+<p>
+ The MAC key (shared secret) for this
+ association, <a class="info" href="#RFC3548">Base 64<span> (</span><span class="info">Josefsson, S., “The Base16, Base32, and Base64 Data Encodings,” .</span><span>)</span></a> [RFC3548]
+ encoded.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor23"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.2.3"></a><h3>8.2.3.&nbsp;
+Diffie-Hellman Response Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ dh_server_public
+
+<blockquote class="text">
+<p>
+ Value: base64(btwoc(g ^ xb mod p))
+
+</p>
+<p>
+ Description: The OP's Diffie-Hellman public key.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ enc_mac_key
+
+<blockquote class="text">
+<p>
+ Value: base64(H(btwoc(g ^ (xa * xb) mod p)) XOR MAC key)
+
+</p>
+<p>
+ Description: The MAC key (shared secret),
+ encrypted with the secret Diffie-Hellman value. H
+ is either "SHA1" or "SHA256" depending on the
+ session type.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ NOTE: The 'btwoc' function is defined in <a class="info" href="#btwoc">Section&nbsp;4.2<span> (</span><span class="info">Integer Representations</span><span>)</span></a>
+
+</p>
+<a name="refuse_assoc"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.2.4"></a><h3>8.2.4.&nbsp;
+Unsuccessful Response Parameters</h3>
+
+<p>
+ If the OP does not support a session type or association
+ type, it MUST respond with a direct error message
+ indicating that the association request failed. If there
+ is another association session type or association type
+ that is supported, the OP SHOULD include that information
+ in the response.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#direct_response">Section&nbsp;5.1.2<span> (</span><span class="info">Direct Response</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ error
+
+<blockquote class="text">
+<p>
+ Value: A human-readable message indicating why the
+ association request failed.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ error_code
+
+<blockquote class="text">
+<p>
+ Value: "unsupported-type"
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ session_type
+
+<blockquote class="text">
+<p>
+ Value: (optional) A valid association session type
+ from <a class="info" href="#assoc_sess_types">Section&nbsp;8.4<span> (</span><span class="info">Association Session Types</span><span>)</span></a> that the
+ OP supports.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ assoc_type
+
+<blockquote class="text">
+<p>
+ Value: (optional) An association type supported by
+ the OP from <a class="info" href="#assoc_types">Section&nbsp;8.3<span> (</span><span class="info">Association Types</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ Upon receipt of an "unsupported-type" response, the
+ Relying Party MAY make another request with the specified
+ association session type and association type. If no
+ association is established, the Relying Party MAY continue
+ the authentication process in <a class="info" href="#check_auth">Direct Verification<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>.
+
+</p>
+<a name="assoc_types"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.3"></a><h3>8.3.&nbsp;
+Association Types</h3>
+
+<a name="anchor24"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.3.1"></a><h3>8.3.1.&nbsp;
+HMAC-SHA1</h3>
+
+<p>
+ An association of type "HMAC-SHA1" uses the <a class="info" href="#sign_algos">HMAC-SHA1<span> (</span><span class="info">Signature Algorithms</span><span>)</span></a> signature algorithm.
+
+</p>
+<a name="anchor25"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.3.2"></a><h3>8.3.2.&nbsp;
+HMAC-SHA256</h3>
+
+<p>
+ An association of type "HMAC-SHA256" uses the <a class="info" href="#sign_algos">HMAC-SHA256<span> (</span><span class="info">Signature Algorithms</span><span>)</span></a> signature
+ algorithm.
+
+</p>
+<a name="assoc_sess_types"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.4"></a><h3>8.4.&nbsp;
+Association Session Types</h3>
+
+<p>
+ OpenID Authentication defines three valid association
+ session types: "no-encryption", "DH-SHA1", and "DH-SHA256".
+
+</p>
+<a name="anchor26"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.4.1"></a><h3>8.4.1.&nbsp;
+No-Encryption Association Sessions</h3>
+
+<p>
+ In a "no-encryption" association session, the OP sends
+ the association MAC key in plain-text to the Relying Party.
+ This makes it possible for an eavesdropper to intercept
+ the key, and forge messages to this Relying Party when not
+ using transport layer encryption. Therefore, "no-encryption"
+ association sessions MUST NOT be used unless the messages
+ are using transport layer encryption. See <a class="info" href="#preventing_eavesdropping">Section&nbsp;15.1.1<span> (</span><span class="info">Eavesdropping Attacks</span><span>)</span></a>
+ for more information.
+
+</p>
+<p>
+ The MAC key sent by the OP MUST be the length specified
+ for the requested association type, as specified in <a class="info" href="#sign_algos">Section&nbsp;6.2<span> (</span><span class="info">Signature Algorithms</span><span>)</span></a>.
+
+</p>
+<a name="dh_sessions"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.8.4.2"></a><h3>8.4.2.&nbsp;
+Diffie-Hellman Association Sessions</h3>
+
+<p>
+ The "DH-SHA1" and "DH-SHA256" association types use
+ Diffie-Hellman Key Exchange to securely transmit the
+ shared secret.
+
+</p>
+<p>
+ The MAC key MUST be the same length as the output of H,
+ the hash function - 160 bits (20 bytes) for DH-SHA1 or 256
+ bits (32 bytes) for DH-SHA256, as well as the output of
+ the signature algorithm of this association.
+
+</p>
+<p>
+ The Relying Party specifies a modulus, p, and a generator,
+ g. The Relying Party chooses a random private key xa and
+ OpenID Provider chooses a random private key xb, both in
+ the range [1 .. p-1]. The shared secret used to encrypt
+ the MAC key is thus g ^ (xa * xb) mod p = (g ^ xa) ^ xb
+ mod p = (g ^ xb) ^ xa mod p. For more information, see
+ <a class="info" href="#RFC2631">[RFC2631]<span> (</span><span class="info">Rescorla, E., “Diffie-Hellman Key Agreement Method,” .</span><span>)</span></a>. For information on the
+ selection of random values, see <a class="info" href="#RFC1750">[RFC1750]<span> (</span><span class="info">Eastlake, D., Crocker, S., and J. Schiller, “Randomness Recommendations for Security,” .</span><span>)</span></a>.
+
+</p>
+<a name="requesting_authentication"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9"></a><h3>9.&nbsp;
+Requesting Authentication</h3>
+
+<p>
+ Once the Relying Party has successfully performed discovery
+ and (optionally) created an association with the discovered
+ OP Endpoint URL, it can send an authentication request to the
+ OP to obtain an assertion. An authentication request is an
+ <a class="info" href="#indirect_comm">indirect request<span> (</span><span class="info">Indirect Communication</span><span>)</span></a>.
+
+</p>
+<a name="anchor27"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9.1"></a><h3>9.1.&nbsp;
+Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>
+ Value: "checkid_immediate" or "checkid_setup"
+
+</p>
+<p>
+ Note: If the Relying Party wishes the end user to be
+ able to interact with the OP, "checkid_setup"
+ should be used. An example of a situation where
+ interaction between the end user and the OP is not
+ desired is when the authentication request is
+ happening asynchronously in JavaScript.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.claimed_id
+
+<blockquote class="text">
+<p>
+ Value: (optional) The Claimed Identifier.
+
+</p>
+<p>
+ "openid.claimed_id" and "openid.identity" SHALL
+ be either both present or both absent. If neither
+ value is present, the assertion is not about an
+ identifier, and will contain other information in
+ its payload, using
+ <a class="info" href="#extensions">extensions<span> (</span><span class="info">Extensions</span><span>)</span></a>.
+
+</p>
+<p>
+ It is RECOMMENDED that OPs accept XRI identifiers
+ with or without the "xri://" prefix, as specified
+ in the <a class="info" href="#normalization">Normalization<span> (</span><span class="info">Normalization</span><span>)</span></a> section.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>
+ Value: (optional) The OP-Local Identifier.
+
+</p>
+<p>
+ If a different OP-Local Identifier is not specified,
+ the claimed identifier MUST be used as the value for
+ openid.identity.
+
+</p>
+<p>
+ Note: If this is set to the special value
+ "http://specs.openid.net/auth/2.0/identifier_select"
+ then the OP SHOULD choose an Identifier that belongs
+ to the end user. This parameter MAY be omitted if
+ the request is not about an identifier (for instance
+ if an extension is in use that makes the request
+ meaningful without it; see openid.claimed_id above).
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>
+ Value: (optional) A handle for an association
+ between the Relying Party and the OP that SHOULD be
+ used to sign the response.
+
+</p>
+<p>
+ Note: If no association handle is sent, the
+ transaction will take place in <a class="info" href="#check_auth">Stateless Mode<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>
+ Value: (optional) URL to which the OP SHOULD return
+ the User-Agent with the response indicating the
+ status of the request.
+
+</p>
+<p>
+ Note: If this value is not sent in the request it
+ signifies that the Relying Party does not wish
+ for the end user to be returned.
+
+</p>
+<p>
+ Note: The return_to URL MAY be used as a mechanism
+ for the Relying Party to attach context about the
+ authentication request to the authentication
+ response. This document does not define a mechanism
+ by which the RP can ensure that query parameters are
+ not modified by outside parties; such a mechanism
+ can be defined by the RP itself.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.realm
+
+<blockquote class="text">
+<p>
+ Value: (optional) URL pattern the OP SHOULD ask the
+ end user to trust. See <a class="info" href="#realms">Section&nbsp;9.2<span> (</span><span class="info">Realms</span><span>)</span></a>.
+ This value MUST be sent if openid.return_to is
+ omitted.
+
+</p>
+<p>
+ Default: return_to URL
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="realms"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9.2"></a><h3>9.2.&nbsp;
+Realms</h3>
+
+<p>
+ A "realm" is a pattern that represents the part of URL-space
+ for which an OpenID Authentication request is valid. A realm
+ is designed to give the end user an indication of the scope
+ of the authentication request. OPs SHOULD present the realm
+ when requesting the end user's approval for an authentication
+ request. The realm SHOULD be used by OPs to uniquely identify
+ Relying Parties. For example, OPs MAY use the realm to allow
+ the end user to automate approval of authentication requests.
+
+</p>
+<p>
+ A realm pattern is a URL, with the following changes:
+ </p>
+<ul class="text">
+<li>
+ A realm MUST NOT contain a URI fragment
+
+</li>
+<li>
+ A realm MAY contain a wild-card at the beginning of the
+ URL authority section. A wild-card consists of the
+ characters "*." prepended to the DNS name in the
+ authority section of the URL.
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ A URL matches a realm if:
+
+ </p>
+<ul class="text">
+<li>
+ The URL scheme and port of the URL are identical to those
+ in the realm. See <a class="info" href="#RFC3986">RFC
+ 3986<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a> [RFC3986], section 3.1 for rules about URI matching.
+
+</li>
+<li>
+ The URL's path is equal to or a sub-directory of the
+ realm's path.
+
+</li>
+<li>
+ Either:
+
+<ol class="text">
+<li>
+ The realm's domain contains the wild-card characters
+ "*.", and the trailing part of the URL's domain is
+ identical to the part of the realm following the
+ "*." wildcard, or
+
+</li>
+<li>
+ The URL's domain is identical to the realm's domain
+
+</li>
+</ol>
+
+</li>
+</ul><p>
+
+ When present, the "openid.return_to" URL MUST match the
+ "openid.realm", or the OP MUST return an <a class="info" href="#indirect_error">indirect error response<span> (</span><span class="info">Indirect Error Responses</span><span>)</span></a>.
+
+</p>
+<p>
+ It is RECOMMENDED that OPs protect their users from making
+ assertions with overly-general realms, like http://*.com/ or
+ http://*.co.uk/. Overly general realms can be dangerous when
+ the realm is used for identifying a particular Relying
+ Party. Whether a realm is overly-general is at the
+ discretion of the OP.
+
+</p>
+<a name="return_to_verification"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9.2.1"></a><h3>9.2.1.&nbsp;
+Using the Realm for Return URL Verification</h3>
+
+<p>
+ OpenID providers SHOULD verify that the return_to URL
+ specified in the request is an OpenID relying party
+ endpoint. To verify a return_to URL, obtain the relying
+ party endpoints for the realm by performing <a class="info" href="#rp_discovery">discovery on the relying
+ party<span> (</span><span class="info">Discovering OpenID Relying Parties</span><span>)</span></a>. As always when performing discovery, the
+ discovered URL is the URL of the last HTTP response,
+ following redirects. If any redirects are followed when
+ performing discovery on the realm, verification has
+ failed. If discovery has successfuly completed, check to
+ make sure that the return_to URL matches one of the
+ relying party endpoints.
+
+</p>
+<p>
+ A realm may contain a wildcard, and so may not be a valid
+ URL. In that case, perform discovery on the URL obtained
+ by substituting "www" for the wildcard in the realm.
+
+</p>
+<p>
+ To match a return_to URL against a relying party endpoint,
+ use the same rules as for matching the return_to URL
+ against the realm, treating the relying party's endpoint
+ URL as the realm. Relying party endpoint URLs MUST NOT
+ contain a domain wildcard, and SHOULD be as specific as
+ possible.
+
+</p>
+<p>
+ If verification is attempted and fails, the provider
+ SHOULD NOT send a positive assertion to that return_to
+ URL.
+
+</p>
+<p>
+ Providers MAY cache verified return_to URLs.
+
+</p>
+<a name="anchor28"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.9.3"></a><h3>9.3.&nbsp;
+Immediate Requests</h3>
+
+<p>
+ When requesting authentication, the Relying Party MAY
+ request that the OP not interact with the end user. In
+ this case the OP MUST respond immediately with either an
+ assertion that authentication is successful, or a response
+ indicating that the request cannot be completed without
+ further user interaction. This is accomplished by an
+ authentication request with "openid.mode" set to
+ "checkid_immediate".
+
+</p>
+<a name="responding_to_authentication"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.10"></a><h3>10.&nbsp;
+Responding to Authentication Requests</h3>
+
+<p>
+ When an authentication request comes from the User-Agent via
+ <a class="info" href="#indirect_comm">indirect communication<span> (</span><span class="info">Indirect Communication</span><span>)</span></a>,
+ the OP SHOULD determine that an authorized end user wishes to
+ complete the authentication. If an authorized end user wishes
+ to complete the authentication, the OP SHOULD send a <a class="info" href="#positive_assertions">positive assertion<span> (</span><span class="info">Positive Assertions</span><span>)</span></a> to the
+ Relying Party.
+
+</p>
+<p>
+ Methods of identifying authorized end users and obtaining
+ approval to return an OpenID Authentication assertion are
+ beyond the scope of this specification. See <a class="info" href="#rp_mitm_proxy">Section&nbsp;15.1.2.1<span> (</span><span class="info">Rogue Relying Party Proxying</span><span>)</span></a> for OpenID Provider security
+ considerations.
+
+</p>
+<p>
+ If the relying party requested OP-driven identifier selection
+ by setting "openid.identity" to
+ "http://specs.openid.net/auth/2.0/identifier_select"
+ and there are Identifiers for which the end user is authorized
+ to issue authentication responses, the OP SHOULD allow the end
+ user to choose which Identifier to use.
+
+</p>
+<p>
+ If the Relying Party supplied an association handle with the
+ authentication request, the OP SHOULD attempt to look up an
+ association based on that handle. If the association is
+ missing or expired, the OP SHOULD send the
+ "openid.invalidate_handle" parameter as part of the response
+ with the value of the request's "openid.assoc_handle"
+ parameter, and SHOULD proceed as if no association handle was
+ specified.
+
+</p>
+<p>
+ If no association handle is specified, the OP SHOULD use a
+ private association for signing the response. The OP MUST
+ store this association and MUST respond to later requests to
+ check the signature of the response via <a class="info" href="#check_auth">Direct Verification<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>.
+
+</p>
+<p>
+ Relying Parties SHOULD accept and verify assertions about
+ Identifiers for which they have not requested authentication.
+ OPs SHOULD use private associations for signing unsolicited
+ positive assertions.
+
+</p>
+<p>
+ If the "openid.return_to" value is omitted in the request, the
+ Relying Party does not wish to receive an authentication
+ assertion from the OP. This can be useful when using
+ extensions to transfer data from the Relying Party to the OP.
+
+</p>
+<a name="positive_assertions"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.10.1"></a><h3>10.1.&nbsp;
+Positive Assertions</h3>
+
+<p>
+ Positive assertions are <a class="info" href="#indirect_comm">indirect responses<span> (</span><span class="info">Indirect Communication</span><span>)</span></a> with the following fields:
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "id_res"
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.op_endpoint
+
+<blockquote class="text">
+<p>
+ The OP Endpoint URL.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.claimed_id
+
+<blockquote class="text">
+<p>
+ Value: (optional) The Claimed Identifier.
+ "openid.claimed_id" and "openid.identity" SHALL
+ be either both present or both absent.
+
+</p>
+<p>
+ Note: The end user MAY choose to use an OP-Local
+ Identifier as a Claimed Identifier.
+
+</p>
+<p>
+ Note: If neither Identifier is present in the assertion,
+ it is not about an identifier, and will contain
+ other information in its payload, using <a class="info" href="#extensions">extensions<span> (</span><span class="info">Extensions</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.identity
+
+<blockquote class="text">
+<p>
+ Value: (optional) The OP-Local Identifier
+
+</p>
+<p>
+ Note: OpenID Providers MAY assist the end user in
+ selecting the Claimed and OP-Local Identifiers about
+ which the assertion is made. The openid.identity
+ field MAY be omitted if an extension is in use that
+ makes the response meaningful without it
+ (see openid.claimed_id above).
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.return_to
+
+<blockquote class="text">
+<p>
+ Value: Verbatim copy of the return_to URL parameter
+ sent in the request.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.response_nonce
+
+<blockquote class="text">
+<p>
+ Value: A string 255 characters or less in length,
+ that MUST be unique to this particular successful
+ authentication response. The nonce MUST start with the
+ current time on the server, and MAY contain additional
+ ASCII characters in the range 33-126 inclusive
+ (printable non-whitespace characters), as necessary to
+ make each response unique. The date and time MUST be
+ formatted as specified in section 5.6 of
+ <a class="info" href="#RFC3339">[RFC3339]<span> (</span><span class="info">Klyne, G. and C. Newman, “Date and Time on the Internet: Timestamps,” .</span><span>)</span></a>, with the following restrictions:
+
+ </p>
+<ul class="text">
+<li>
+ All times must be in the UTC
+ timezone, indicated with a "Z".
+
+</li>
+<li>
+ No fractional seconds are allowed
+
+</li>
+</ul>
+
+ For example: 2005-05-15T17:11:51ZUNIQUE
+
+
+</blockquote>
+
+</li>
+<li>
+ openid.invalidate_handle
+
+<blockquote class="text">
+<p>
+ Value: (optional) If the Relying Party sent an
+ invalid association handle with the request, it
+ SHOULD be included here.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.assoc_handle
+
+<blockquote class="text">
+<p>
+ Value: The handle for the association that was used
+ to sign this assertion.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.signed
+
+<blockquote class="text">
+<p>
+ Value: Comma-separated list of signed fields.
+
+</p>
+<p>
+ Note: This entry consists of the fields without the
+ "openid." prefix that the signature covers. This
+ list MUST contain at least "op_endpoint",
+ "return_to" "response_nonce" and "assoc_handle", and
+ if present in the response, "claimed_id" and
+ "identity". Additional keys MAY be signed as part of
+ the message. See <a class="info" href="#generating_signatures">Generating
+ Signatures<span> (</span><span class="info">Generating Signatures</span><span>)</span></a>.
+
+</p>
+<p>
+ For example,
+ "op_endpoint,identity,claimed_id,return_to,assoc_handle,response_nonce".
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.sig
+
+<blockquote class="text">
+<p>
+ Value: Base 64 encoded signature calculated as
+ specified in <a class="info" href="#generating_signatures">Section&nbsp;6<span> (</span><span class="info">Generating Signatures</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+
+</p>
+<a name="negative_assertions"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.10.2"></a><h3>10.2.&nbsp;
+Negative Assertions</h3>
+
+<p>
+ If the OP is unable to identify the end user or the end
+ user does not or cannot approve the authentication request,
+ the OP SHOULD send a negative assertion to the Relying
+ Party as an <a class="info" href="#indirect_comm">indirect
+ response<span> (</span><span class="info">Indirect Communication</span><span>)</span></a>.
+
+</p>
+<p>
+ When receiving a negative assertion in response to a
+ "checkid_immediate" mode request, Relying Parties SHOULD
+ construct a new authentication request using "checkid_setup"
+ mode. Details about how this differs from OpenID
+ Authentication 1.1 can be found in <a class="info" href="#compat_mode">Section&nbsp;14<span> (</span><span class="info">OpenID Authentication 1.1 Compatibility</span><span>)</span></a>.
+
+</p>
+<a name="anchor29"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.10.2.1"></a><h3>10.2.1.&nbsp;
+In Response to Immediate Requests</h3>
+
+<p>
+ If the request was an immediate request, there is no chance
+ for the end user to interact with pages on the OP to provide
+ identifying credentials or approval of a request.
+ A negative assertion of an immediate request takes the
+ following form:
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "setup_needed"
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor30"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.10.2.2"></a><h3>10.2.2.&nbsp;
+In Response to Non-Immediate Requests</h3>
+
+<p>
+ Since the OP may display pages to the end user and
+ request credentials from the end user, a negative response
+ to a request that is not immediate is definitive. It
+ takes the following form:
+
+ </p>
+<ul class="text">
+<li>
+ openid.ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#http_encoding">Section&nbsp;4.1.2<span> (</span><span class="info">HTTP Encoding</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>
+ Value: "cancel"
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ Often, if the user does not wish to or cannot complete the
+ authentication request, the OpenID authentication process
+ will be aborted and the Relying Party will not get a
+ cancel mode response (the end user may quit or press the
+ back button in their User-Agent instead of continuing).
+ If a RP receives the "cancel" response, authentication was
+ unsuccessful and the RP MUST treat the end user as
+ non-authenticated.
+
+</p>
+<a name="verification"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11"></a><h3>11.&nbsp;
+Verifying Assertions</h3>
+
+<p>
+ When the Relying Party receives a positive assertion, it MUST
+ verify the following before accepting the assertion:
+
+ </p>
+<ul class="text">
+<li>
+ The value of "openid.return_to" matches the URL of the
+ current request (<a class="info" href="#verify_return_to">Section&nbsp;11.1<span> (</span><span class="info">Verifying the Return URL</span><span>)</span></a>)
+
+</li>
+<li>
+ Discovered information matches the information in the
+ assertion (<a class="info" href="#verify_disco">Section&nbsp;11.2<span> (</span><span class="info">Verifying Discovered Information</span><span>)</span></a>)
+
+</li>
+<li>
+ An assertion has not yet been accepted from this OP with
+ the same value for "openid.response_nonce" (<a class="info" href="#verify_nonce">Section&nbsp;11.3<span> (</span><span class="info">Checking the Nonce</span><span>)</span></a>)
+
+</li>
+<li>
+ The signature on the assertion is valid and all fields
+ that are required to be signed are signed (<a class="info" href="#verifying_signatures">Section&nbsp;11.4<span> (</span><span class="info">Verifying Signatures</span><span>)</span></a>)
+
+</li>
+</ul><p>
+
+ If all four of these conditions are met, assertion is now
+ verified. If the assertion contained a Claimed Identifier, the
+ user is now authenticated with that identifier.
+
+</p>
+<a name="verify_return_to"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.1"></a><h3>11.1.&nbsp;
+Verifying the Return URL</h3>
+
+<p>
+ To verify that the "openid.return_to" URL matches the URL
+ that is processing this assertion:
+
+ </p>
+<ul class="text">
+<li>
+ The URL scheme, authority, and path MUST be the same
+ between the two URLs.
+
+</li>
+<li>
+ Any query parameters that are present in the
+ "openid.return_to" URL MUST also be present with the
+ same values in the URL of the HTTP request the RP
+ received.
+
+</li>
+</ul><p>
+
+</p>
+<a name="verify_disco"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.2"></a><h3>11.2.&nbsp;
+Verifying Discovered Information</h3>
+
+<p>
+ If the Claimed Identifier in the assertion is a URL and
+ contains a fragment, the fragment part and the fragment
+ delimiter character "#" MUST NOT be used for the purposes
+ of verifying the discovered information.
+
+</p>
+<p>
+ If the Claimed Identifier is included in the assertion, it
+ MUST have been <a class="info" href="#discovery">discovered<span> (</span><span class="info">Discovery</span><span>)</span></a> by
+ the Relying Party and the information in the assertion MUST
+ be present in the discovered information. The Claimed
+ Identifier MUST NOT be an OP Identifier.
+
+</p>
+<p>
+ If the Claimed Identifier was not previously discovered
+ by the Relying Party (the "openid.identity" in the request
+ was "http://specs.openid.net/auth/2.0/identifier_select" or
+ a different Identifier, or if the OP is sending an unsolicited
+ positive assertion), the Relying Party MUST perform discovery
+ on the Claimed Identifier in the response to make sure that
+ the OP is authorized to make assertions about the Claimed
+ Identifier.
+
+</p>
+<p>
+ If no Claimed Identifier is present in the response, the
+ assertion is not about an identifier and the RP MUST NOT use
+ the User-supplied Identifier associated with the current
+ OpenID authentication transaction to identify the user.
+ Extension information in the assertion MAY still be used.
+
+</p><br><hr class="insert">
+<table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left">
+<tbody><tr><th align="left">Discovered Value</th><th align="left">Response Field</th></tr>
+<tr>
+<td align="left">Claimed Identifier</td>
+<td align="left">openid.claimed_id</td>
+</tr>
+<tr>
+<td align="left">OP-Local Identifier</td>
+<td align="left">openid.identity</td>
+</tr>
+<tr>
+<td align="left">OP Endpoint URL</td>
+<td align="left">openid.op_endpoint</td>
+</tr>
+<tr>
+<td align="left">Protocol Version</td>
+<td align="left">openid.ns</td>
+</tr>
+</tbody></table>
+
+<p style="text-align: center;">
+ This table shows the mapping of <a class="info" href="#discovered_info">discovered information<span> (</span><span class="info">Discovered Information</span><span>)</span></a>
+ into fields in the <a class="info" href="#positive_assertions">OpenID Authentication 2.0
+ "id_res" response<span> (</span><span class="info">Positive Assertions</span><span>)</span></a>
+
+</p><table align="center" border="0" cellpadding="0" cellspacing="2"><tbody><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Discovered Information to Authentication Response Mapping&nbsp;</b></font><br></td></tr></tbody></table><hr class="insert">
+
+<p>
+ If using a discovery mechanism that yields an XRDS document,
+ the protocol version, OP Endpoint URL and the OP-Local
+ Identifier (if different than the Claimed Identifier) MUST
+ be present in one &lt;xrd:Service&gt; element. There MAY be
+ unused fields in that &lt;xrd:Service&gt; element.
+
+</p>
+<p>Non-normative example:
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>&lt;Service xmlns="xri://$xrd*($v*2.0)"&gt;
+ &lt;Type&gt;http://specs.openid.net/auth/2.0/signon&lt;/Type&gt;
+ &lt;URI&gt;http://provider.example.com/openid&lt;/URI&gt;
+ &lt;URI&gt;https://provider.example.com/openid&lt;/URI&gt;
+&lt;/Service&gt;
+</pre></div>
+<p>
+ In this example XRDS snippet, the &lt;xrd:Service&gt;
+ element has two &lt;xrd:URI&gt; elements, which map to OP
+ Endpoint URLs as per <a class="info" href="#discovered_info">Section&nbsp;7.3.1<span> (</span><span class="info">Discovered Information</span><span>)</span></a>. If
+ an assertion has either value for "openid.op_endpoint",
+ then that field matches this &lt;xrd:Service&gt;
+ element. The other &lt;xrd:URI&gt; element is unused.
+
+</p>
+<a name="verify_nonce"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.3"></a><h3>11.3.&nbsp;
+Checking the Nonce</h3>
+
+<p>
+ To prevent replay attacks, the agent checking the signature
+ keeps track of the nonce values included in positive
+ assertions and never accepts the same value more than once
+ for the same OP Endpoint URL.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>
+ When using "check_authentication", the OP MUST NOT issue
+ more than one successful response to a request with the
+ same value for "openid.response_nonce".
+
+</li>
+<li>
+ When the Relying Party checks the signature on an
+ assertion, the Relying Party SHOULD ensure that an
+ assertion has not yet been accepted with the same value
+ for "openid.response_nonce" from the same OP Endpoint
+ URL.
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ The time-stamp MAY be used to reject responses that are too
+ far away from the current time, limiting the amount of time
+ that nonces must be stored to prevent attacks. The
+ acceptable range is out of the scope of this
+ specification. A larger range requires storing more nonces
+ for a longer time. A shorter range increases the chance that
+ clock-skew and transaction time will cause a spurious
+ rejection.
+
+</p>
+<a name="verifying_signatures"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.4"></a><h3>11.4.&nbsp;
+Verifying Signatures</h3>
+
+<p>
+ If the Relying Party has stored an association with the
+ association handle specified in the assertion, it MUST check
+ the signature on the assertion itself. If it does not have
+ an association stored, it MUST request that the OP verify
+ the signature via <a class="info" href="#check_auth">Direct
+ Verification<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>.
+
+</p>
+<a name="anchor31"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.4.1"></a><h3>11.4.1.&nbsp;
+Verifying with an Association</h3>
+
+<p>
+ The Relying Party follows the same procedure that the
+ OP followed in <a class="info" href="#generating_signatures">generating the signature<span> (</span><span class="info">Generating Signatures</span><span>)</span></a>, and then compares the
+ signature in the response to the signature it
+ generated. If the signatures do not match, the assertion
+ is invalid.
+
+</p>
+<p>
+ If an authentication request included an association
+ handle for an association between the OP and the Relying
+ party, and the OP no longer wishes to use that handle
+ (because it has expired or the secret has been
+ compromised, for instance), the OP will send a response
+ that must be verified directly with the OP, as specified
+ in <a class="info" href="#check_auth">Section&nbsp;11.4.2<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>. In that instance, the OP
+ will include the field "openid.invalidate_handle" set to
+ the association handle that the Relying Party included
+ with the original request.
+
+</p>
+<a name="check_auth"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.4.2"></a><h3>11.4.2.&nbsp;
+Verifying Directly with the OpenID Provider</h3>
+
+<p>
+ To have the signature verification performed by the OP,
+ the Relying Party sends a <a class="info" href="#direct_request">direct request<span> (</span><span class="info">Direct Request</span><span>)</span></a> to the OP. To verify the signature,
+ the OP uses a private association that was generated when
+ it issued the <a class="info" href="#positive_assertions">positive assertion<span> (</span><span class="info">Positive Assertions</span><span>)</span></a>.
+
+</p>
+<a name="anchor32"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.4.2.1"></a><h3>11.4.2.1.&nbsp;
+Request Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ openid.mode
+
+<blockquote class="text">
+<p>Value: "check_authentication"
+</p>
+</blockquote>
+
+</li>
+<li>
+ Exact copies of all fields from the authentication
+ response, except for "openid.mode".
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ For verifying signatures an OP MUST only use private
+ associations and MUST NOT use associations that have
+ shared keys. If the verification request contains a
+ handle for a shared association, it means the Relying
+ Party no longer knows the shared secret, or an entity
+ other than the RP (e.g. an attacker) has established
+ this association with the OP.
+
+</p>
+<p>
+ To prevent replay attacks, the OP MUST NOT issue more
+ than one verification response for each authentication
+ response it had previously issued. An authentication
+ response and its matching verification request may
+ be identified by their "openid.response_nonce" values.
+
+</p>
+<a name="anchor33"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.4.2.2"></a><h3>11.4.2.2.&nbsp;
+Response Parameters</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ ns
+
+<blockquote class="text">
+<p>
+ As specified in <a class="info" href="#direct_response">Section&nbsp;5.1.2<span> (</span><span class="info">Direct Response</span><span>)</span></a>.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ is_valid
+
+<blockquote class="text">
+<p>
+ Value: "true" or "false"; asserts whether the
+ signature of the verification request is valid.
+
+</p>
+</blockquote>
+
+</li>
+<li>
+ invalidate_handle
+
+<blockquote class="text">
+<p>
+ Value: (optional) The "invalidate_handle" value
+ sent in the verification request, if the OP confirms
+ it is invalid.
+
+</p>
+<p>
+ Description: If present in a verification response
+ with "is_valid" set to "true", the Relying Party
+ SHOULD remove the corresponding association from its
+ store and SHOULD NOT send further authentication
+ requests with this handle.
+
+</p>
+<p>
+ Note: This two-step process for invalidating
+ associations is necessary to prevent an attacker
+ from invalidating an association at will by adding
+ "invalidate_handle" parameters to an authentication
+ response.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="identifying"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.5"></a><h3>11.5.&nbsp;
+Identifying the end user</h3>
+
+<p>
+ The Claimed Identifier in a successful authentication
+ response SHOULD be used by the Relying Party as a key for
+ local storage of information about the user. The Claimed
+ Identifier MAY be used as a user-visible Identifier. When
+ displaying URL Identifiers, the fragment MAY be omitted.
+
+</p>
+<a name="identifier_recycling"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.5.1"></a><h3>11.5.1.&nbsp;
+Identifier Recycling</h3>
+
+<p>
+ OpenID Providers with large user bases can use fragments
+ to recycle URL Identifiers if it is so desired. When
+ reassigning a URL Identifier to a new end user OPs should
+ generate a new, unique fragment part.
+
+</p>
+<p>
+ The full URL with the fragment part constitutes the Claimed
+ Identifier in positive assertions, therefore Relying Parties
+ will distinguish between the current and previous owners of
+ the fragment-less URL.
+
+</p>
+<p>
+ This mechanism allows the (presumably short, memorable)
+ recycled URL Identifiers without the fragment to be used by
+ end users at login time and by Relying Parties for display
+ purposes.
+
+</p>
+<a name="http_s_identifiers"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.11.5.2"></a><h3>11.5.2.&nbsp;
+HTTP and HTTPS URL Identifiers</h3>
+
+<p>
+ Relying Parties MUST differentiate between URL Identifiers
+ that have different schemes. When end user input is
+ processed into a URL, it is processed into a HTTP URL. If
+ the same end user controls the same URL, differing only by
+ scheme, and it is desired that the Identifier be the HTTPS
+ URL, it is RECOMMENDED that a redirect be issued from the
+ HTTP URL to the HTTPS URL. Because the HTTP and HTTPS URLs
+ are not equivalent and the Identifier that is used is the
+ URL after following redirects, there is no foreseen
+ reduction in security when using this scheme. If an
+ attacker could gain control of the HTTP URL, it would have
+ no effect on the HTTPS URL, since the HTTP URL is not ever
+ used as an Identifier except to initiate the discovery
+ process.
+
+</p>
+<a name="extensions"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.12"></a><h3>12.&nbsp;
+Extensions</h3>
+
+<p>
+ An Extension to OpenID Authentication is a protocol that
+ "piggybacks" on the authentication request and response. Extensions
+ are useful for providing extra information about an
+ authentication request or response as well as providing extra
+ information about the subject of the authentication response.
+
+</p>
+<p>
+ OpenID extensions are identified by a Type URI. The Type URI
+ MAY be used as the value of an &lt;xrd:Type&gt; element of an
+ OpenID &lt;xrd:Service&gt; element in an XRDS document
+ associated with a Claimed Identifier. The Type URI is also
+ used to associate key-value pairs in messages with the extension.
+
+</p>
+<p>
+
+ To associate keys and values in a message with an extension,
+ the key MUST be associated with the Type URI. To associate
+ keys with a Type URI, establish an alias by adding a key
+ prefixed with "openid.ns." and ending with the alias text
+ whose value is the Type URI. Once an alias has been
+ established, all pairs in the message whose keys start with
+ "openid." followed by the alias text, followed by a period or
+ the end of the key are associated with that extension.
+ This mechanism is similar to the XML namespaces.
+
+</p>
+<p>
+ A namespace alias MUST NOT contain a period and MUST NOT be
+ the same as another namespace alias in the same message. A
+ namespace alias also MUST NOT be in the following list of
+ disallowed aliases:
+
+ </p>
+<ul class="text">
+<li>assoc_handle
+</li>
+<li>assoc_type
+</li>
+<li>claimed_id
+</li>
+<li>contact
+</li>
+<li>delegate
+</li>
+<li>dh_consumer_public
+</li>
+<li>dh_gen
+</li>
+<li>dh_modulus
+</li>
+<li>error
+</li>
+<li>identity
+</li>
+<li>invalidate_handle
+</li>
+<li>mode
+</li>
+<li>ns
+</li>
+<li>op_endpoint
+</li>
+<li>openid
+</li>
+<li>realm
+</li>
+<li>reference
+</li>
+<li>response_nonce
+</li>
+<li>return_to
+</li>
+<li>server
+</li>
+<li>session_type
+</li>
+<li>sig
+</li>
+<li>signed
+</li>
+<li>trust_root
+</li>
+</ul><p>
+
+ A namespace MUST NOT be assigned more than one alias in the
+ same message. If a message is a response to another message,
+ the response MAY use a different alias to refer to the same
+ namespace.
+
+</p>
+<p>Non-normative example:
+</p>
+<p>An extension's type URI is
+ "&lt;http://example.com/ext/1.0&gt;".
+
+ </p>
+<blockquote class="text">
+<p>openid.ns.x=http://example.com/ext/1.0
+</p>
+<p>openid.x=example
+</p>
+<p>openid.x.foo=bar
+</p>
+<p>openid.xx=notx
+</p>
+</blockquote><p>
+
+ In this example, the keys "openid.x" and "openid.x.foo" are
+ associated with the extension; the "openid.xx" key is not.
+
+</p>
+<p>
+ Extensions MUST NOT define multiple parameters with the same name.
+ Extensions that need to send multiple values for the same parameter
+ name must define their own conventions for doing so.
+
+</p>
+<a name="rp_discovery"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.13"></a><h3>13.&nbsp;
+Discovering OpenID Relying Parties</h3>
+
+<p>
+ Relying Party discovery allows for software agents to discover
+ sites that support OpenID. It also allows OpenID providers to
+ automatically verify that a return_to URL in an OpenID request
+ is an OpenID relying party endpoint for the specified realm.
+
+</p>
+<p>
+ Relying Parties SHOULD use the Yadis protocol to publish their
+ valid return_to URLs. The relying party MAY publish this
+ information at any URL, and SHOULD publish it under the realm
+ so that providers can verify return_to URLs.
+
+</p>
+<p>
+ A Relying Party discovery XRDS document MUST contain one or more
+ &lt;xrd:Service&gt; elements:
+
+ </p>
+<ul class="text">
+<li>
+ Containing at least one &lt;xrd:URI&gt; element.
+
+</li>
+<li>
+ Where all &lt;xrd:URI&gt; tags contain a URL that accepts
+ OpenID 2.0 Authentication responses.
+
+</li>
+<li>
+ Containing a &lt;xrd:Type&gt; tag whose content is
+ "http://specs.openid.net/auth/2.0/return_to".
+
+</li>
+</ul><p>
+
+</p>
+<p>Non-normative example:
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>&lt;Service xmlns="xri://$xrd*($v*2.0)"&gt;
+ &lt;Type&gt;http://specs.openid.net/auth/2.0/return_to&lt;/Type&gt;
+ &lt;URI&gt;http://consumer.example.com/return&lt;/URI&gt;
+&lt;/Service&gt;
+</pre></div>
+<a name="compat_mode"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14"></a><h3>14.&nbsp;
+OpenID Authentication 1.1 Compatibility</h3>
+
+<p>
+ This section describes how to interact with OpenID
+ Authentication 1.1 Relying Parties and OPs. OpenID
+ Authentication 2.0 implementations SHOULD support OpenID
+ Authentication 1.1 compatibility, unless security
+ considerations make it undesirable.
+
+</p>
+<a name="anchor34"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.1"></a><h3>14.1.&nbsp;
+Changes from OpenID Authentication 1.1</h3>
+
+<p>
+ (non-normative)
+
+</p>
+<p>
+ This specification is based on the original specification for
+ OpenID Authentication as written by Brad Fitzpatrick. That
+ specification did not have a version number, but was called
+ OpenID 1.0, and then OpenID 1.1 when it was revised. The
+ protocol outlined in this specification is intended to be
+ backwards-compatible with the revised OpenID protocol. The
+ changes to the specification are outlined in this section.
+
+</p>
+<a name="anchor35"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.1.1"></a><h3>14.1.1.&nbsp;
+Updated Initiation and Discovery</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ Supports OP Identifiers. This new variation of the
+ protocol flow is initiated by an end user entering an OP
+ Identifier instead of their own Identifier. This allows
+ the OP to assist the end user in selecting an
+ Identifier.
+
+</li>
+<li>
+ Supports the use of XRIs as Identifiers. XRIs may be
+ used as Identifiers for both end users and OPs, and
+ provide automatic mapping from one or more reassignable
+ i-names to a synonymous persistent Canonical ID that
+ will never be reassigned.
+
+</li>
+<li>
+ When URLs are used as Identifiers, they are normalized
+ according to the guidelines in <a class="info" href="#RFC3986">[RFC3986]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a>,
+ for better compatibility with the existing Web infrastructure.
+
+</li>
+<li>
+ Uses the Yadis protocol for discovery. This allows for
+ using multiple OPs for a single Identifier, for
+ load-balancing and fallback in the case of OP
+ failure. Additionally, it allows for discovery of
+ supported extensions and other associated services.
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor36"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.1.2"></a><h3>14.1.2.&nbsp;
+Security improvements</h3>
+
+<p>
+ A nonce is now part of the protocol for built-in protection
+ against replay attacks, which was previously implemented
+ out-of-band by each library or application.
+
+</p>
+<p>
+ A new association type, HMAC-SHA256, and a new association
+ session type, DH-SHA256, allow for stronger signatures on
+ authentication assertions.
+
+</p>
+<p>
+ An actual <a class="info" href="#security_considerations">Security
+ Considerations section<span> (</span><span class="info">Security Considerations</span><span>)</span></a> which looks at protecting
+ the protocol from end-to-end.
+
+</p>
+<a name="anchor37"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.1.3"></a><h3>14.1.3.&nbsp;
+Extensions</h3>
+
+<p>
+ Extensions are now an officially supported mechanism to
+ support data exchange and other Relying Party-OP
+ communication along with the authentication
+ exchange. Extensions allow for the exchange of arbitrary
+ attributes, as well as for protocol extensions,
+ such as the inclusion of additional information about the
+ Relying Party in the authentication request.
+
+</p>
+<p>
+ Because extensions can transfer arbitrary data, the
+ Identifier is now optional in authentication messages.
+
+</p>
+<a name="anchor38"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.2"></a><h3>14.2.&nbsp;
+Implementing OpenID Authentication 1.1 Compatibility</h3>
+
+<p>
+ All messages in OpenID Authentication 1.1 omit the
+ "openid.ns" parameter, which is an easy way for an RP to
+ determine if the message is from an OpenID Authentication
+ 1.1 endpoint. OpenID Authentication 1.1 supports only
+ HMAC-SHA1 associations.
+
+</p>
+<p>
+ Error responses in OpenID Authentication 1.1 did not define
+ "contact" or "reference". OpenID Authentication 1.1 did
+ allow for the addition of extra fields in error
+ responses. It is RECOMMENDED for contact and reference to be
+ sent even when using OpenID Authentication 1.1, since they
+ may be useful for debugging and do not affect compatibility.
+
+</p>
+<a name="anchor39"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.2.1"></a><h3>14.2.1.&nbsp;
+Relying Parties</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ When HTML discovery is performed, the OP endpoint URL
+ is marked by the link relationship "openid.server"
+ rather than "openid2.provider". The end user's
+ OP-Local Identifier is marked by the link relationship
+ "openid.delegate" rather than "openid2.local_id". The
+ protocol version is in this case
+ "http://openid.net/signon/1.1". HTML allows multiple
+ link relationships to be specified for a single link,
+ so if an OP provides both OpenID Authentication 1.1
+ and OpenID Authentication 2.0, "openid2.provider" and
+ "openid.server" may appear in the same "rel"
+ attribute.
+
+</li>
+<li>
+ When XRDS-based discovery is performed, the end user's
+ OP-Local Identifier appears in the
+ &lt;openid:Delegate&gt; tag of the OpenID
+ &lt;xrd:Service&gt; element rather than in the
+ &lt;xrd:LocalID&gt; tag. In order to support
+ currently-deployed discovery code, both tags MAY
+ appear in the &lt;xrd:Service&gt; element.
+
+</li>
+<li>
+ Relying Parties SHOULD extract and use OpenID
+ Authentication 1.x service elements from XRDS
+ documents, if Yadis succeeds on an URL
+ Identifier. Such service elements are identified by
+ &lt;xrd:Type&gt; tags whose text contents are
+ "http://openid.net/server/1.0" or
+ "http://openid.net/server/1.1". Although this is not
+ specified in the previous version of the protocol, it
+ is a generally accepted practice of advertising OpenID
+ Authentication 1.x services through Yadis.
+
+</li>
+<li>
+ "openid.claimed_id" is not defined by OpenID
+ Authentication 1.1. Relying Parties MAY send the value
+ when making requests, but MUST NOT depend on the value
+ being present in authentication responses. When the
+ OP-Local Identifier ("openid.identity") is
+ different from the Claimed Identifier, the Relying
+ Party MUST keep track of what Claimed Identifier was
+ used to discover the OP-Local Identifier, for
+ example by keeping it in session state. Although the
+ Claimed Identifier will not be present in the
+ response, it MUST be used as the identifier for the
+ user.
+
+</li>
+<li>
+ "openid.identity" MUST be sent in a <a class="info" href="#responding_to_authentication">authentication
+ request<span> (</span><span class="info">Responding to Authentication Requests</span><span>)</span></a>.
+
+</li>
+<li>
+ Relying Parties MUST send a blank session_type parameter
+ in "no-encryption" association requests.
+
+</li>
+<li>
+ In OpenID Authentication 1.1, the "no-encryption"
+ association session type is represented by a blank or
+ missing "openid.session_type" parameter. Relying
+ Parties MUST NOT send requests with
+ "openid.session_type" set to "no-encryption".
+
+</li>
+<li>
+ In <a class="info" href="#requesting_authentication">authentication
+ requests<span> (</span><span class="info">Requesting Authentication</span><span>)</span></a>, the "openid.identity" parameter
+ SHOULD NOT be the special value
+ "http://specs.openid.net/auth/2.0/identifier_select",
+ because OpenID Authentication 1.1 does not support the
+ use of OP Identifiers.
+
+</li>
+<li>
+ The "openid.realm" parameter in authentication requests
+ was known as "openid.trust_root". The syntax and meaning
+ are identical.
+
+</li>
+<li>
+ When responding with a negative assertion to a
+ "checkid_immediate" mode authentication request, the
+ "user_setup_url" parameter MUST be returned. This is a
+ URL that the end user may visit to complete the
+ request. The OP MAY redirect the end user to
+ this URL, or provide the end user with a link that
+ points to this URL.
+
+</li>
+<li>
+ The Relying Party MUST accept an <a class="info" href="#positive_assertions">authentication
+ response<span> (</span><span class="info">Positive Assertions</span><span>)</span></a> that is missing the
+ "openid.response_nonce" parameter. It SHOULD
+ implement a method for preventing replay attacks.
+
+</li>
+<li>
+ Relying Parties MUST accept
+ <a class="info" href="#positive_assertions">authentication responses<span> (</span><span class="info">Positive Assertions</span><span>)</span></a> that are missing the "openid.op_endpoint" parameter.
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor40"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.14.2.2"></a><h3>14.2.2.&nbsp;
+OpenID Providers</h3>
+
+<p>
+ </p>
+<ul class="text">
+<li>
+ "openid.identity" MUST be sent in a <a class="info" href="#positive_assertions">positive authentication
+ assertion<span> (</span><span class="info">Positive Assertions</span><span>)</span></a>.
+
+</li>
+<li>
+ In OpenID Authentication 1.1, the "no-encryption"
+ association session type is represented by a blank or
+ missing "openid.session_type" parameter. OPs MUST NOT
+ send responses with "openid.session_type" set to
+ "no-encryption".
+
+</li>
+<li>
+ OPs MAY choose to return a successful "no-encryption"
+ response to any association request. As above, the
+ "openid.session_type" parameter MUST be blank or
+ omitted from the response.
+
+</li>
+<li>
+ OPs MUST accept association requests with no assoc_type
+ parameter, and assume them to be of type HMAC-SHA1.
+
+</li>
+<li>
+ Unsuccessful association attempts MAY be responded with
+ direct error messages or with "no-encryption" positive
+ association responses.
+
+</li>
+<li>
+ The "openid.realm" parameter in authentication requests
+ was known as "openid.trust_root". The syntax and meaning
+ are identical.
+
+</li>
+<li>
+ When responding with a negative assertion to a
+ "checkid_immediate" mode authentication request, the
+ "user_setup_url" parameter MUST be returned. This is a URL
+ that the end user may visit to complete the request. The
+ Relying Party may redirect the end user to this URL, or
+ provide the end user with a link that points to this
+ URL.
+
+</li>
+<li>
+ OPs MUST NOT send the "openid.op_endpoint" parameter in
+ <a class="info" href="#positive_assertions">authentication responses<span> (</span><span class="info">Positive Assertions</span><span>)</span></a>, since it is not part of the OpenID Authentication
+ 1.1 protocol.
+
+</li>
+</ul><p>
+
+</p>
+<a name="security_considerations"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15"></a><h3>15.&nbsp;
+Security Considerations</h3>
+
+<a name="anchor41"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.1"></a><h3>15.1.&nbsp;
+Preventing Attacks</h3>
+
+<a name="preventing_eavesdropping"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.1.1"></a><h3>15.1.1.&nbsp;
+Eavesdropping Attacks</h3>
+
+<p>
+ There is one place in this protocol that is vulnerable
+ to eavesdropping attacks.
+ </p>
+<ul class="text">
+<li>
+ If the nonce were not checked, an eavesdropper could also
+ intercept a successful authentication assertion and re-use it.
+
+</li>
+</ul><p>
+
+</p>
+<p>
+ This attack can be prevented by using transport layer encryption
+ for these connections to prevent eavesdropping. In addition,
+ if not using TLS this attack can still be prevented by
+ checking the nonce while performing message verification.
+ When doing so, the positive authentication assertion cannot
+ be re-used.
+
+</p>
+<a name="anchor42"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.1.2"></a><h3>15.1.2.&nbsp;
+Man-in-the-Middle Attacks</h3>
+
+<p>
+ Associations prevent tampering of signed fields by a man
+ in the middle except during discovery, association
+ sessions and <a class="info" href="#check_auth">Direct
+ Verification<span> (</span><span class="info">Verifying Directly with the OpenID Provider</span><span>)</span></a>. Altering signed fields without the
+ shared secret requires breaking the MAC. Currently no
+ tractable attack is known on the MACs used in this
+ protocol. The quality of the protection provided by the
+ MAC depends on the randomness of the shared MAC key, so it
+ is important that an unguessable value be used.
+
+</p>
+<p>
+ If DNS resolution or the transport layer is compromised
+ signatures on messages are not adequate, since the
+ attacker can impersonate the OP and issue its own
+ associations, or its own decisions in Stateless Mode. If
+ an attacker can tamper with the discovery process they can
+ specify any OP, and so does not have to impersonate the
+ OP. Additionally, if an attacker can compromise the
+ integrity of the information returned during the discovery
+ process, by altering the XRDS document, the need for a man
+ in the middle is removed. One method to prevent this sort
+ of attack is by digitally signing the XRDS file as per
+ <a class="info" href="#RFC3275">XMLDSIG<span> (</span><span class="info">Eastlake 3rd, D., Reagle Jr., J., and D. Solo, “(Extensible Markup Language) XML-Signature Syntax and Processing,” .</span><span>)</span></a> [RFC3275]. The keying material
+ is not specified, since the RP ultimately needs to make
+ its own decision whether to trust keys used for such
+ signature.
+
+</p>
+<p>
+ Using SSL with certificates signed by a trusted authority
+ prevents these kinds of attacks by verifying the results
+ of the DNS look-up against the certificate. Once the
+ validity of the certificate has been established,
+ tampering is not possible. Impersonating an SSL server
+ requires forging or stealing a certificate, which is
+ significantly harder than the network based attacks.
+
+</p>
+<p>
+ In order to get protection from SSL, SSL must be used for
+ all parts of the interaction, including interaction with
+ the end user through the User-Agent. While the protocol
+ does not require SSL be used, its use is strongly
+ RECOMMENDED. Current best practices dictate that an OP
+ SHOULD use SSL, with a certificate signed by a trusted
+ authority, to secure its Endpoint URL as well as the
+ interactions with the end user's User-Agent. In addition,
+ SSL, with a certificate signed by a trusted authority,
+ SHOULD be used so that a Relying Party can fetch the end
+ user's URL in a secure manner. Following its own security
+ policies, a Relying Party MAY choose to not complete, or
+ even begin, a transaction if SSL is not being correctly
+ used at these various endpoints.
+
+</p>
+<a name="rp_mitm_proxy"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.1.2.1"></a><h3>15.1.2.1.&nbsp;
+Rogue Relying Party Proxying</h3>
+
+<p>
+ A special type of man-in-the-middle attack is one where
+ the Relying Party is a rogue party acting as a MITM. The
+ RP would perform discovery on the End User's Claimed
+ Identifier and instead of redirecting the User Agent to
+ the OP, would instead proxy the OP through itself. This
+ would thus allow the RP to capture credentials the End
+ User provides to the OP. While there are multiple ways to
+ prevent this sort of attack, the specifics are outside the
+ scope of this document. Each method of prevention
+ requires that the OP establish a secure channel with the
+ End User.
+
+</p>
+<a name="anchor43"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.2"></a><h3>15.2.&nbsp;
+User-Agents</h3>
+
+<p>
+ Since this protocol is intended to be used interactively,
+ User-Agents will primarily be common Web browsers. Web
+ browsers or their hosts may be infected with spyware or
+ other malware, which limits the strength of the
+ authentication assertion, since untrusted software makes it
+ impossible to know whether the authentication decision has
+ been made with the end user's approval. With that said, many
+ web applications and protocols today rely on the security of
+ the Web browser and their hosts.
+
+</p>
+<p>
+ Cross-site-scripting attacks against OPs may be used to the
+ same effect. For the best security, OPs should not depend
+ on scripting. This enables User-Agents that do not support
+ scripting, or have scripting disabled, to still employ the
+ protocol.
+
+</p>
+<a name="anchor44"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.3"></a><h3>15.3.&nbsp;
+User Interface Considerations</h3>
+
+<p>
+ The Relying Party SHOULD redirect the end user to the OP
+ Endpoint URL in a top-level browser window with all controls
+ visible. This allows better protection for the end user
+ against OP look-alike sites (phishing).
+
+</p>
+<p>
+ OpenID Providers SHOULD educate their end users about the
+ potential for OpenID phishing attacks and SHOULD equip their
+ end users with the tools to defeat such attacks, for example
+ browser plug-ins that verify the authenticity of the OP's
+ Authentication Service Endpoint URL.
+
+</p>
+<a name="anchor45"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.4"></a><h3>15.4.&nbsp;
+HTTP and HTTPS URL Identifiers</h3>
+
+<p>
+ While these types of Identifiers have been <a class="info" href="#http_s_identifiers">previously discussed<span> (</span><span class="info">HTTP and HTTPS URL Identifiers</span><span>)</span></a>,
+ they are worth mentioning again. As previously stated, the
+ RECOMMENDED method of an End User expressing control over a
+ URL differing only be scheme is to setup a redirect from the
+ HTTP URL to the HTTPS URL. Relying Parties will never store
+ the HTTP URL as during the discovery and initiation phase
+ will follow the redirect and use the HTTPS URL as the
+ Claimed Identifier.
+
+</p>
+<p>
+ End users with concerns over this recommendation should
+ directly enter their HTTPS URL at each Relying Party. This
+ thus removes the step where the Relying Party follows the
+ redirect to the HTTPS URL. The single security
+ consideration currently seen is if an attacker were to
+ compromise the integrity of the HTTP URL by removing the
+ redirect and pointing the Identifier at a rogue OP. This
+ however will alter the user experience, is detectable by
+ anti-phishing technologies, and the security of the
+ Identifier itself is a fundamental principle within OpenID.
+
+</p>
+<a name="anchor46"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.5"></a><h3>15.5.&nbsp;
+Denial of Service Attacks</h3>
+
+<p>
+ Within the protocol there are places where a rogue RP could
+ launch a denial of service attack against an OP since there
+ is nothing in OpenID protocol messages that allows the OP to
+ quickly check that it is a genuine request. This can be
+ done by the RP repeatedly requesting associations,
+ authentication, or verification of a signature.
+
+</p>
+<p>
+ The potentially most severe attack is during the association
+ phase as each message requires the OP to execute a discrete
+ exponentiation. Since the RP has the ability to specify
+ modulus and generator per message, an attacker can even
+ force the OP to perform this exponentiation in real time
+ prior to responding for each message.
+
+</p>
+<p>
+ While this could be particularly harmful, OpenID Providers
+ can easily use generic IP based rate-limiting and banning
+ techniques to help combat these sorts of attacks. OPs can
+ also look at banning requests based on the "openid.realm"
+ and "openid.return_to" values.
+
+</p>
+<a name="anchor47"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.15.6"></a><h3>15.6.&nbsp;
+Protocol Variants</h3>
+
+<p>
+ The following are known variations in the protocol which may
+ or may not directly affect the security of the use of the
+ protocol. It is imagined that these values could be used in
+ the creation of security profiles for this protocol. The
+ following list of variants are from the perspective of an
+ OpenID Provider.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">Number</th><th align="left">Variant</th><th align="left">Values</th></tr>
+<tr>
+<td align="left">1.</td>
+<td align="left">
+ Are wildcards allowed in realms?
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">2.</td>
+<td align="left">
+ Require prior association? Does the OP require the RP
+ first create an association before requesting
+ authentication?
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">3.</td>
+<td align="left">
+ Types of claimed identifiers accepted.
+ </td>
+<td align="left">
+ Set of HTTP/HTTPS/XRI
+ </td>
+</tr>
+<tr>
+<td align="left">4.</td>
+<td align="left">
+ Are self-issued certificates allowed for authentication?
+ This applies to all SSL traffic. If 'no' here, then OP
+ *probably* requires all HTTPS identifiers to chain up to
+ known trust roots, but that's intentionally not implied.
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">5.</td>
+<td align="left">
+ Must the XRDS file be signed? Signature on the XRDS as per
+ XMLDSIG. Keying material not specified, since the RP
+ ultimately needs to make own decision whether to trust
+ keys used for such signature.
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">6.</td>
+<td align="left">
+ Must the XRDS file be retrieved over secure channel? This does not
+ imply SSL?
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">7.</td>
+<td align="left">
+ What types of session types can be used when creating
+ associations?
+ </td>
+<td align="left">
+ Set of no-encryption/DH-SHA1/DH-SHA256
+ </td>
+</tr>
+<tr>
+<td align="left">8.</td>
+<td align="left">
+ Must the RP have an XRDS document?
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+<tr>
+<td align="left">9.</td>
+<td align="left">
+ What association types the OP agrees to use for
+ signatures?
+ </td>
+<td align="left">
+ Set of HMAC-SHA1/HMAC-SHA256
+ </td>
+</tr>
+<tr>
+<td align="left">10.</td>
+<td align="left">
+ Must the association request take place over secure channel?
+ </td>
+<td align="left">
+ One of Yes/No
+ </td>
+</tr>
+</tbody></table>
+
+<p style="text-align: center;">
+ Identified security variants.
+
+</p>
+<a name="anchor48"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A"></a><h3>Appendix A.&nbsp;
+Examples</h3>
+
+<p>Non-normative
+</p>
+<a name="normalization_example"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.1"></a><h3>Appendix A.1.&nbsp;
+Normalization</h3>
+
+<p>
+ See section 6 of <a class="info" href="#RFC3986">[RFC3986]<span> (</span><span class="info">Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .</span><span>)</span></a> for
+ textual URL normalization details and more examples.
+
+</p><br><hr class="insert">
+<table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">User's Input</th><th align="left">Identifier</th><th align="left">Type</th><th align="left">Discussion</th></tr>
+<tr>
+<td align="left">example.com</td>
+<td align="left">http://example.com/</td>
+<td align="left">URL</td>
+<td align="left">A URI with a missing scheme is normalized to a http URI</td>
+</tr>
+<tr>
+<td align="left">http://example.com</td>
+<td align="left">http://example.com/</td>
+<td align="left">URL</td>
+<td align="left">An empty path component is normalized to a slash</td>
+</tr>
+<tr>
+<td align="left">https://example.com/</td>
+<td align="left">https://example.com/</td>
+<td align="left">URL</td>
+<td align="left">https URIs remain https URIs</td>
+</tr>
+<tr>
+<td align="left">http://example.com/user</td>
+<td align="left">http://example.com/user</td>
+<td align="left">URL</td>
+<td align="left">No trailing slash is added to non-empty path components</td>
+</tr>
+<tr>
+<td align="left">http://example.com/user/</td>
+<td align="left">http://example.com/user/</td>
+<td align="left">URL</td>
+<td align="left">Trailing slashes are preserved on non-empty path components</td>
+</tr>
+<tr>
+<td align="left">http://example.com/</td>
+<td align="left">http://example.com/</td>
+<td align="left">URL</td>
+<td align="left">Trailing slashes are preserved when the path is empty</td>
+</tr>
+<tr>
+<td align="left">=example</td>
+<td align="left">=example</td>
+<td align="left">XRI</td>
+<td align="left">Normalized XRIs start with a global context symbol</td>
+</tr>
+<tr>
+<td align="left">xri://=example</td>
+<td align="left">=example</td>
+<td align="left">XRI</td>
+<td align="left">Normalized XRIs start with a global context symbol</td>
+</tr>
+</tbody></table>
+<table align="center" border="0" cellpadding="0" cellspacing="2"><tbody><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;User's Input to Identifier Normalization&nbsp;</b></font><br></td></tr></tbody></table><hr class="insert">
+
+<a name="anchor49"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.2"></a><h3>Appendix A.2.&nbsp;
+OP-Local Identifiers</h3>
+
+<p>
+ An end user wants to use "http://www.example.com/" as their
+ Claimed Identifier. The end user has an account with
+ Example Provider, which functions as an OpenID Provider. The
+ end user's OP-Local Identifier is
+ "https://exampleuser.exampleprovider.com/".
+
+</p>
+<p>
+ In this scenario, with the proper configuration of Yadis or
+ HTML-Based Discovery (see <a class="info" href="#discovery">Section&nbsp;7.3<span> (</span><span class="info">Discovery</span><span>)</span></a> and
+ <a class="info" href="#XRDS_Sample">Appendix&nbsp;A.3<span> (</span><span class="info">XRDS</span><span>)</span></a> below), a Relying Party will
+ discover the following information about the end user:
+
+ </p>
+<blockquote class="text"><dl>
+<dt>Claimed Identifier</dt>
+<dd>
+ http://www.example.com/
+
+</dd>
+<dt>OP-Local Identifier</dt>
+<dd>
+ https://exampleuser.exampleprovider.com/
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="XRDS_Sample"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.3"></a><h3>Appendix A.3.&nbsp;
+XRDS</h3>
+
+<p>
+ For an end user to use "http://www.example.com/" as
+ their Identifier, but have Relying Parties actually
+ verify "https://exampleuser.exampleprovider.com/" with the OP
+ Endpoint URL
+ "https://www.exampleprovider.com/endpoint/", the
+ following XML snippet should be present in the final XRD
+ element in the XRDS file when discovery is preformed on
+ "http://www.example.com/":
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>&lt;Service xmlns="xri://$xrd*($v*2.0)"&gt;
+ &lt;Type&gt;http://specs.openid.net/auth/2.0/signon&lt;/Type&gt;
+ &lt;URI&gt;https://www.exampleprovider.com/endpoint/&lt;/URI&gt;
+ &lt;LocalID&gt;https://exampleuser.exampleprovider.com/&lt;/LocalID&gt;
+&lt;/Service&gt;
+</pre></div>
+<a name="anchor50"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.4"></a><h3>Appendix A.4.&nbsp;
+HTML Identifier Markup</h3>
+
+<p>
+ To use "http://www.example.com/" as their Identifier, but have
+ Relying Parties actually verify
+ "http://exampleuser.livejournal.com/" with the OpenID
+ Provider located at
+ "http://www.livejournal.com/openid/server.bml", the
+ following markup should be present in the &lt;head&gt;
+ of the HTML document located by the identifier URL:
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>&lt;link rel="openid2.provider openid.server"
+ href="http://www.livejournal.com/openid/server.bml"/&gt;
+&lt;link rel="openid2.local_id openid.delegate"
+ href="http://exampleuser.livejournal.com/"/&gt;
+</pre></div>
+<a name="anchor51"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.5"></a><h3>Appendix A.5.&nbsp;
+XRI CanonicalID</h3>
+
+<p>
+ For example, if the XRI i-names =example and =exmpl both
+ yield an XRDS document with the CanonicalID
+ xri://(example)!1234 then those Identifiers should be
+ treated as equivalent. For applications with user accounts,
+ the persistent Canonical ID xri://(example)!1234 should be
+ used the primary key for the account. Although the
+ i-names =example and =exmpl may also be stored for reference
+ as display names, they are reassignable identifiers and
+ should not be used as persistent keys.
+
+</p>
+<a name="pvalue"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.B"></a><h3>Appendix B.&nbsp;
+Diffie-Hellman Key Exchange Default Value</h3>
+
+<p>
+ This is a confirmed-prime number, used as the default
+ modulus for Diffie-Hellman Key Exchange. In hexadecimal:
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>DCF93A0B883972EC0E19989AC5A2CE310E1D37717E8D9571BB7623731866E61E
+F75A2E27898B057F9891C2E27A639C3F29B60814581CD3B2CA3986D268370557
+7D45C2E7E52DC81C7A171876E5CEA74B1448BFDFAF18828EFD2519F14E45E382
+6634AF1949E5B535CC829A483B8A76223E5D490A257F05BDFF16F2FB22C583AB
+</pre></div>
+<a name="anchor52"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.C"></a><h3>Appendix C.&nbsp;
+Acknowledgements</h3>
+
+<p>
+ The OpenID Community would like to thank the following people
+ for the work they've done in the drafting and editing of this
+ specification. If you want to know the nitty gritty of who
+ actually wrote what, feel free to look at our SVN repository
+ or even use "svn blame". :)
+ http://openid.net/svn/specifications/authentication/2.0/
+
+</p>
+<p>
+ </p>
+<blockquote class="text">
+<p>Barry Ferg (barry@sxip.com)
+</p>
+<p>Brad Fitzpatrick (brad@danga.com) &lt;author&gt;
+</p>
+<p>Carl Howells (chowells@janrain.com)
+</p>
+<p>David Recordon (david@sixapart.com) &lt;author/editor&gt;
+</p>
+<p>Dick Hardt (dick@sxip.com) &lt;author&gt;
+</p>
+<p>Drummond Reed (drummond.reed@cordance.net)
+</p>
+<p>Hans Granqvist (hgranqvist@verisign.com)
+</p>
+<p>Johannes Ernst (jernst@netmesh.us)
+</p>
+<p>Johnny Bufu (johnny@sxip.com) &lt;editor&gt;
+</p>
+<p>Josh Hoyt (josh@janrain.com) &lt;author/editor&gt;
+</p>
+<p>Kevin Turner (kevin@janrain.com)
+</p>
+<p>Marius Scurtescu (marius@sxip.com)
+</p>
+<p>Martin Atkins (mart@degeneration.co.uk)
+</p>
+<p>Mike Glover (mpg4@janrain.com)
+</p>
+</blockquote><p>
+
+</p>
+<a name="rfc.references1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>16.&nbsp;Normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="FIPS180-2">[FIPS180-2]</a></td>
+<td class="author-text">U.S. Department of Commerce and National Institute of Standards
+ and Technology, “<a href="http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf">Secure Hash Signature Standard</a>,” FIPS&nbsp;180-2.<p>
+Defines Secure Hash Algorithm 256 (SHA256)
+</p>
+</td></tr>
+<tr><td class="author-text" valign="top"><a name="HTML401">[HTML401]</a></td>
+<td class="author-text">W3C, “<a href="http://www.w3.org/TR/html401">HTML 4.01 Specification</a>.”</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC1750">[RFC1750]</a></td>
+<td class="author-text">Eastlake, D., Crocker, S., and J. Schiller, “<a href="ftp://ftp.isi.edu/in-notes/rfc1750.txt">Randomness Recommendations for Security</a>,” RFC&nbsp;1750.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2104">[RFC2104]</a></td>
+<td class="author-text">Krawczyk, H., Bellare, M., and R. Canetti, “<a href="ftp://ftp.isi.edu/in-notes/rfc2104.txt">HMAC: Keyed-Hashing for Message Authentication</a>,” RFC&nbsp;2104.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2119">[RFC2119]</a></td>
+<td class="author-text">Bradner, B., “<a href="ftp://ftp.isi.edu/in-notes/rfc2119.txt">Key words for use in RFCs to Indicate Requirement Levels</a>,” RFC&nbsp;2119.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2616">[RFC2616]</a></td>
+<td class="author-text">Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, “<a href="ftp://ftp.isi.edu/in-notes/rfc2616.txt">Hypertext Transfer Protocol -- HTTP/1.1</a>,” RFC&nbsp;2616.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2631">[RFC2631]</a></td>
+<td class="author-text">Rescorla, E., “<a href="ftp://ftp.isi.edu/in-notes/rfc2631.txt">Diffie-Hellman Key Agreement Method</a>,” RFC&nbsp;2631.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3174">[RFC3174]</a></td>
+<td class="author-text">Eastlake, D. and P. Jones, “<a href="ftp://ftp.isi.edu/in-notes/rfc3174.txt">US Secure Hash Algorithm 1 (SHA1)</a>,” RFC&nbsp;3174.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3275">[RFC3275]</a></td>
+<td class="author-text">Eastlake 3rd, D., Reagle Jr., J., and D. Solo, “<a href="ftp://ftp.isi.edu/in-notes/rfc3275.txt">(Extensible Markup Language) XML-Signature Syntax and
+ Processing</a>,” RFC&nbsp;3275.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3339">[RFC3339]</a></td>
+<td class="author-text">Klyne, G. and C. Newman, “<a href="ftp://ftp.isi.edu/in-notes/rfc3339.txt">Date and Time on the Internet: Timestamps</a>,” RFC&nbsp;3339.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3548">[RFC3548]</a></td>
+<td class="author-text">Josefsson, S., “<a href="ftp://ftp.isi.edu/in-notes/rfc3548.txt">The Base16, Base32, and Base64 Data Encodings</a>,” RFC&nbsp;3548.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3629">[RFC3629]</a></td>
+<td class="author-text">Yergeau, F., “<a href="ftp://ftp.isi.edu/in-notes/rfc3629.txt">UTF-8, a transformation format of Unicode and ISO 10646</a>,” RFC&nbsp;3629.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3986">[RFC3986]</a></td>
+<td class="author-text">Berners-Lee, T., “<a href="ftp://ftp.isi.edu/in-notes/rfc3986.txt">Uniform Resource Identifiers (URI): Generic Syntax</a>,” RFC&nbsp;3986.</td></tr>
+<tr><td class="author-text" valign="top"><a name="XRI_Resolution_2.0">[XRI_Resolution_2.0]</a></td>
+<td class="author-text">Wachob, G., Reed, D., Chasen, L., Tan, W., and S. Churchill, “<a href="http://www.oasis-open.org/committees/download.php/17293">Extensible Resource Identifier (XRI) Resolution V2.0
+ - Committee Draft 02</a>” (<a href="http://docs.oasis-open.org/xri/2.0/specs/cd02/xri-resolution-V2.0-cd-02.html">HTML</a>, <a href="http://docs.oasis-open.org/xri/2.0/specs/cd02/xri-resolution-V2.0-cd-02.pdf">PDF</a>).</td></tr>
+<tr><td class="author-text" valign="top"><a name="XRI_Syntax_2.0">[XRI_Syntax_2.0]</a></td>
+<td class="author-text">Reed, D. and D. McAlpin, “<a href="http://www.oasis-open.org/committees/download.php/15376">Extensible Resource Identifier (XRI) Syntax V2.0</a>” (<a href="http://www.oasis-open.org/committees/download.php/15376">HTML</a>, <a href="http://www.oasis-open.org/committees/download.php/15377">PDF</a>).</td></tr>
+<tr><td class="author-text" valign="top"><a name="Yadis">[Yadis]</a></td>
+<td class="author-text">Miller, J., “Yadis Specification 1.0” (<a href="http://yadis.org/papers/yadis-v1.0.pdf">PDF</a>, <a href="http://yadis.org/papers/yadis-v1.0.odt">ODT</a>).</td></tr>
+</tbody></table>
+
+<a name="rfc.authors"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Author's Address</h3>
+<table border="0" cellpadding="0" cellspacing="0" width="99%">
+<tbody><tr><td class="author-text">&nbsp;</td>
+<td class="author-text">specs@openid.net</td></tr>
+</tbody></table>
+
+</body></html> \ No newline at end of file
diff --git a/doc/specs/openid-provider-authentication-policy-extension-1_0-02.html b/doc/specs/openid-provider-authentication-policy-extension-1_0-02.html
new file mode 100644
index 0000000..a0de6e3
--- /dev/null
+++ b/doc/specs/openid-provider-authentication-policy-extension-1_0-02.html
@@ -0,0 +1,1137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en"><head><title>Draft: OpenID Provider Authentication Policy Extension 1.0 - Draft 2</title>
+
+<meta http-equiv="Expires" content="Tue, 23 Oct 2007 23:12:39 +0000">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="description" content="OpenID Provider Authentication Policy Extension 1.0 - Draft 2">
+<meta name="generator" content="xml2rfc v1.31 (http://xml.resource.org/)">
+<style type="text/css"><!--
+ body {
+ font-family: verdana, charcoal, helvetica, arial, sans-serif;
+ font-size: small; color: #000; background-color: #FFF;
+ margin: 2em;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
+ font-weight: bold; font-style: normal;
+ }
+ h1 { color: #900; background-color: transparent; text-align: right; }
+ h3 { color: #333; background-color: transparent; }
+
+ td.RFCbug {
+ font-size: x-small; text-decoration: none;
+ width: 30px; height: 30px; padding-top: 2px;
+ text-align: justify; vertical-align: middle;
+ background-color: #000;
+ }
+ td.RFCbug span.RFC {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: bold; color: #666;
+ }
+ td.RFCbug span.hotText {
+ font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-weight: normal; text-align: center; color: #FFF;
+ }
+
+ table.TOCbug { width: 30px; height: 15px; }
+ td.TOCbug {
+ text-align: center; width: 30px; height: 15px;
+ color: #FFF; background-color: #900;
+ }
+ td.TOCbug a {
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
+ font-weight: bold; font-size: x-small; text-decoration: none;
+ color: #FFF; background-color: transparent;
+ }
+
+ td.header {
+ font-family: arial, helvetica, sans-serif; font-size: x-small;
+ vertical-align: top; width: 33%;
+ color: #FFF; background-color: #666;
+ }
+ td.author { font-weight: bold; font-size: x-small; margin-left: 4em; }
+ td.author-text { font-size: x-small; }
+
+ /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
+ a.info {
+ /* This is the key. */
+ position: relative;
+ z-index: 24;
+ text-decoration: none;
+ }
+ a.info:hover {
+ z-index: 25;
+ color: #FFF; background-color: #900;
+ }
+ a.info span { display: none; }
+ a.info:hover span.info {
+ /* The span will display just on :hover state. */
+ display: block;
+ position: absolute;
+ font-size: smaller;
+ top: 2em; left: -5em; width: 15em;
+ padding: 2px; border: 1px solid #333;
+ color: #900; background-color: #EEE;
+ text-align: left;
+ }
+
+ a { font-weight: bold; }
+ a:link { color: #900; background-color: transparent; }
+ a:visited { color: #633; background-color: transparent; }
+ a:active { color: #633; background-color: transparent; }
+
+ p { margin-left: 2em; margin-right: 2em; }
+ p.copyright { font-size: x-small; }
+ p.toc { font-size: small; font-weight: bold; margin-left: 3em; }
+ table.toc { margin: 0 0 0 3em; padding: 0; border: 0; vertical-align: text-top; }
+ td.toc { font-size: small; font-weight: bold; vertical-align: text-top; }
+
+ ol.text { margin-left: 2em; margin-right: 2em; }
+ ul.text { margin-left: 2em; margin-right: 2em; }
+ li { margin-left: 3em; }
+
+ /* RFC-2629 <spanx>s and <artwork>s. */
+ em { font-style: italic; }
+ strong { font-weight: bold; }
+ dfn { font-weight: bold; font-style: normal; }
+ cite { font-weight: normal; font-style: normal; }
+ tt { color: #036; }
+ tt, pre, pre dfn, pre em, pre cite, pre span {
+ font-family: "Courier New", Courier, monospace; font-size: small;
+ }
+ pre {
+ text-align: left; padding: 4px;
+ color: #000; background-color: #CCC;
+ }
+ pre dfn { color: #900; }
+ pre em { color: #66F; background-color: #FFC; font-weight: normal; }
+ pre .key { color: #33C; font-weight: bold; }
+ pre .id { color: #900; }
+ pre .str { color: #000; background-color: #CFF; }
+ pre .val { color: #066; }
+ pre .rep { color: #909; }
+ pre .oth { color: #000; background-color: #FCF; }
+ pre .err { background-color: #FCC; }
+
+ /* RFC-2629 <texttable>s. */
+ table.full, table.headers, table.none {
+ font-size: small; text-align: center; border-width: 2px;
+ vertical-align: top; border-collapse: collapse;
+ }
+ table.full { border-style: solid; border-color: black; }
+ table.headers, table.none { border-style: none; }
+ th {
+ font-weight: bold; border-color: black;
+ border-width: 2px 2px 3px 2px;
+ }
+ table.full th { border-style: solid; }
+ table.headers th { border-style: none none solid none; }
+ table.none th { border-style: none; }
+ table.full td {
+ border-style: solid; border-color: #333;
+ border-width: 1px 2px;
+ }
+ table.headers td, table.none td { border-style: none; }
+
+ hr { height: 1px; }
+ hr.insert {
+ width: 80%; border-style: none; border-width: 0;
+ color: #CCC; background-color: #CCC;
+ }
+--></style></head><body>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<table summary="layout" border="0" cellpadding="0" cellspacing="0" width="66%"><tbody><tr><td><table summary="layout" border="0" cellpadding="2" cellspacing="1" width="100%">
+<tbody><tr><td class="header">Draft</td><td class="header">D. Recordon</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">Six Apart</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">J. Bufu, Ed.</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">Sxip Identity</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">J. Hoyt, Ed.</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">JanRain</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">October 23, 2007</td></tr>
+</tbody></table></td></tr></tbody></table>
+<h1><br>OpenID Provider Authentication Policy Extension 1.0 - Draft 2</h1>
+
+<h3>Abstract</h3>
+
+<p>
+ This extension to the OpenID Authentication protocol provides
+ a mechanism by which a Relying Party can request that
+ particular authentication policies be applied by the OpenID
+ Provider when authenticating an End User. This extension also
+ provides a mechanism by which an OpenID Provider may inform a
+ Relying Party which authentication policies were used. Thus a
+ Relying Party can request that the End User authenticate, for
+ example, using a phishing-resistant or multi-factor
+ authentication method.
+
+</p>
+<p>
+ This extension is not intended to provide all information
+ regarding the quality of an OpenID Authentication
+ assertion. Rather, it is designed to be balanced with
+ information the Relying Party already has with regard to the
+ OpenID Provider and the level of trust it places in it. If
+ additional information is needed about processes such as new
+ End User enrollment on the OpenID Provider, such information
+ should either be transmitted out-of-band or in other extensions
+ such as OpenID Attribute Exchange. Other aspects (e.g. security
+ characteristics, credential provisioning, etc) could be dealt
+ with in the future, though End User privacy concerns must be
+ kept in mind especially when discussing enrollment procedures.
+
+</p>
+<p>
+ This extension is optional, though its use is certainly
+ recommended. This extension can be used with OpenID
+ Authentication versions 1.1 and 2.0.
+
+</p>
+<p>
+ While none of the information transmitted using this extension
+ can be verified by the Relying Party using technology alone,
+ this does not limit the utility of this extension. The lack of
+ a single required trust model within OpenID allows Relying
+ Parties to decide which Providers are trustworthy; likewise,
+ RPs can decide whether to trust authentication policy claims
+ from such OpenID Providers as well. As with other OpenID
+ extensions, is is the Relying Party's responsibility to
+ implement policy relative to the OpenID Provider's response.
+
+</p><a name="toc"></a><br><hr>
+<h3>Table of Contents</h3>
+<p class="toc">
+<a href="#anchor1">1.</a>&nbsp;
+Definitions<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor2">1.1.</a>&nbsp;
+Requirements Notation<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor3">1.2.</a>&nbsp;
+Conventions<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor4">1.3.</a>&nbsp;
+Terminology<br>
+<a href="#anchor5">2.</a>&nbsp;
+Extension Overview<br>
+<a href="#advertising">3.</a>&nbsp;
+Advertising Supported Policies<br>
+<a href="#auth_policies">4.</a>&nbsp;
+Defined Authentication Policies<br>
+<a href="#anchor8">5.</a>&nbsp;
+Authentication Protocol<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor9">5.1.</a>&nbsp;
+Request Parameters<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor10">5.2.</a>&nbsp;
+Response Parameters<br>
+<a href="#anchor11">6.</a>&nbsp;
+Security Considerations<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#anchor12">6.1.</a>&nbsp;
+NIST Assurance Levels<br>
+<a href="#examples">Appendix&nbsp;A.</a>&nbsp;
+Examples<br>
+<a href="#anchor13">Appendix&nbsp;A.1.</a>&nbsp;
+Authentication Method Classifications<br>
+<a href="#anchor15">Appendix&nbsp;B.</a>&nbsp;
+Acknowledgements<br>
+<a href="#rfc.references1">7.</a>&nbsp;
+Normative References<br>
+<a href="#rfc.authors">§</a>&nbsp;
+Authors' Addresses<br>
+</p>
+<br clear="all">
+
+<a name="anchor1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1"></a><h3>1.&nbsp;
+Definitions</h3>
+
+<a name="anchor2"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1.1"></a><h3>1.1.&nbsp;
+Requirements Notation</h3>
+
+<p>
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
+ "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" in this document are to be interpreted as
+ described in <a class="info" href="#RFC2119">[RFC2119]<span> (</span><span class="info">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels,” 1997.</span><span>)</span></a>.
+
+</p>
+<a name="anchor3"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1.2"></a><h3>1.2.&nbsp;
+Conventions</h3>
+
+<p>
+ Throughout this document, values are quoted to indicate that
+ they are to be taken literally. When using these values in
+ protocol messages, the quotes MUST NOT be used as part of the
+ value.
+
+</p>
+<p>
+ All OpenID Provider Authentication Policy Extension (PAPE) messages
+ MUST contain the following extension namespace declaration, as
+ specified in the Extensions section of <a class="info" href="#OpenIDAuthentication2.0">[OpenIDAuthentication2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Draft 11,” 2007.</span><span>)</span></a>.
+
+</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre>
+ openid.ns.&lt;alias&gt;=http://specs.openid.net/extensions/pape/1.0
+
+</pre></div>
+<p>
+ The actual extension namespace alias should be determined on a
+ per-message basis by the party composing the messages, in such a
+ manner as to avoid conflicts between multiple extensions. For the
+ purposes of this document and when constructing OpenID 1.1 messages,
+ the extension namespace alias SHALL be "pape".
+
+</p>
+<a name="anchor4"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1.3"></a><h3>1.3.&nbsp;
+Terminology</h3>
+
+<p>
+ The following terms are defined in
+ <a class="info" href="#OpenIDAuthentication2.0">[OpenIDAuthentication2.0]<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Draft 11,” 2007.</span><span>)</span></a>:
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>Identifier
+</li>
+<li>OpenID Provider (OP)
+</li>
+<li>Relying Party (RP)
+</li>
+<li>User-Agent
+</li>
+</ul><p>
+
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>Authentication Method:</dt>
+<dd>
+ A single mechanism by which the End User authenticated to their
+ OpenID Provider. For example, a password or a hardware
+ credential.
+
+</dd>
+<dt>Authentication Policy:</dt>
+<dd>
+ An Authentication Policy is a plain-text description of
+ requirements that dictate which Authentication Methods can be
+ used by an End User when authenticating to their OpenID Provider.
+ An Authentication Policy is defined by a URI which must be
+ previously agreed upon by one or more OPs and RPs.
+
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor5"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.2"></a><h3>2.&nbsp;
+Extension Overview</h3>
+
+<p>
+ </p>
+<ol class="text">
+<li>
+ As part of the <a class="info" href="#Yadis">[Yadis]<span> (</span><span class="info">Miller, J., Ed., “Yadis Specification 1.0,” 2005.</span><span>)</span></a> Discovery process, OpenID
+ Providers can optionally add supported authentication policies to
+ an End User's XRDS document. This aids Relying Parties in
+ choosing between multiple listed OPs depending on authentication
+ policy requirements.
+
+</li>
+<li>
+ The Relying Party includes parameters in the OpenID Authentication
+ request describing its preferences for authentication policy for
+ the current assertion.
+
+</li>
+<li>
+ The OpenID Provider processes the PAPE request, prompting the End
+ User to fulfill the requested policies during the authentication
+ process.
+
+</li>
+<li>
+ As part of the OpenID Provider's response to the Relying Party,
+ the OP includes PAPE information around the End User's
+ authentication. An OP MAY include this response information even
+ if not requested by the RP.
+
+</li>
+<li>
+ When processing the OpenID Provider's response, the Relying Party
+ takes the PAPE information into account when determining if the
+ End User should be sent through additional verification steps or
+ if the OpenID login process cannot proceed due to not meeting
+ policy requirements.
+
+</li>
+</ol><p>
+
+</p>
+<a name="advertising"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3"></a><h3>3.&nbsp;
+Advertising Supported Policies</h3>
+
+<p>
+ Via the use of <a class="info" href="#Yadis">[Yadis]<span> (</span><span class="info">Miller, J., Ed., “Yadis Specification 1.0,” 2005.</span><span>)</span></a> within OpenID, Relying
+ Parties are able to discover OpenID Provider service
+ information in an automated fashion. This is used within
+ OpenID Authentication for a RP to discover what version of the
+ protocol each OP listed supports as well as any extensions,
+ such as this one, that are supported. To aide in the process
+ of a Relying Party selecting which OP they wish to interact
+ with, it is advised that the following information be added to
+ the End User's XRDS document.
+
+</p>
+<p>
+ When advertising supported policies, each policy URI MUST be added as
+ the value of an &lt;xrd:Type&gt; element of an OpenID
+ &lt;xrd:Service&gt; element in an XRDS document.
+
+</p>
+<a name="auth_policies"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4"></a><h3>4.&nbsp;
+Defined Authentication Policies</h3>
+
+<p>
+ The following are defined policies and policy
+ identifiers describing how the End User should authenticate to an OP.
+ Additional policies can be specified elsewhere and used without
+ making changes to this document. The policies described below are
+ designed to be a starting point to cover the most common use-cases.
+ Additional polices can be found at
+ http://schemas.openid.net/pape/policies/.
+
+ <a class="info" href="#comment.anchor6">[anchor6]<span> (</span><span class="info">There
+is ongoing discussion as to if a policy should be defined to represent
+technologies which help prevent phishing attacks though do not fit the
+phishing-resistant definition. Examples would be site seal technology,
+browser plugins specific to OpenID flows, and Internet Explorer 7's
+support for Extended Validation SSL certificates.</span><span>)</span></a><a name="anchor6"></a>
+
+</p>
+<p>
+ When multiple policies are listed in the Relying Party's request, it
+ is up to the OpenID Provider to satisfy as many of the policies as it
+ can. This might mean that the OP needs to understand the relationship
+ between policies (such as if one encompasses another or if one is
+ stronger than another). This also means that when the RP processes the
+ OP's response, it will have to make its own determinations as to if its
+ requirements were met. That said, if the RP requested Multi-Factor
+ Authentication and the OP supports Multi-Factor Physical Authentication,
+ it is recommended that the OP includes both policies in the response.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>Phishing-Resistant Authentication
+ <a class="info" href="#comment.anchor7">[anchor7]<span> (</span><span class="info">There
+is ongoing discussion as to the best wording for this definition. The
+main spirit of this definition is that a user does not authenticate to
+the OP by providing a password by itself directly from within the
+User-Agent.</span><span>)</span></a><a name="anchor7"></a>
+
+<blockquote class="text">
+<p>http://schemas.openid.net/pape/policies/2007/06/phishing-resistant
+</p>
+<p>
+ An authentication mechanism where the End User does not
+ provide a shared secret to a party potentially under the
+ control of the Relying Party. (Note that the potentially
+ malicious Relying Party controls where the User-Agent is
+ redirected to and thus may not send it to the End User's
+ actual OpenID Provider).
+
+</p>
+</blockquote>
+
+</li>
+<li>Multi-Factor Authentication
+
+<blockquote class="text">
+<p>http://schemas.openid.net/pape/policies/2007/06/multi-factor
+</p>
+<p>
+ An authentication mechanism where the End User authenticates
+ to the OpenID Provider by providing over one authentication
+ factor. Common authentication factors are something you
+ know, something you have, and something you are. An example
+ would be authentication using a password and a software
+ token or digital certificate.
+
+</p>
+</blockquote>
+
+</li>
+<li>Physical Multi-Factor Authentication
+
+<blockquote class="text">
+<p>http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical
+</p>
+<p>
+ An authentication mechanism where the End User authenticates
+ to the OpenID Provider by providing over one authentication
+ factor where at least one of the factors is a physical
+ factor such as a hardware device or biometric. Common
+ authentication factors are something you know, something you
+ have, and something you are. This policy also implies the
+ Multi-Factor Authentication policy
+ (http://schemas.openid.net/pape/policies/2007/06/multi-factor)
+ and both policies MAY BE specified in conjunction without
+ conflict. An example would be authentication using a password
+ and a hardware token.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor8"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5"></a><h3>5.&nbsp;
+Authentication Protocol</h3>
+
+<a name="anchor9"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.1"></a><h3>5.1.&nbsp;
+Request Parameters</h3>
+
+<p>
+ The following parameters MUST be included during an <a class="info" href="#OpenIDAuthentication2.0">OpenID Authentication
+ request<span> (</span><span class="info">specs@openid.net, “OpenID Authentication 2.0 - Draft 11,” 2007.</span><span>)</span></a> [OpenIDAuthentication2.0] by the Relying Party unless marked as optional.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>openid.ns.pape
+
+<blockquote class="text">
+<p>
+ Value: "http://specs.openid.net/extensions/pape/1.0"
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.pape.max_auth_age
+
+<blockquote class="text">
+<p>
+ (Optional) If the End User has not actively authenticated to
+ the OP within the number of seconds specified in a manner
+ fitting the requested policies, the OP SHOULD authenticate the
+ End User for this request.
+
+</p>
+<p>
+ Value: Integer value greater than or equal to zero in
+ seconds.
+
+</p>
+<p>
+ The OP should realize that not adhering to the request for
+ re-authentication most likely means that the End User will
+ not be allowed access to the services provided by the RP. If
+ this parameter is absent in the request, the OP should
+ authenticate the user at its own discretion.
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.pape.preferred_auth_policies
+
+<blockquote class="text">
+<p>
+ Zero or more authentication policy URIs that the OP SHOULD
+ conform to when authenticating the user. If multiple policies
+ are requested, the OP SHOULD satisfy as many as it can.
+
+</p>
+<p>
+ Value: Space separated list of authentication policy URIs.
+
+</p>
+<p>
+ If no policies are requested, the RP may be interested in other
+ information such as the authentication age.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor10"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5.2"></a><h3>5.2.&nbsp;
+Response Parameters</h3>
+
+<p>
+ In response to a Relying Party's request, the following parameters
+ MUST be included in the OpenID Authentication Response. All response
+ parameters MUST be included in the signature of the Authentication
+ Response. It is RECOMMENDED that an OP supporting this extension
+ include the following parameters even if not requested by the
+ Relying Party.
+
+</p>
+<p>
+ All response parameters MUST describe the End User's current session
+ with the OpenID Provider.
+
+</p>
+<p>
+ </p>
+<ul class="text">
+<li>openid.ns.pape
+
+<blockquote class="text">
+<p>
+ Value: "http://specs.openid.net/extensions/pape/1.0"
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.pape.auth_policies
+
+<blockquote class="text">
+<p>
+ One or more authentication policy URIs that the OP conformed
+ to when authenticating the End User.
+
+</p>
+<p>
+ Value: Space separated list of authentication policy URIs.
+
+</p>
+<p>
+ Note: If no policies were met though the OP wishes to convey
+ other information in the response, this parameter MUST be
+ included with the value of "none".
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.pape.auth_time
+
+<blockquote class="text">
+<p>
+ (Optional) The most recent timestamp when the End User has
+ actively authenticated to the OP in a manner fitting the
+ asserted policies.
+
+</p>
+<p>
+ Value: The timestamp MUST be formatted as specified
+ in section 5.6 of <a class="info" href="#RFC3339">[RFC3339]<span> (</span><span class="info">Klyne, G. and C. Newman, “Date and Time on the Internet: Timestamps,” .</span><span>)</span></a>, with the
+ following restrictions:
+ </p>
+<ul class="text">
+<li>
+ All times must be in the UTC
+ timezone, indicated with a "Z".
+
+</li>
+<li>
+ No fractional seconds are allowed
+
+</li>
+</ul>
+ For example: 2005-05-15T17:11:51Z
+
+
+<p>
+ Note: If the RP's request included the "openid.max_auth_age"
+ parameter then the OP MUST include "openid.auth_time" in its
+ response. If "openid.max_auth_age" was not requested, the
+ OP MAY choose to include "openid.auth_time" in its response.
+
+</p>
+</blockquote>
+
+</li>
+<li>openid.pape.nist_auth_level
+
+<blockquote class="text">
+<p>
+ (Optional) The Assurance Level as defined by the National
+ Institute of Standards and Technology (NIST) in <a class="info" href="#NIST_SP800-63">Special Publication 800-63<span> (</span><span class="info">Burr, W., Dodson, D., and W. Polk, Ed., “Electronic Authentication Guideline,” April&nbsp;2006.</span><span>)</span></a> [NIST_SP800‑63]
+ corresponding to the authentication method and policies
+ employed by the OP when authenticating the End User.
+
+</p>
+<p>
+ Value: Integer value between 0 and 4 inclusive.
+
+</p>
+<p>
+ Note: Level 0 is not an assurance level defined by NIST, but
+ rather SHOULD be used to signify that the OP recognizes the
+ parameter and the End User authentication did not meet the
+ requirements of Level 1. See <a class="info" href="#NIST_Examples">Appendix&nbsp;A.1.2<span> (</span><span class="info">NIST Assurance Levels</span><span>)</span></a> for high-level example
+ classifications of authentication methods within the defined
+ levels.
+
+</p>
+</blockquote>
+
+</li>
+</ul><p>
+
+</p>
+<a name="anchor11"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6"></a><h3>6.&nbsp;
+Security Considerations</h3>
+
+<p>
+ As to commonly accepted security practices, it should be noted that
+ the overall strength of any authentication is only as strong as its
+ weakest step. It is thus recommended that provisioning of
+ phishing-resistant and other credentials stronger than shared secrets
+ should be accomplished using methods that are at least as strong as
+ the credential being provisioned. By counter-example, allowing people
+ to retrieve a phishing-resistant credential using only a phishable
+ shared secret negates much of the value provided by the
+ phishing-resistant credential itself.
+
+</p>
+<p>
+ OpenID Providers need to make smart decisions as to the level of
+ authentication that they assert the End User performed in comparison
+ to that requested by the Relying Party. For example, if the RP were to
+ request phishing-resistant authentication it may or may not make sense
+ for the OP to actually tell it that the End User did in fact perform
+ phishing-resistant, physical multi-factor, and NIST Level 2
+ authentication. While there are use cases where the OP should provide
+ the true strength of the authentication if it is above the request,
+ there are also use cases where the OP should only assert to the level
+ requested.
+
+</p>
+<p>
+ One example of the latter would be in an online banking scenario where
+ the End User is solely viewing their balance and thus the RP requests
+ phishing-resistant authentication. If the OP were to actually assert
+ that the user performed stronger authentication than requested,
+ additional access may be granted to the End User at the RP. While in
+ many cases this may be desired, in this scenario it increases the risk
+ in terms of if the End User were to not end their session with the RP
+ and leave their User-Agent unsecured. Rather by the OP only responding
+ to the level requested, and the RP making a second request for a
+ higher level when it is needed at the time, it can reduce the overall
+ risk. An example of this is that when working on Linux systems you do
+ not login as the "root" user at all times.
+
+</p>
+<a name="anchor12"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.6.1"></a><h3>6.1.&nbsp;
+NIST Assurance Levels</h3>
+
+<p>
+ Depending on the particular use case being satisfied by the
+ authentication response and PAPE information, the OpenID Provider
+ will have to make a decision, ideally with the consent of the End
+ User, as if it will include the "openid.pape.nist_auth_level"
+ parameter. This information is designed to give Relying Parties more
+ information around the strength of credentials used without actually
+ disclosing the specific credential type. Disclosing the specific
+ credential type can be considered a potential privacy or security
+ risk.
+
+</p>
+<p>
+ It is RECOMMENDED that this parameter always be included in the
+ response from the OP. This holds true even in cases where the End
+ User authentication does not meet one of the defined Authentication
+ Policies. For example, if the End User is authenticating using a
+ password via HTTPS there is still value to the RP in knowing if the
+ strength of the Password corresponds to the entropy requirements
+ laid out by Level 1 or 2 or that it does not even meet the minimum
+ requirement for the lowest level. With that said, discretion needs
+ to be used by OP's as conveying that one of their End User's has a
+ weak password to an "un-trustworthy" RP would not generally be
+ considered a good idea.
+
+</p>
+<a name="examples"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A"></a><h3>Appendix A.&nbsp;
+Examples</h3>
+
+<a name="anchor13"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.1"></a><h3>Appendix A.1.&nbsp;
+Authentication Method Classifications</h3>
+
+<p>
+ This non-normative section illustrates classification of various
+ common authentication methods and their respective conformance
+ within the defined policies and levels.
+
+</p>
+<a name="policy_examples"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.1.1"></a><h3>Appendix A.1.1.&nbsp;
+Authentication Policy Examples</h3>
+
+<p style="text-align: center;">
+ This table provides examples of common authentication
+ technologies and their mapping to the Authentication Policies
+ defined in <a class="info" href="#auth_policies">Section&nbsp;4<span> (</span><span class="info">Defined Authentication Policies</span><span>)</span></a>.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">Method</th><th align="left">Phishing-Resistant</th><th align="left">Multi-Factor</th><th align="left">Physical Multi-Factor</th></tr>
+<tr>
+<td align="left">Password via HTTPS</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and digital certificate via HTTPS</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and "soft" OTP token via HTTPS</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and "hard" OTP token via HTTPS</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">PIN and "hard" crypto token via HTTPS</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+</tbody></table>
+
+<p><a class="info" href="#comment.anchor14">[anchor14]<span> (</span><span class="info">Where does technology such as Vidoop or Passfaces fit into this table?</span><span>)</span></a><a name="anchor14"></a>
+</p>
+<a name="NIST_Examples"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.A.1.2"></a><h3>Appendix A.1.2.&nbsp;
+NIST Assurance Levels</h3>
+
+<p>
+ This section is designed to highlight the majority of referenced
+ information needed in the most commonly envisioned OpenID Provider
+ deployments. All normative and authoritative text can be found in
+ <a class="info" href="#NIST_SP800-63">[NIST_SP800‑63]<span> (</span><span class="info">Burr, W., Dodson, D., and W. Polk, Ed., “Electronic Authentication Guideline,” April&nbsp;2006.</span><span>)</span></a>.
+
+</p>
+<p style="text-align: center;">
+ This table is republished from page 39 of <a class="info" href="#NIST_SP800-63">[NIST_SP800‑63]<span> (</span><span class="info">Burr, W., Dodson, D., and W. Polk, Ed., “Electronic Authentication Guideline,” April&nbsp;2006.</span><span>)</span></a>.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">Token Type</th><th align="left">Level 1</th><th align="left">Level 2</th><th align="left">Level 3</th><th align="left">Level 4</th></tr>
+<tr>
+<td align="left">Hard crypto token</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">One-time password device</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">Soft crypto token</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">Passwords &amp; PINs</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+</tr>
+</tbody></table>
+
+<p style="text-align: center;">
+ This table is republished from page 39 of <a class="info" href="#NIST_SP800-63">[NIST_SP800‑63]<span> (</span><span class="info">Burr, W., Dodson, D., and W. Polk, Ed., “Electronic Authentication Guideline,” April&nbsp;2006.</span><span>)</span></a>.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">Protect Against</th><th align="left">Level 1</th><th align="left">Level 2</th><th align="left">Level 3</th><th align="left">Level 4</th></tr>
+<tr>
+<td align="left">On-line guessing</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">Replay</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">Eavesdropper</td>
+<td align="left">&nbsp;</td>
+<td align="left">X</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">Verifier impersonation</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">Man-in-the-middle</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">X</td>
+<td align="left">X</td>
+</tr>
+<tr>
+<td align="left">Session hijacking</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">X</td>
+</tr>
+</tbody></table>
+
+<p style="text-align: center;">
+ The following table illustrates the minimum number of factors
+ required at each assurance level.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left">
+<tbody><tr><th align="left">Level</th><th align="left">Factors</th></tr>
+<tr>
+<td align="left">1</td>
+<td align="left">1</td>
+</tr>
+<tr>
+<td align="left">2</td>
+<td align="left">1</td>
+</tr>
+<tr>
+<td align="left">3</td>
+<td align="left">2</td>
+</tr>
+<tr>
+<td align="left">4</td>
+<td align="left">2</td>
+</tr>
+</tbody></table>
+
+<p>
+ In all cases, implementing a commonly accepted nonce and
+ cross-site scripting protection when entering authentication
+ credentials is required to satisfy all four Assurance Levels. All
+ examples below assume this requirement is met.
+
+</p>
+<p>
+ It should be noted that NIST Assurance Levels 1 and 2 have
+ differing password entropy requirements. When working with
+ passwords, you should refer to the <a class="info" href="#NIST_SP800-63">[NIST_SP800‑63]<span> (</span><span class="info">Burr, W., Dodson, D., and W. Polk, Ed., “Electronic Authentication Guideline,” April&nbsp;2006.</span><span>)</span></a>
+ specification for more details. All examples below assume the
+ password meets these requirements.
+
+</p>
+<p style="text-align: center;">
+ This table provides examples of common authentication
+ technologies and their mapping to NIST Assurance Levels, please
+ be aware that there are details not represented in these
+ examples that may bear on the resulting Assurance Level.
+
+</p><table class="full" align="center" border="0" cellpadding="2" cellspacing="2">
+<col align="left"><col align="left"><col align="left"><col align="left"><col align="left">
+<tbody><tr><th align="left">Method</th><th align="left">Level 1</th><th align="left">Level 2</th><th align="left">Level 3</th><th align="left">Level 4</th></tr>
+<tr>
+<td align="left">Password via HTTP</td>
+<td align="left">Yes, if challenge-response</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">Password via HTTPS</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">&nbsp;</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and Digital Certificate via HTTPS</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and "soft" OTP token via HTTPS</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and "hard" OTP token via HTTPS</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">&nbsp;</td>
+</tr>
+<tr>
+<td align="left">PIN and "hard" crypto token via HTTPS</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">Yes</td>
+<td align="left">Yes, if FIPS 140-2 Level 2 crypto and Level 3 physical</td>
+</tr>
+</tbody></table>
+
+<a name="anchor15"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.B"></a><h3>Appendix B.&nbsp;
+Acknowledgements</h3>
+
+<p>
+ We'd like to thank Barry Ferg, Ben Laurie, Dick Hardt, Drummond Reed,
+ George Fletcher, Kim Cameron, and Mike Jones for their feedback when
+ drafting this specification. David Recordon would also like to
+ acknowledge VeriSign who employed him during the original authoring
+ of this specification.
+
+</p>
+<a name="rfc.references1"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>7.&nbsp;Normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="NIST_SP800-63">[NIST_SP800-63]</a></td>
+<td class="author-text">Burr, W., Dodson, D., and W. Polk, Ed., “<a href="http://csrc.nist.gov/publications/nistpubs/800-63/SP800-63V1_0_2.pdf">Electronic Authentication Guideline</a>,” April&nbsp;2006.</td></tr>
+<tr><td class="author-text" valign="top"><a name="OpenIDAuthentication2.0">[OpenIDAuthentication2.0]</a></td>
+<td class="author-text">specs@openid.net, “OpenID Authentication 2.0 - Draft 11,” 2007 (<a href="http://www.openid.net/specs/openid-authentication-2_0-11.txt">TXT</a>, <a href="http://www.openid.net/specs/openid-authentication-2_0-11.html">HTML</a>).</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2119">[RFC2119]</a></td>
+<td class="author-text">Bradner, B., “<a href="ftp://ftp.isi.edu/in-notes/rfc2119.txt">Key words for use in RFCs to Indicate Requirement Levels</a>,” RFC&nbsp;2119, 1997.</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC3339">[RFC3339]</a></td>
+<td class="author-text">Klyne, G. and C. Newman, “<a href="ftp://ftp.isi.edu/in-notes/rfc3339.txt">Date and Time on the Internet: Timestamps</a>,” RFC&nbsp;3339.</td></tr>
+<tr><td class="author-text" valign="top"><a name="Yadis">[Yadis]</a></td>
+<td class="author-text">Miller, J., Ed., “Yadis Specification 1.0,” 2005 (<a href="http://yadis.org/papers/yadis-v1.0.pdf">PDF</a>, <a href="http://yadis.org/papers/yadis-v1.0.odt">ODT</a>).</td></tr>
+</tbody></table>
+
+<a name="rfc.comments"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Editorial Comments</h3>
+<table border="0">
+<tbody><tr><td class="author-text" valign="top">
+<a class="info" href="#anchor6">
+anchor6</a><a name="comment.anchor6"></a>:
+</td><td class="author-text">
+There is ongoing discussion as to if a policy should be defined to
+represent technologies which help prevent phishing attacks though do
+not fit the phishing-resistant definition. Examples would be site seal
+technology, browser plugins specific to OpenID flows, and Internet
+Explorer 7's support for Extended Validation SSL certificates.</td></tr>
+<tr><td class="author-text" valign="top">
+<a class="info" href="#anchor7">
+anchor7</a><a name="comment.anchor7"></a>:
+</td><td class="author-text">
+There is ongoing discussion as to the best wording for this definition.
+The main spirit of this definition is that a user does not authenticate
+to the OP by providing a password by itself directly from within the
+User-Agent.</td></tr>
+<tr><td class="author-text" valign="top">
+<a class="info" href="#anchor14">
+anchor14</a><a name="comment.anchor14"></a>:
+</td><td class="author-text">
+Where does technology such as Vidoop or Passfaces fit into this table?</td></tr>
+</tbody></table>
+
+<a name="rfc.authors"></a><br><hr>
+<table summary="layout" class="TOCbug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="TOCbug"><a href="#toc">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Authors' Addresses</h3>
+<table border="0" cellpadding="0" cellspacing="0" width="99%">
+<tbody><tr><td class="author-text">&nbsp;</td>
+<td class="author-text">David Recordon</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Six Apart, Ltd.</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">548 4th Street</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">San Francisco, CA 94107</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">USA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:david@sixapart.com">david@sixapart.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://www.sixapart.com/">http://www.sixapart.com/</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Johnny Bufu (editor)</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Sxip Identity</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">798 Beatty Street</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Vancouver, BC V6B 2M1</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">CA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:johnny@sxip.com">johnny@sxip.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Jonathan Daugherty (editor)</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">JanRain</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">5331 SW Macadam Ave. #375</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Portland, OR 97239</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">US</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:cygnus@janrain.com">cygnus@janrain.com</a></td></tr>
+<tr><td class="author" align="right">URI:&nbsp;</td>
+<td class="author-text"><a href="http://janrain.com/">http://janrain.com/</a></td></tr>
+</tbody></table>
+
+</body></html> \ No newline at end of file
diff --git a/doc/specs/openid-simple-registration-extension-1_0.html b/doc/specs/openid-simple-registration-extension-1_0.html
new file mode 100644
index 0000000..f1bdde0
--- /dev/null
+++ b/doc/specs/openid-simple-registration-extension-1_0.html
@@ -0,0 +1,389 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en"><head><title>OpenID Simple Registration Extension 1.0</title>
+
+
+<meta http-equiv="Expires" content="Fri, 30 Jun 2006 13:13:42 +0000">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="description" content="OpenID Simple Registration Extension 1.0">
+<meta name="generator" content="xml2rfc v1.30 (http://xml.resource.org/)">
+<style type="text/css">
+<!--
+ body {
+ font-family: verdana, charcoal, helvetica, arial, sans-serif;
+ margin: 2em;
+ font-size: small ; color: #000000 ; background-color: #ffffff ; }
+ .title { color: #990000; font-size: x-large ;
+ font-weight: bold; text-align: right;
+ font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
+ background-color: transparent; }
+ .filename { color: #666666; font-size: 18px; line-height: 28px;
+ font-weight: bold; text-align: right;
+ font-family: helvetica, arial, sans-serif;
+ background-color: transparent; }
+ td.rfcbug { background-color: #000000 ; width: 30px ; height: 30px ;
+ text-align: justify; vertical-align: middle ; padding-top: 2px ; }
+ td.rfcbug span.RFC { color: #666666; font-weight: bold; text-decoration: none;
+ background-color: #000000 ;
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-size: x-small ; }
+ td.rfcbug span.hotText { color: #ffffff; font-weight: normal; text-decoration: none;
+ text-align: center ;
+ font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
+ font-size: x-small ; background-color: #000000; }
+ /* info code from SantaKlauss at http://www.madaboutstyle.com/tooltip2.html */
+ div#counter{margin-top: 100px}
+
+ a.info{
+ position:relative; /*this is the key*/
+ z-index:24;
+ text-decoration:none}
+
+ a.info:hover{z-index:25; background-color:#990000 ; color: #ffffff ;}
+
+ a.info span{display: none}
+
+ a.info:hover span.info{ /*the span will display just on :hover state*/
+ display:block;
+ position:absolute;
+ font-size: smaller ;
+ top:2em; left:2em; width:15em;
+ padding: 2px ;
+ border:1px solid #333333;
+ background-color:#eeeeee; color:#990000;
+ text-align: left ;}
+
+ A { font-weight: bold; }
+ A:link { color: #990000; background-color: transparent ; }
+ A:visited { color: #333333; background-color: transparent ; }
+ A:active { color: #333333; background-color: transparent ; }
+
+ p { margin-left: 2em; margin-right: 2em; }
+ p.copyright { font-size: x-small ; }
+ p.toc { font-size: small ; font-weight: bold ; margin-left: 3em ;}
+ table.toc { margin: 0 0 0 3em; padding: 0; border: 0; vertical-align: text-top; }
+ td.toc { font-size: small; font-weight: bold; vertical-align: text-top; }
+
+ span.emph { font-style: italic; }
+ span.strong { font-weight: bold; }
+ span.verb, span.vbare { font-family: "Courier New", Courier, monospace ; }
+
+ span.vemph { font-style: italic; font-family: "Courier New", Courier, monospace ; }
+ span.vstrong { font-weight: bold; font-family: "Courier New", Courier, monospace ; }
+ span.vdeluxe { font-weight: bold; font-style: italic; font-family: "Courier New", Courier, monospace ; }
+
+ ol.text { margin-left: 2em; margin-right: 2em; }
+ ul.text { margin-left: 2em; margin-right: 2em; }
+ li { margin-left: 3em; }
+
+ pre { margin-left: 3em; color: #333333; background-color: transparent;
+ font-family: "Courier New", Courier, monospace ; font-size: small ;
+ text-align: left;
+ }
+
+ h3 { color: #333333; font-size: medium ;
+ font-family: helvetica, arial, sans-serif ;
+ background-color: transparent; }
+ h4 { font-size: small; font-family: helvetica, arial, sans-serif ; }
+
+ table.bug { width: 30px ; height: 15px ; }
+ td.bug { color: #ffffff ; background-color: #990000 ;
+ text-align: center ; width: 30px ; height: 15px ;
+ }
+ td.bug A.link2 { color: #ffffff ; font-weight: bold;
+ text-decoration: none;
+ font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
+ font-size: x-small ; background-color: transparent }
+
+ td.header { color: #ffffff; font-size: x-small ;
+ font-family: arial, helvetica, sans-serif; vertical-align: top;
+ background-color: #666666 ; width: 33% ; }
+ td.author { font-weight: bold; margin-left: 4em; font-size: x-small ; }
+ td.author-text { font-size: x-small; }
+ table.full { vertical-align: top ; border-collapse: collapse ;
+ border-style: solid solid solid solid ;
+ border-color: black black black black ;
+ font-size: small ; text-align: center ; }
+ table.headers, table.none { vertical-align: top ; border-collapse: collapse ;
+ border-style: none;
+ font-size: small ; text-align: center ; }
+ table.full th { font-weight: bold ;
+ border-style: solid ;
+ border-color: black black black black ; }
+ table.headers th { font-weight: bold ;
+ border-style: none none solid none;
+ border-color: black black black black ; }
+ table.none th { font-weight: bold ;
+ border-style: none; }
+ table.full td {
+ border-style: solid solid solid solid ;
+ border-color: #333333 #333333 #333333 #333333 ; }
+ table.headers td, table.none td { border-style: none; }
+
+ hr { height: 1px }
+-->
+</style></head><body>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<table summary="layout" border="0" cellpadding="0" cellspacing="0" width="66%"><tbody><tr><td><table summary="layout" border="0" cellpadding="2" cellspacing="1" width="100%">
+<tbody><tr><td class="header"> </td><td class="header">J. Hoyt</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">J. Daugherty</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">JanRain</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">D. Recordon</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">VeriSign</td></tr>
+<tr><td class="header">&nbsp;</td><td class="header">June 30, 2006</td></tr>
+</tbody></table></td></tr></tbody></table>
+<div align="right"><span class="title"><br>OpenID Simple Registration Extension 1.0</span></div>
+
+<h3>Abstract</h3>
+
+<p>OpenID Simple Registation is an extension to the OpenID
+ Authentication protocol that allows for very light-weight
+ profile exchange. It is designed to pass eight commonly
+ requested pieces of information when an End User goes to
+ register a new account with a web service.
+</p><a name="toc"></a><br><hr>
+<h3>Table of Contents</h3>
+<p class="toc">
+<a href="#anchor1">1.</a>&nbsp;
+Requirements Notation<br>
+<a href="#anchor2">2.</a>&nbsp;
+Terminology<br>
+<a href="#anchor3">3.</a>&nbsp;
+Request Format<br>
+<a href="#response_format">4.</a>&nbsp;
+Response Format<br>
+<a href="#anchor4">5.</a>&nbsp;
+Security Considerations<br>
+<a href="#rfc.references1">6.</a>&nbsp;
+Normative References<br>
+<a href="#rfc.authors">§</a>&nbsp;
+Authors' Addresses<br>
+</p>
+<br clear="all">
+
+<a name="anchor1"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.1"></a><h3>1.&nbsp;Requirements Notation</h3>
+
+<p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
+ "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" in this document are to be interpreted as
+ described in <a class="info" href="#RFC2119">[RFC2119]<span> (</span><span class="info">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels,” .</span><span>)</span></a>.
+</p>
+<a name="anchor2"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.2"></a><h3>2.&nbsp;Terminology</h3>
+
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>End User:</dt>
+<dd>The actual human user who wants to
+ prove their Identity to a Consumer.
+</dd>
+<dt>Consumer:</dt>
+<dd>A web service that wants proof that
+ the End User owns the Claimed Identity.
+</dd>
+<dt>Identity Provider:</dt>
+<dd>Also called "IdP" or
+ "Server". This is the OpenID Authentication server
+ that a Consumer contacts for cryptographic proof that the
+ End User owns the Claimed Identity.
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor3"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.3"></a><h3>3.&nbsp;Request Format</h3>
+
+<p>The request parameters detailed here SHOULD be sent with
+ OpenID Authentication checkid_immediate or checkid_setup
+ requests.
+</p>
+<p>All of the following request fields are OPTIONAL, though
+ at least one of "openid.sreg.required" or "openid.sreg.optional"
+ MUST be specified in the request.
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.sreg.required:</dt>
+<dd>Comma-separated list of
+ field names which, if absent from the response, will
+ prevent the Consumer from completing the
+ registration without End User interation. The field names
+ are those that are specified in the <a class="info" href="#response_format">Response Format<span> (</span><span class="info">Response Format</span><span>)</span></a>, with the
+ "openid.sreg." prefix removed.
+</dd>
+<dt>openid.sreg.optional:</dt>
+<dd>Comma-separated list of
+ field names Fields that will be used by the Consumer, but
+ whose absence will not prevent the registration from
+ completing. The field names are those that are specified in
+ the <a class="info" href="#response_format">Response Format<span> (</span><span class="info">Response Format</span><span>)</span></a>,
+ with the "openid.sreg." prefix removed.
+</dd>
+<dt>openid.sreg.policy_url:</dt>
+<dd> A URL
+ which the Consumer provides to give the End User a
+ place to read about the how the profile data will be
+ used. The Identity Provider SHOULD display this URL to the End
+ User if it is given.
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="response_format"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.4"></a><h3>4.&nbsp;Response Format</h3>
+
+<p>The fields below SHOULD be included in the Identity Providers's
+ response when "openid.mode" is "id_res".
+</p>
+<p>The response's "openid.signed" field list MUST include the
+ returned registration field names, prefixed without the
+ openid. prefix (e.g., sreg.nickname). The "openid.sig" field
+ MUST provide a signature for the sreg. fields in addition to
+ the OpenID data according to the OpenID Authentication specification.
+</p>
+<p>If the Consumer's signature verification fails, then
+ no registration data from the Identity Provider SHOULD be used.
+</p>
+<p>The Consumer MUST be prepared to handle a response which
+ lacks fields marked as required or optional.
+</p>
+<p>The behavior in the case of missing required fields or extra,
+ unrequested fields is up to the Consumer. The Consumer
+ SHOULD treat this situation the same as it would if the End User
+ entered the data manually.
+</p>
+<p>A single field MUST NOT be repeated in the response, and all
+ included fields MUST be taken from the set of fields defined in
+ this specification.
+</p>
+<p>An Identity Provider MAY return any subset of the following
+ fields in response to the query. In particular:
+</p>
+<p>
+ </p>
+<blockquote class="text"><dl>
+<dt>openid.sreg.nickname:</dt>
+<dd>Any UTF-8 string that
+ the End User wants to use as a nickname.
+</dd>
+<dt>openid.sreg.email:</dt>
+<dd>The email address of the
+ End User as specified in section 3.4.1 of <a class="info" href="#RFC2822">[RFC2822]<span> (</span><span class="info">Resnick, P., “Internet Message Format,” .</span><span>)</span></a>.
+</dd>
+<dt>openid.sreg.fullname:</dt>
+<dd>UTF-8 string free text
+ representation of the End User's full name.
+</dd>
+<dt>openid.sreg.dob:</dt>
+<dd>The End User's date of
+ birth as YYYY-MM-DD. Any values whose representation uses
+ fewer than the specified number of digits should be
+ zero-padded. The length of this value MUST always be 10. If
+ the End User user does not want to reveal any particular
+ component of this value, it MUST be set to zero.
+ <br>
+
+ For instance, if a End User wants to specify that his
+ date of birth is in 1980, but not the month or day, the value
+ returned SHALL be "1980-00-00".
+</dd>
+<dt>openid.sreg.gender:</dt>
+<dd>The End User's gender,
+ "M" for male, "F" for female.
+</dd>
+<dt>openid.sreg.postcode:</dt>
+<dd>UTF-8 string free text that
+ SHOULD conform to the End User's country's postal system.
+</dd>
+<dt>openid.sreg.country:</dt>
+<dd>The
+ End User's country of residence as specified by <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/index.html">ISO3166</a>.
+</dd>
+<dt>openid.sreg.language:</dt>
+<dd>End User's preferred
+ language as specified by <a href="http://www.w3.org/WAI/ER/IG/ert/iso639.htm">ISO639</a>.
+</dd>
+<dt>openid.sreg.timezone:</dt>
+<dd>ASCII string from <a href="http://www.twinsun.com/tz/tz-link.htm">TimeZone
+ database</a>
+ <br>
+
+ For example, "Europe/Paris" or "America/Los_Angeles".
+</dd>
+</dl></blockquote><p>
+
+</p>
+<a name="anchor4"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<a name="rfc.section.5"></a><h3>5.&nbsp;Security Considerations</h3>
+
+<p>None.
+</p>
+<a name="rfc.references1"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>6.&nbsp;Normative References</h3>
+<table border="0" width="99%">
+<tbody><tr><td class="author-text" valign="top"><a name="RFC2119">[RFC2119]</a></td>
+<td class="author-text">Bradner, B., “Key words for use in RFCs to Indicate Requirement Levels.”</td></tr>
+<tr><td class="author-text" valign="top"><a name="RFC2822">[RFC2822]</a></td>
+<td class="author-text">Resnick, P., “Internet Message Format.”</td></tr>
+<tr><td class="author-text" valign="top"><a name="openid_authentication">[openid_authentication]</a></td>
+<td class="author-text">Recordon, D. and B. Fitzpatrick, “OpenID Authentication 1.1.”</td></tr>
+</tbody></table>
+
+<a name="rfc.authors"></a><br><hr>
+<table summary="layout" class="bug" align="right" cellpadding="0" cellspacing="2"><tbody><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></tbody></table>
+<h3>Authors' Addresses</h3>
+<table border="0" cellpadding="0" cellspacing="0" width="99%">
+<tbody><tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Josh Hoyt</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">JanRain, Inc.</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">5331 SW Macadam Avenue</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Suite #375</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Portland, OR 97239</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">USA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:josh@janrain.com">josh@janrain.com</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Jonathan Daugherty</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">JanRain, Inc.</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">5331 SW Macadam Avenue</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Suite #375</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Portland, OR 97239</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">USA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:jonathan@janrain.com">jonathan@janrain.com</a></td></tr>
+<tr cellpadding="3"><td>&nbsp;</td><td>&nbsp;</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">David
+ Recordon</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">VeriSign, Inc.</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">487 E Middlefield Road</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">Mountain View, CA 94109</td></tr>
+<tr><td class="author-text">&nbsp;</td>
+<td class="author-text">USA</td></tr>
+<tr><td class="author" align="right">Email:&nbsp;</td>
+<td class="author-text"><a href="mailto:drecordon@verisign.com">drecordon@verisign.com</a></td></tr>
+</tbody></table>
+
+</body></html> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 4469c17..6e294e5 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -102,11 +102,13 @@
<Compile Include="OpenId\Messages\AssociateUnsuccessfulResponseTests.cs" />
<Compile Include="OpenId\Messages\AssociateUnencryptedResponseTests.cs" />
<Compile Include="OpenId\ChannelElements\OpenIdChannelTests.cs" />
+ <Compile Include="OpenId\Messages\CheckIdRequestTests.cs" />
<Compile Include="OpenId\Messages\DirectErrorResponseTests.cs" />
<Compile Include="OpenId\Messages\IndirectErrorResponseTests.cs" />
<Compile Include="OpenId\OpenIdCoordinator.cs" />
<Compile Include="OpenId\AssociationHandshakeTests.cs" />
<Compile Include="OpenId\OpenIdTestBase.cs" />
+ <Compile Include="OpenId\RealmTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Messaging\ResponseTests.cs" />
<Compile Include="OAuth\AppendixScenarios.cs" />
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
index 054a149..7743ccc 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
@@ -35,6 +35,74 @@ namespace DotNetOpenAuth.Test.OpenId {
}
/// <summary>
+ /// Verifies that the RP and OP can renegotiate an association type if the RP's
+ /// initial request for an association is for a type the OP doesn't support.
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateRenegotiateBitLength() {
+ // TODO: test where the RP asks for an association type that the OP doesn't support
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies that the RP cannot get caught in an infinite loop if a bad OP
+ /// keeps sending it association retry messages.
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateRenegotiateBitLengthRPStopsAfterOneRetry() {
+ // TODO: code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies security settings limit RP's initial associate request
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateRequestDeterminedBySecuritySettings() {
+ // TODO: Code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies security settings limit RP's acceptance of OP's counter-suggestion
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateRenegotiateLimitedByRPSecuritySettings() {
+ // TODO: Code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies security settings limit OP's set of acceptable association types.
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateLimitedByOPSecuritySettings() {
+ // TODO: Code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies the RP can recover with no association after receiving an
+ /// associate error response from the OP when no suggested association
+ /// type is included.
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateContinueAfterOpenIdError() {
+ // TODO: Code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Verifies that the RP can recover from an invalid or non-existent
+ /// response from the OP, for example in the HTTP timeout case.
+ /// </summary>
+ [TestMethod, Ignore]
+ public void AssociateContinueAfterHttpError() {
+ // TODO: Code here
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
/// Runs a parameterized association flow test using all supported OpenID versions.
/// </summary>
/// <param name="opEndpoint">The OP endpoint to simulate using.</param>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs
new file mode 100644
index 0000000..0f970f9
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs
@@ -0,0 +1,105 @@
+//-----------------------------------------------------------------------
+// <copyright file="CheckIdRequestTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.OpenId.Messages;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.Messaging;
+
+ [TestClass]
+ public class CheckIdRequestTests : OpenIdTestBase {
+ private Uri ProviderEndpoint;
+ private CheckIdRequest immediatev1;
+ private CheckIdRequest setupv1;
+ private CheckIdRequest immediatev2;
+ private CheckIdRequest setupv2;
+
+
+ [TestInitialize]
+ public override void SetUp() {
+ base.SetUp();
+
+ ProviderEndpoint = new Uri("http://host");
+
+ immediatev1 = new CheckIdRequest(Protocol.V11.Version, ProviderEndpoint, true);
+ setupv1 = new CheckIdRequest(Protocol.V11.Version, ProviderEndpoint, false);
+
+ immediatev2 = new CheckIdRequest(Protocol.V20.Version, ProviderEndpoint, true);
+ setupv2 = new CheckIdRequest(Protocol.V20.Version, ProviderEndpoint, false);
+
+ // Prepare all message versions so that they SHOULD be valid by default.
+ // In particular, V1 messages require ReturnTo.
+ immediatev1.ReturnTo = new Uri("http://returnto/");
+ setupv1.ReturnTo = new Uri("http://returnto/");
+
+ try {
+ immediatev1.EnsureValidMessage();
+ setupv1.EnsureValidMessage();
+ immediatev2.EnsureValidMessage();
+ setupv2.EnsureValidMessage();
+ } catch (ProtocolException ex) {
+ Assert.Inconclusive("All messages ought to be valid before tests run, but got: {0}", ex.Message);
+ }
+ }
+
+ /// <summary>
+ /// Tests that having <see cref="CheckIdRequest.ClaimedIdentifier"/> set without
+ /// <see cref="CheckIdRequest.LocalIdentifier"/> set is recognized as an error in OpenID 2.x.
+ /// </summary>
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void ClaimedIdentifierWithoutIdentity() {
+ setupv2.ClaimedIdentifier = "http://andrew.arnott.myopenid.com/";
+ setupv2.EnsureValidMessage();
+ }
+
+ /// <summary>
+ /// Tests that having <see cref="CheckIdRequest.LocalIdentifier"/> set without
+ /// <see cref="CheckIdRequest.ClaimedIdentifier"/> set is recognized as an error in OpenID 2.x.
+ /// </summary>
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void LocalIdentifierWithoutClaimedIdentifier() {
+ setupv2.LocalIdentifier = "http://andrew.arnott.myopenid.com/";
+ setupv2.EnsureValidMessage();
+ }
+
+ /// <summary>
+ /// Tests that having <see cref="CheckIdRequest.LocalIdentifier"/> set without
+ /// <see cref="CheckIdRequest.ClaimedIdentifier"/> set is recognized as valid in OpenID 1.x.
+ /// </summary>
+ [TestMethod]
+ public void LocalIdentifierWithoutClaimedIdentifierV1() {
+ setupv1.LocalIdentifier = "http://andrew.arnott.myopenid.com/";
+ setupv1.EnsureValidMessage();
+ }
+
+ /// <summary>
+ /// Verifies that the validation check throws if the return_to and the realm
+ /// values are not compatible.
+ /// </summary>
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void RealmReturnToMismatchV2() {
+ setupv2.Realm = "http://somehost/";
+ setupv2.ReturnTo = new Uri("http://someotherhost/");
+ setupv2.EnsureValidMessage();
+ }
+
+ /// <summary>
+ /// Verifies that the validation check throws if the return_to and the realm
+ /// values are not compatible.
+ /// </summary>
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void RealmReturnToMismatchV1() {
+ setupv1.Realm = "http://somehost/";
+ setupv1.ReturnTo = new Uri("http://someotherhost/");
+ setupv1.EnsureValidMessage();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs
new file mode 100644
index 0000000..5d59ded
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs
@@ -0,0 +1,224 @@
+//-----------------------------------------------------------------------
+// <copyright file="RealmTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test
+{
+ using System;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.OpenId;
+
+ [TestClass]
+ public class RealmTests
+ {
+ [TestMethod]
+ public void ValidRealmsTest()
+ {
+ // Just create these. If any are determined to be invalid,
+ // an exception should be thrown that would fail this test.
+ new Realm("http://www.myopenid.com");
+ new Realm("http://www.myopenid.com/");
+ new Realm("http://www.myopenid.com:5221/");
+ new Realm("https://www.myopenid.com");
+ new Realm("http://www.myopenid.com/abc");
+ new Realm("http://www.myopenid.com/abc/");
+ new Realm("http://*.myopenid.com/");
+ new Realm("http://*.com/");
+ new Realm("http://*.guest.myopenid.com/");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void InvalidRealmNullString()
+ {
+ new Realm((string)null);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void InvalidRealmNullUri() {
+ new Realm((Uri)null);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmEmpty()
+ {
+ new Realm(string.Empty);
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmBadProtocol()
+ {
+ new Realm("asdf://www.microsoft.com/");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmNoScheme()
+ {
+ new Realm("www.guy.com");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmBadWildcard1()
+ {
+ new Realm("http://*www.my.com");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmBadWildcard2() {
+ new Realm("http://www.*.com");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmBadWildcard3() {
+ new Realm("http://www.my.*/");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmTwoWildcards1()
+ {
+ new Realm("http://**.my.com");
+ }
+
+ [TestMethod]
+ [ExpectedException(typeof(UriFormatException))]
+ public void InvalidRealmTwoWildcards2()
+ {
+ new Realm("http://*.*.my.com");
+ }
+
+ [TestMethod]
+ public void IsSaneTest()
+ {
+ Assert.IsTrue(new Realm("http://www.myopenid.com").IsSane);
+ Assert.IsTrue(new Realm("http://myopenid.com").IsSane);
+ Assert.IsTrue(new Realm("http://localhost").IsSane);
+ Assert.IsTrue(new Realm("http://localhost:33532/dab").IsSane);
+ Assert.IsTrue(new Realm("http://www.myopenid.com").IsSane);
+
+ Assert.IsFalse(new Realm("http://*.com").IsSane);
+ Assert.IsFalse(new Realm("http://*.co.uk").IsSane);
+ }
+
+ [TestMethod]
+ public void IsUrlWithinRealmTests()
+ {
+ /*
+ * The openid.return_to URL MUST descend from the openid.trust_root, or the
+ * Identity Provider SHOULD return an error. Namely, the URL scheme and port
+ * MUST match. The path, if present, MUST be equal to or below the value of
+ * openid.trust_root, and the domains on both MUST match, or, the
+ * openid.trust_root value contain a wildcard like http://*.example.com.
+ * The wildcard SHALL only be at the beginning. It is RECOMMENDED Identity
+ * Provider's protect their End Users from requests for things like
+ * http://*.com/ or http://*.co.uk/.
+ */
+
+ // Schemes must match
+ Assert.IsFalse(new Realm("https://www.my.com/").Contains("http://www.my.com/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("https://www.my.com/"));
+
+ // Ports must match
+ Assert.IsTrue(new Realm("http://www.my.com/").Contains("http://www.my.com:80/boo"));
+ Assert.IsTrue(new Realm("http://www.my.com:80/").Contains("http://www.my.com/boo"));
+ Assert.IsFalse(new Realm("http://www.my.com:79/").Contains("http://www.my.com/boo"));
+ Assert.IsFalse(new Realm("https://www.my.com/").Contains("http://www.my.com:79/boo"));
+
+ // Path must be (at or) below trust root
+ Assert.IsTrue(new Realm("http://www.my.com/").Contains("http://www.my.com/"));
+ Assert.IsTrue(new Realm("http://www.my.com/").Contains("http://www.my.com/boo"));
+ Assert.IsTrue(new Realm("http://www.my.com/p/").Contains("http://www.my.com/p/l"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah").Contains("http://www.my.com/bah/bah"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah").Contains("http://www.my.com/bah/bah"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah.html").Contains("http://www.my.com/bah.html/bah"));
+ Assert.IsFalse(new Realm("http://www.my.com/bah").Contains("http://www.my.com/bahbah"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah").Contains("http://www.my.com/bah?q=a"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah?q=a").Contains("http://www.my.com/bah?q=a"));
+ Assert.IsTrue(new Realm("http://www.my.com/bah?a=b&c=d").Contains("http://www.my.com/bah?a=b&c=d&e=f"));
+ Assert.IsFalse(new Realm("http://www.my.com/bah?a=b&c=d").Contains("http://www.my.com/bah?a=b"));
+
+ // Domains MUST match
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://yours.com/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://www.yours.com/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://q.www.my.com/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://wwww.my.com/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://www.my.com.uk/"));
+ Assert.IsFalse(new Realm("http://www.my.com/").Contains("http://www.my.comm/"));
+
+ // Allow for wildcards
+ Assert.IsTrue(new Realm("http://*.www.my.com/").Contains("http://bah.www.my.com/"));
+ Assert.IsTrue(new Realm("http://*.www.my.com/").Contains("http://bah.WWW.MY.COM/"));
+ Assert.IsTrue(new Realm("http://*.www.my.com/").Contains("http://bah.www.my.com/boo"));
+ Assert.IsTrue(new Realm("http://*.my.com/").Contains("http://bah.www.my.com/boo"));
+ Assert.IsTrue(new Realm("http://*.my.com/").Contains("http://my.com/boo"));
+ Assert.IsFalse(new Realm("http://*.my.com/").Contains("http://ohmeohmy.com/"));
+ Assert.IsFalse(new Realm("http://*.my.com/").Contains("http://me.com/"));
+ Assert.IsFalse(new Realm("http://*.my.com/").Contains("http://my.co/"));
+ Assert.IsFalse(new Realm("http://*.my.com/").Contains("http://com/"));
+ Assert.IsFalse(new Realm("http://*.www.my.com/").Contains("http://my.com/"));
+ Assert.IsFalse(new Realm("http://*.www.my.com/").Contains("http://zzz.my.com/"));
+ // These are tested against by the constructor test, as these are invalid wildcard positions.
+ ////Assert.IsFalse(new Realm("http://*www.my.com/").ValidateUrl("http://bah.www.my.com/"));
+ ////Assert.IsFalse(new Realm("http://*www.my.com/").ValidateUrl("http://wwww.my.com/"));
+
+ // Among those that should return true, mix up character casing to test for case sensitivity.
+ // Host names should be case INSENSITIVE, but paths should probably be case SENSITIVE,
+ // because in some systems they are case sensitive and to ignore this would open
+ // security holes.
+ Assert.IsTrue(new Realm("http://www.my.com/").Contains("http://WWW.MY.COM/"));
+ Assert.IsFalse(new Realm("http://www.my.com/abc").Contains("http://www.my.com/ABC"));
+ }
+
+ [TestMethod]
+ public void ImplicitConversionFromStringTests() {
+ Realm realm = "http://host";
+ Assert.AreEqual("host", realm.Host);
+ realm = (string)null;
+ Assert.IsNull(realm);
+ }
+
+ [TestMethod]
+ public void ImplicitConversionToStringTests() {
+ Realm realm = new Realm("http://host/");
+ string realmString = realm;
+ Assert.AreEqual("http://host/", realmString);
+ realm = null;
+ realmString = realm;
+ Assert.IsNull(realmString);
+ }
+
+ [TestMethod]
+ public void ImplicitConverstionFromUriTests() {
+ Uri uri = new Uri("http://host");
+ Realm realm = uri;
+ Assert.AreEqual(uri.Host, realm.Host);
+ uri = null;
+ realm = uri;
+ Assert.IsNull(realm);
+ }
+
+ [TestMethod]
+ public void EqualsTest()
+ {
+ Realm testRealm1a = new Realm("http://www.yahoo.com");
+ Realm testRealm1b = new Realm("http://www.yahoo.com");
+ Realm testRealm2 = new Realm("http://www.yahoo.com/b");
+ Realm testRealm3 = new Realm("http://*.www.yahoo.com");
+
+ Assert.AreEqual(testRealm1a, testRealm1b);
+ Assert.AreNotEqual(testRealm1a, testRealm2);
+ Assert.AreNotEqual(testRealm1a, null);
+ Assert.AreNotEqual(testRealm1a, testRealm1a.ToString(), "Although the URLs are equal, different object types shouldn't be equal.");
+ Assert.AreNotEqual(testRealm3, testRealm1a, "Wildcard difference ignored by Equals");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index a31ac97..2656006 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -14,9 +14,14 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
ProjectSection(SolutionItems) = preProject
..\doc\specs\OAuth Core 1.0.htm = ..\doc\specs\OAuth Core 1.0.htm
+ ..\doc\specs\openid-attribute-exchange-1_0.html = ..\doc\specs\openid-attribute-exchange-1_0.html
+ ..\doc\specs\openid-authentication-1_1.html = ..\doc\specs\openid-authentication-1_1.html
+ ..\doc\specs\openid-authentication-2_0.html = ..\doc\specs\openid-authentication-2_0.html
+ ..\doc\specs\openid-provider-authentication-policy-extension-1_0-02.html = ..\doc\specs\openid-provider-authentication-policy-extension-1_0-02.html
+ ..\doc\specs\openid-simple-registration-extension-1_0.html = ..\doc\specs\openid-simple-registration-extension-1_0.html
EndProjectSection
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Consumer", "..\samples\Consumer", "{F9076F04-17AF-4205-93A2-1D3BEBFCDAEB}"
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Consumer", "..\samples\Consumer\", "{F9076F04-17AF-4205-93A2-1D3BEBFCDAEB}"
ProjectSection(WebsiteProperties) = preProject
TargetFramework = "3.5"
ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;{AA78D112-D889-414B-A7D4-467B34C7B663}|DotNetOpenAuth.ApplicationBlock.dll;"
@@ -45,7 +50,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B4C6
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsumerWpf", "..\samples\ConsumerWpf\ConsumerWpf.csproj", "{6EC36418-DBC5-4AD1-A402-413604AA7A08}"
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "ServiceProvider", "..\samples\ServiceProvider", "{EC910270-AAB6-4AC6-9B57-99118CFBE557}"
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "ServiceProvider", "..\samples\ServiceProvider\", "{EC910270-AAB6-4AC6-9B57-99118CFBE557}"
ProjectSection(WebsiteProperties) = preProject
TargetFramework = "3.5"
ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;"
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 0da6de6..0d143eb 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -163,6 +163,8 @@
<Compile Include="OpenId\ChannelElements\OpenIdChannel.cs" />
<Compile Include="OpenId\ChannelElements\OpenIdMessageFactory.cs" />
<Compile Include="OpenId\Configuration.cs" />
+ <Compile Include="OpenId\Messages\CheckIdRequest.cs" />
+ <Compile Include="OpenId\Realm.cs" />
<Compile Include="OpenId\RelyingPartyDescription.cs" />
<Compile Include="OpenId\DiffieHellmanUtilities.cs" />
<Compile Include="OpenId\DiffieHellman\DHKeyGeneration.cs" />
diff --git a/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs
new file mode 100644
index 0000000..034dd65
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs
@@ -0,0 +1,154 @@
+//-----------------------------------------------------------------------
+// <copyright file="CheckIdRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// An authentication request from a Relying Party to a Provider.
+ /// </summary>
+ /// <remarks>
+ /// This message type satisfies OpenID 2.0 section 9.1.
+ /// </remarks>
+ [DebuggerDisplay("OpenID {ProtocolVersion} {Mode} {ClaimedIdentifier}")]
+ internal class CheckIdRequest : RequestBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CheckIdRequest"/> class.
+ /// </summary>
+ /// <param name="version">The OpenID version to use.</param>
+ /// <param name="providerEndpoint">The Provider endpoint that receives this message.</param>
+ /// <param name="immediate">
+ /// <c>true</c> for asynchronous javascript clients;
+ /// <c>false</c> to allow the Provider to interact with the user in order to complete authentication.
+ /// </param>
+ internal CheckIdRequest(Version version, Uri providerEndpoint, bool immediate) :
+ base(version, providerEndpoint, GetMode(version, immediate), DotNetOpenAuth.Messaging.MessageTransport.Indirect) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Claimed Identifier.
+ /// </summary>
+ /// <remarks>
+ /// <para>"openid.claimed_id" and "openid.identity" SHALL be either both present or both absent.
+ /// If neither value is present, the assertion is not about an identifier,
+ /// and will contain other information in its payload, using extensions (Extensions). </para>
+ /// <para>It is RECOMMENDED that OPs accept XRI identifiers with or without the "xri://" prefix, as specified in the Normalization (Normalization) section. </para>
+ /// </remarks>
+ [MessagePart("openid.claimed_id", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
+ internal string ClaimedIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the OP Local Identifier.
+ /// </summary>
+ /// <value>The OP-Local Identifier. </value>
+ /// <remarks>
+ /// <para>If a different OP-Local Identifier is not specified, the claimed
+ /// identifier MUST be used as the value for openid.identity.</para>
+ /// <para>Note: If this is set to the special value
+ /// "http://specs.openid.net/auth/2.0/identifier_select" then the OP SHOULD
+ /// choose an Identifier that belongs to the end user. This parameter MAY
+ /// be omitted if the request is not about an identifier (for instance if
+ /// an extension is in use that makes the request meaningful without it;
+ /// see openid.claimed_id above). </para>
+ /// </remarks>
+ [MessagePart("openid.identity", IsRequired = false, AllowEmpty = false)]
+ internal string LocalIdentifier { get; set; }
+
+ /// <summary>
+ /// Gets or sets the handle of the association the RP would like the Provider
+ /// to use for signing a positive assertion in the response message.
+ /// </summary>
+ /// <value>A handle for an association between the Relying Party and the OP
+ /// that SHOULD be used to sign the response. </value>
+ /// <remarks>
+ /// If no association handle is sent, the transaction will take place in Stateless Mode
+ /// (Verifying Directly with the OpenID Provider).
+ /// </remarks>
+ [MessagePart("openid.assoc_handle", IsRequired = false, AllowEmpty = false)]
+ internal string AssociationHandle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the URL the Provider should redirect the user agent to following
+ /// the authentication attempt.
+ /// </summary>
+ /// <value>URL to which the OP SHOULD return the User-Agent with the response
+ /// indicating the status of the request.</value>
+ /// <remarks>
+ /// <para>If this value is not sent in the request it signifies that the Relying Party
+ /// does not wish for the end user to be returned. </para>
+ /// <para>The return_to URL MAY be used as a mechanism for the Relying Party to attach
+ /// context about the authentication request to the authentication response.
+ /// This document does not define a mechanism by which the RP can ensure that query
+ /// parameters are not modified by outside parties; such a mechanism can be defined
+ /// by the RP itself. </para>
+ /// </remarks>
+ [MessagePart("openid.return_to", IsRequired = true, AllowEmpty = false)]
+ [MessagePart("openid.return_to", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
+ internal Uri ReturnTo { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Relying Party discovery URL the Provider may use to verify the
+ /// source of the authentication request.
+ /// </summary>
+ /// <value>
+ /// URL pattern the OP SHOULD ask the end user to trust. See Section 9.2 (Realms).
+ /// This value MUST be sent if openid.return_to is omitted.
+ /// Default: The <see cref="ReturnTo"/> URL.
+ /// </value>
+ [MessagePart("openid.trust_root", IsRequired = false, AllowEmpty = false)]
+ [MessagePart("openid.realm", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
+ internal Realm Realm { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ public override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+
+ if (this.ProtocolVersion.Major >= 2) {
+ ErrorUtilities.VerifyProtocol((this.ClaimedIdentifier == null) == (this.LocalIdentifier == null), OpenIdStrings.ClaimedIdAndLocalIdMustBothPresentOrAbsent);
+ }
+
+ if (this.Realm == null) {
+ // Set the default Realm per the spec if it is not explicitly given.
+ this.Realm = this.ReturnTo;
+ } else if (this.ReturnTo != null) {
+ // Verify that the realm and return_to agree.
+ ErrorUtilities.VerifyProtocol(this.Realm.Contains(this.ReturnTo), OpenIdStrings.ReturnToNotUnderRealm, this.ReturnTo, this.Realm);
+ }
+ }
+
+ /// <summary>
+ /// Gets the value of the openid.mode parameter based on the protocol version and immediate flag.
+ /// </summary>
+ /// <param name="version">The OpenID version to use.</param>
+ /// <param name="immediate">
+ /// <c>true</c> for asynchronous javascript clients;
+ /// <c>false</c> to allow the Provider to interact with the user in order to complete authentication.
+ /// </param>
+ /// <returns>checkid_immediate or checkid_setup</returns>
+ private static string GetMode(Version version, bool immediate) {
+ ErrorUtilities.VerifyArgumentNotNull(version, "version");
+
+ Protocol protocol = Protocol.Lookup(version);
+ return immediate ? protocol.Args.Mode.checkid_immediate : protocol.Args.Mode.checkid_setup;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index 4924d68..d6b6de0 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
@@ -88,6 +88,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The openid.claimed_id and openid.identity parameters must both be present or both be absent..
+ /// </summary>
+ internal static string ClaimedIdAndLocalIdMustBothPresentOrAbsent {
+ get {
+ return ResourceManager.GetString("ClaimedIdAndLocalIdMustBothPresentOrAbsent", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}.
/// </summary>
internal static string DiffieHellmanRequiredPropertiesNotSet {
@@ -115,6 +124,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The scheme must be http or https but was &apos;{0}&apos;..
+ /// </summary>
+ internal static string InvalidScheme {
+ get {
+ return ResourceManager.GetString("InvalidScheme", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The list of keys do not match the provided dictionary..
/// </summary>
internal static string KeysListAndDictionaryDoNotMatch {
@@ -158,5 +176,14 @@ namespace DotNetOpenAuth.OpenId {
return ResourceManager.GetString("NoSessionTypeFound", resourceCulture);
}
}
+
+ /// <summary>
+ /// Looks up a localized string similar to return_to &apos;{0}&apos; not under realm &apos;{1}&apos;..
+ /// </summary>
+ internal static string ReturnToNotUnderRealm {
+ get {
+ return ResourceManager.GetString("ReturnToNotUnderRealm", resourceCulture);
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index 3df53ac..aae4bad 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -126,6 +126,9 @@
<data name="BadAssociationPrivateData" xml:space="preserve">
<value>The private data supplied does not meet the requirements of any known Association type. Its length may be too short, or it may have been corrupted.</value>
</data>
+ <data name="ClaimedIdAndLocalIdMustBothPresentOrAbsent" xml:space="preserve">
+ <value>The openid.claimed_id and openid.identity parameters must both be present or both be absent.</value>
+ </data>
<data name="DiffieHellmanRequiredPropertiesNotSet" xml:space="preserve">
<value>The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}</value>
</data>
@@ -135,6 +138,9 @@
<data name="InvalidKeyValueFormCharacterMissing" xml:space="preserve">
<value>Cannot decode Key-Value Form because a line was found without a '{0}' character. (line {1}: '{2}')</value>
</data>
+ <data name="InvalidScheme" xml:space="preserve">
+ <value>The scheme must be http or https but was '{0}'.</value>
+ </data>
<data name="KeysListAndDictionaryDoNotMatch" xml:space="preserve">
<value>The list of keys do not match the provided dictionary.</value>
</data>
@@ -150,4 +156,7 @@
<data name="NoSessionTypeFound" xml:space="preserve">
<value>Diffie-Hellman session type '{0}' not found for OpenID {1}.</value>
</data>
+ <data name="ReturnToNotUnderRealm" xml:space="preserve">
+ <value>return_to '{0}' not under realm '{1}'.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs
new file mode 100644
index 0000000..80c0188
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Realm.cs
@@ -0,0 +1,339 @@
+//-----------------------------------------------------------------------
+// <copyright file="Realm.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Globalization;
+ using System.Text.RegularExpressions;
+ using System.Xml;
+ using DotNetOpenAuth.OpenId.Provider;
+
+ /// <summary>
+ /// A trust root to validate requests and match return URLs against.
+ /// </summary>
+ /// <remarks>
+ /// This fills the OpenID Authentication 2.0 specification for realms.
+ /// See http://openid.net/specs/openid-authentication-2_0.html#realms
+ /// </remarks>
+ public class Realm {
+ /// <summary>
+ /// Implicitly converts the string-form of a URI to a <see cref="Realm"/> object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings")]
+ [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads")]
+ public static implicit operator Realm(string uri) {
+ return uri != null ? new Realm(uri) : null;
+ }
+
+ /// <summary>
+ /// Implicitly converts a <see cref="Uri"/> to a <see cref="Realm"/> object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings")]
+ public static implicit operator Realm(Uri uri) {
+ return uri != null ? new Realm(uri.AbsoluteUri) : null;
+ }
+
+ /// <summary>
+ /// Implicitly converts a <see cref="Realm"/> object to its <see cref="String"/> form.
+ /// </summary>
+ public static implicit operator string(Realm realm) {
+ return realm != null ? realm.ToString() : null;
+ }
+
+ /// <summary>
+ /// Instantiates a <see cref="Realm"/> from its string representation.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads"), SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
+ public Realm(string realmUrl) {
+ if (realmUrl == null) throw new ArgumentNullException("realmUrl");
+ DomainWildcard = Regex.IsMatch(realmUrl, wildcardDetectionPattern);
+ uri = new Uri(Regex.Replace(realmUrl, wildcardDetectionPattern, m => m.Groups[1].Value));
+ if (!uri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase) &&
+ !uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
+ throw new UriFormatException(string.Format(CultureInfo.CurrentCulture,
+ OpenIdStrings.InvalidScheme, uri.Scheme));
+ }
+
+ /// <summary>
+ /// Instantiates a <see cref="Realm"/> from its <see cref="Uri"/> representation.
+ /// </summary>
+ public Realm(Uri realmUrl) {
+ if (realmUrl == null) throw new ArgumentNullException("realmUrl");
+ uri = realmUrl;
+ if (!uri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase) &&
+ !uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
+ throw new UriFormatException(string.Format(CultureInfo.CurrentCulture,
+ OpenIdStrings.InvalidScheme, uri.Scheme));
+ }
+
+ /// <summary>
+ /// Instantiates a <see cref="Realm"/> from its <see cref="UriBuilder"/> representation.
+ /// </summary>
+ /// <remarks>
+ /// This is useful because UriBuilder can construct a host with a wildcard
+ /// in the Host property, but once there it can't be converted to a Uri.
+ /// </remarks>
+ internal Realm(UriBuilder realmUriBuilder)
+ : this(safeUriBuilderToString(realmUriBuilder)) { }
+ static string safeUriBuilderToString(UriBuilder realmUriBuilder) {
+ if (realmUriBuilder == null) throw new ArgumentNullException("realmUriBuilder");
+ // Note: we MUST use ToString. Uri property throws if wildcard is present.
+ return realmUriBuilder.ToString();
+ }
+
+ Uri uri;
+ const string wildcardDetectionPattern = @"^(\w+://)\*\.";
+
+ /// <summary>
+ /// Whether a '*.' prefix to the hostname is used in the realm to allow
+ /// subdomains or hosts to be added to the URL.
+ /// </summary>
+ public bool DomainWildcard { get; private set; }
+
+ /// <summary>
+ /// Gets the host component of this instance.
+ /// </summary>
+ public string Host { get { return uri.Host; } }
+
+ /// <summary>
+ /// Gets the scheme name for this URI.
+ /// </summary>
+ public string Scheme { get { return uri.Scheme; } }
+
+ /// <summary>
+ /// Gets the port number of this URI.
+ /// </summary>
+ public int Port { get { return uri.Port; } }
+
+ /// <summary>
+ /// Gets the absolute path of the URI.
+ /// </summary>
+ public string AbsolutePath { get { return uri.AbsolutePath; } }
+
+ /// <summary>
+ /// Gets the System.Uri.AbsolutePath and System.Uri.Query properties separated
+ /// by a question mark (?).
+ /// </summary>
+ public string PathAndQuery { get { return uri.PathAndQuery; } }
+
+ /// <summary>
+ /// Gets the realm URL. If the realm includes a wildcard, it is not included here.
+ /// </summary>
+ internal Uri NoWildcardUri { get { return uri; } }
+
+ /// <summary>
+ /// Produces the Realm URL. If the realm URL had a wildcard in it,
+ /// the wildcard is replaced with a "www." prefix.
+ /// </summary>
+ /// <remarks>
+ /// See OpenID 2.0 spec section 9.2.1 for the explanation on the addition of
+ /// the "www" prefix.
+ /// </remarks>
+ internal Uri UriWithWildcardChangedToWww {
+ get {
+ if (DomainWildcard) {
+ UriBuilder builder = new UriBuilder(NoWildcardUri);
+ builder.Host = "www." + builder.Host;
+ return builder.Uri;
+ } else {
+ return NoWildcardUri;
+ }
+ }
+ }
+
+ static string[] topLevelDomains = { "com", "edu", "gov", "int", "mil", "net", "org", "biz", "info", "name", "museum", "coop", "aero", "ac", "ad", "ae",
+ "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at", "au", "aw", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj",
+ "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr",
+ "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "eh", "er", "es", "et", "fi", "fj", "fk", "fm", "fo",
+ "fr", "ga", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr",
+ "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is", "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp",
+ "kr", "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc", "md", "mg", "mh", "mk", "ml", "mm",
+ "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na", "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr",
+ "nu", "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "ru", "rw", "sa",
+ "sb", "sc", "sd", "se", "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "sv", "sy", "sz", "tc", "td", "tf", "tg", "th",
+ "tj", "tk", "tm", "tn", "to", "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um", "us", "uy", "uz", "va", "vc", "ve", "vg", "vi",
+ "vn", "vu", "wf", "ws", "ye", "yt", "yu", "za", "zm", "zw" };
+
+ /// <summary>
+ /// This method checks the to see if a trust root represents a reasonable (sane) set of URLs.
+ /// </summary>
+ /// <remarks>
+ /// 'http://*.com/', for example is not a reasonable pattern, as it cannot meaningfully
+ /// specify the site claiming it. This function attempts to find many related examples,
+ /// but it can only work via heuristics. Negative responses from this method should be
+ /// treated as advisory, used only to alert the user to examine the trust root carefully.
+ /// </remarks>
+ internal bool IsSane {
+ get {
+ if (Host.Equals("localhost", StringComparison.OrdinalIgnoreCase))
+ return true;
+
+ string[] host_parts = Host.Split('.');
+
+ string tld = host_parts[host_parts.Length - 1];
+
+ if (Array.IndexOf(topLevelDomains, tld) < 0)
+ return false;
+
+ if (tld.Length == 2) {
+ if (host_parts.Length == 1)
+ return false;
+
+ if (host_parts[host_parts.Length - 2].Length <= 3)
+ return host_parts.Length > 2;
+ } else {
+ return host_parts.Length > 1;
+ }
+
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Validates a URL against this trust root.
+ /// </summary>
+ /// <param name="url">A string specifying URL to check.</param>
+ /// <returns>Whether the given URL is within this trust root.</returns>
+ internal bool Contains(string url) {
+ return Contains(new Uri(url));
+ }
+
+ /// <summary>
+ /// Validates a URL against this trust root.
+ /// </summary>
+ /// <param name="url">The URL to check.</param>
+ /// <returns>Whether the given URL is within this trust root.</returns>
+ internal bool Contains(Uri url) {
+ if (url.Scheme != Scheme)
+ return false;
+
+ if (url.Port != Port)
+ return false;
+
+ if (!DomainWildcard) {
+ if (url.Host != Host) {
+ return false;
+ }
+ } else {
+ Debug.Assert(!string.IsNullOrEmpty(Host), "The host part of the Regex should evaluate to at least one char for successful parsed trust roots.");
+ string[] host_parts = Host.Split('.');
+ string[] url_parts = url.Host.Split('.');
+
+ // If the domain containing the wildcard has more parts than the URL to match against,
+ // it naturally can't be valid.
+ // Unless *.example.com actually matches example.com too.
+ if (host_parts.Length > url_parts.Length)
+ return false;
+
+ // Compare last part first and move forward.
+ // Maybe could be done by using EndsWith, but piecewies helps ensure that
+ // *.my.com doesn't match ohmeohmy.com but can still match my.com.
+ for (int i = 0; i < host_parts.Length; i++) {
+ string hostPart = host_parts[host_parts.Length - 1 - i];
+ string urlPart = url_parts[url_parts.Length - 1 - i];
+ if (!string.Equals(hostPart, urlPart, StringComparison.OrdinalIgnoreCase)) {
+ return false;
+ }
+ }
+ }
+
+ // If path matches or is specified to root ...
+ // (deliberately case sensitive to protect security on case sensitive systems)
+ if (PathAndQuery.Equals(url.PathAndQuery, StringComparison.Ordinal)
+ || PathAndQuery.Equals("/", StringComparison.Ordinal))
+ return true;
+
+ // If trust root has a longer path, the return URL must be invalid.
+ if (PathAndQuery.Length > url.PathAndQuery.Length)
+ return false;
+
+ // The following code assures that http://example.com/directory isn't below http://example.com/dir,
+ // but makes sure http://example.com/dir/ectory is below http://example.com/dir
+ int path_len = PathAndQuery.Length;
+ string url_prefix = url.PathAndQuery.Substring(0, path_len);
+
+ if (PathAndQuery != url_prefix)
+ return false;
+
+ // If trust root includes a query string ...
+ if (PathAndQuery.Contains("?")) {
+ // ... make sure return URL begins with a new argument
+ return url.PathAndQuery[path_len] == '&';
+ }
+
+ // Or make sure a query string is introduced or a path below trust root
+ return PathAndQuery.EndsWith("/", StringComparison.Ordinal)
+ || url.PathAndQuery[path_len] == '?'
+ || url.PathAndQuery[path_len] == '/';
+ }
+
+#if TODO // TODO: Add discovery and then re-enable this code block
+ /// <summary>
+ /// Searches for an XRDS document at the realm URL, and if found, searches
+ /// for a description of a relying party endpoints (OpenId login pages).
+ /// </summary>
+ /// <param name="allowRedirects">
+ /// Whether redirects may be followed when discovering the Realm.
+ /// This may be true when creating an unsolicited assertion, but must be
+ /// false when performing return URL verification per 2.0 spec section 9.2.1.
+ /// </param>
+ /// <returns>The details of the endpoints if found, otherwise null.</returns>
+ internal IEnumerable<DotNetOpenId.Provider.RelyingPartyReceivingEndpoint> Discover(bool allowRedirects) {
+ // Attempt YADIS discovery
+ DiscoveryResult yadisResult = Yadis.Yadis.Discover(UriWithWildcardChangedToWww, false);
+ if (yadisResult != null) {
+ if (!allowRedirects && yadisResult.NormalizedUri != yadisResult.RequestUri) {
+ // Redirect occurred when it was not allowed.
+ throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
+ Strings.RealmCausedRedirectUponDiscovery, yadisResult.RequestUri));
+ }
+ if (yadisResult.IsXrds) {
+ try {
+ XrdsDocument xrds = new XrdsDocument(yadisResult.ResponseText);
+ return xrds.FindRelyingPartyReceivingEndpoints();
+ } catch (XmlException ex) {
+ throw new OpenIdException(Strings.InvalidXRDSDocument, ex);
+ }
+ }
+ }
+ return new RelyingPartyReceivingEndpoint[0];
+ }
+#endif
+
+ /// <summary>
+ /// Checks whether one <see cref="Realm"/> is equal to another.
+ /// </summary>
+ public override bool Equals(object obj) {
+ Realm other = obj as Realm;
+ if (other == null) return false;
+ return uri.Equals(other.uri) && DomainWildcard == other.DomainWildcard;
+ }
+
+ /// <summary>
+ /// Returns the hash code used for storing this object in a hash table.
+ /// </summary>
+ /// <returns></returns>
+ public override int GetHashCode() {
+ return uri.GetHashCode() + (DomainWildcard ? 1 : 0);
+ }
+
+ /// <summary>
+ /// Returns the string form of this <see cref="Realm"/>.
+ /// </summary>
+ public override string ToString() {
+ if (DomainWildcard) {
+ UriBuilder builder = new UriBuilder(uri);
+ builder.Host = "*." + builder.Host;
+ return builder.ToStringWithImpliedPorts();
+ } else {
+ return uri.AbsoluteUri;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth/UriUtil.cs b/src/DotNetOpenAuth/UriUtil.cs
index 63f666d..3385e4e 100644
--- a/src/DotNetOpenAuth/UriUtil.cs
+++ b/src/DotNetOpenAuth/UriUtil.cs
@@ -9,6 +9,8 @@ namespace DotNetOpenAuth {
using System.Collections.Specialized;
using System.Linq;
using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using System.Text.RegularExpressions;
/// <summary>
/// Utility methods for working with URIs.
@@ -42,5 +44,28 @@ namespace DotNetOpenAuth {
return string.Equals(uri.Scheme, "https", StringComparison.OrdinalIgnoreCase);
}
+
+ /// <summary>
+ /// Equivalent to UriBuilder.ToString() but omits port # if it may be implied.
+ /// Equivalent to UriBuilder.Uri.ToString(), but doesn't throw an exception if the Host has a wildcard.
+ /// </summary>
+ public static string ToStringWithImpliedPorts(this UriBuilder builder) {
+ ErrorUtilities.VerifyArgumentNotNull(builder, "builder");
+
+ // We only check for implied ports on HTTP and HTTPS schemes since those
+ // are the only ones supported by OpenID anyway.
+ if ((builder.Port == 80 && string.Equals(builder.Scheme, "http", StringComparison.OrdinalIgnoreCase)) ||
+ (builder.Port == 443 && string.Equals(builder.Scheme, "https", StringComparison.OrdinalIgnoreCase))) {
+ // An implied port may be removed.
+ string url = builder.ToString();
+ // Be really careful to only remove the first :80 or :443 so we are guaranteed
+ // we're removing only the port (and not something in the query string that
+ // looks like a port.
+ return Regex.Replace(url, @"^(https?://[^:]+):\d+", m => m.Groups[1].Value, RegexOptions.IgnoreCase);
+ } else {
+ // The port must be explicitly given anyway.
+ return builder.ToString();
+ }
+ }
}
}