diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2008-11-22 07:27:31 -0800 |
---|---|---|
committer | Andrew <andrewarnott@gmail.com> | 2008-11-22 07:27:31 -0800 |
commit | e9379729042a5ca7312df00d81f42370a83df0d1 (patch) | |
tree | 0d239a61f133ba126baf03fb285432bd5abe87f6 | |
parent | 70d616e4153a79fa0dcddd6db5aff57c6627ed2f (diff) | |
download | DotNetOpenAuth-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.html | 1157 | ||||
-rw-r--r-- | doc/specs/openid-authentication-1_1.html | 1593 | ||||
-rw-r--r-- | doc/specs/openid-authentication-2_0.html | 4172 | ||||
-rw-r--r-- | doc/specs/openid-provider-authentication-policy-extension-1_0-02.html | 1137 | ||||
-rw-r--r-- | doc/specs/openid-simple-registration-extension-1_0.html | 389 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj | 2 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs | 68 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs | 105 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Test/OpenId/RealmTests.cs | 224 | ||||
-rw-r--r-- | src/DotNetOpenAuth.sln | 9 | ||||
-rw-r--r-- | src/DotNetOpenAuth/DotNetOpenAuth.csproj | 2 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/Messages/CheckIdRequest.cs | 154 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs | 27 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/OpenIdStrings.resx | 9 | ||||
-rw-r--r-- | src/DotNetOpenAuth/OpenId/Realm.cs | 339 | ||||
-rw-r--r-- | src/DotNetOpenAuth/UriUtil.cs | 25 |
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"> TOC </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"> </td><td class="header">J. Bufu</td></tr> +<tr><td class="header"> </td><td class="header">Sxip Identity</td></tr> +<tr><td class="header"> </td><td class="header">J. Hoyt</td></tr> +<tr><td class="header"> </td><td class="header">JanRain</td></tr> +<tr><td class="header"> </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> +Terminology<br> + <a href="#anchor2">1.1.</a> +Definitions and Conventions<br> +<a href="#anchor3">2.</a> +Overview<br> +<a href="#anchor4">3.</a> +Information Model<br> + <a href="#identifier-definition">3.1.</a> +Subject Identifier<br> + <a href="#attribute-name-definition">3.2.</a> +Attribute Type Identifier<br> + <a href="#attribute-value-definition">3.3.</a> +Attribute Value<br> + <a href="#attribute-specific-encodings">3.3.1.</a> +Attribute-Specific Encodings<br> +<a href="#anchor5">4.</a> +Discovery<br> +<a href="#fetch">5.</a> +Fetch Message<br> + <a href="#fetch_request">5.1.</a> +Fetch Request Format<br> + <a href="#fetch_response">5.2.</a> +Fetch Response Format<br> +<a href="#store">6.</a> +Store Message<br> + <a href="#store_request">6.1.</a> +Store Request Format<br> + <a href="#store_response">6.2.</a> +Store Response Format<br> + <a href="#anchor6">6.2.1.</a> +Storage Success<br> + <a href="#anchor7">6.2.2.</a> +Storage Failure<br> +<a href="#anchor8">7.</a> +Security Considerations<br> +<a href="#anchor9">8.</a> +Acknowledgements<br> +<a href="#rfc.references1">9.</a> +References<br> + <a href="#rfc.references1">9.1.</a> +Normative References<br> + <a href="#rfc.references2">9.2.</a> +Non-normative References<br> +<a href="#rfc.authors">§</a> +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1"></a><h3>1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1.1"></a><h3>1.1. +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.<extension_alias>=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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.2"></a><h3>2. +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 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 5<span> (</span><span class="info">Fetch Message</span><span>)</span></a>) + and store (see <a class="info" href="#store">Section 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3"></a><h3>3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.1"></a><h3>3.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.2"></a><h3>3.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.3"></a><h3>3.3. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.3.1"></a><h3>3.3.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4"></a><h3>4. +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 2007.</span><span>)</span></a>. The attribute exchange + namespace "http://openid.net/srv/ax/1.0" SHOULD be listed as an <xrd:Type> + child element of the <xrd:Service> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5"></a><h3>5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1"></a><h3>5.1. +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.<alias>" 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.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + The value of this parameter specifies the type identifier + URI of a requested attribute. The <alias> 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 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.<alias>" 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.<alias>" 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.<alias></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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2"></a><h3>5.2. +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.<alias>" + 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.<alias>" parameter MUST + have an associated "openid.ax.type.<alias>" parameter. + +</p> +<p> + If a value was not supplied or available from the user, + the associated "openid.ax.value.<alias>" field + SHOULD NOT be included by the OP in the fetch response. + An "openid.ax.count.<alias>" with a value of "0" + together with its corresponding "openid.ax.type.<alias>" + 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.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + The value of this parameter specifies the type identifier + URI for an attribute in the fetch response. + The <alias> 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 2007.</span><span>)</span></a>; they also MUST + NOT contain commas (",") and periods ("."). + +</p> +</blockquote> + +</dd> +<dt>openid.ax.count.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + The number of values returned for the attribute referred + to as <alias>. + +</p> +</blockquote> + +</dd> +<dt>openid.ax.value.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + Assigns a value to the attribute referred to as + <alias>. This parameter format MUST be used if + "openid.ax.count.<alias>" is not sent. + +</p> +</blockquote> + +</dd> +<dt>openid.ax.value.<alias>.<number></dt> +<dd> + +<blockquote class="text"> +<p> + Assigns a value to the attribute referred to as + <alias>. This parameter format MUST be used + if "openid.ax.count.<alias>" is sent and at least + one value is provided for the associated attribute. + +</p> +<p> + The <number> uniquely identifies the index of + the value, ranging from one to the value specified by + "openid.ax.count.<alias>". The number of + parameters MUST be equal to the value specified by + "openid.ax.count.<alias>". 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6"></a><h3>6. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.1"></a><h3>6.1. +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.<alias>" or + "openid.ax.value.<alias>.<number>" parameter MUST + have an associated "openid.ax.type.<alias>" 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.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + The value of this parameter specifies the type identifier + URI for an attribute in the sore request. + The <alias> 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 2007.</span><span>)</span></a>; they also MUST + NOT contain commas (",") and periods ("."). + +</p> +</blockquote> + +</dd> +<dt>openid.ax.count.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + The number of values sent for the attribute referred to + as <alias>. If present, it MUST be greater than + zero. + +</p> +</blockquote> + +</dd> +<dt>openid.ax.value.<alias></dt> +<dd> + +<blockquote class="text"> +<p> + Assigns a value to the attribute referred to as + <alias>. This parameter format MUST be used if + "openid.ax.count.<alias>" is not sent. + +</p> +</blockquote> + +</dd> +<dt>openid.ax.value.<alias>.<number></dt> +<dd> + +<blockquote class="text"> +<p> + Assigns a value to the attribute referred to as + <alias>. The <number> uniquely identifies the + index of the value, ranging from one to the value specified + by "openid.ax.count.<alias>". This parameter format + MUST be used if "openid.ax.count.<alias>" is sent, + and the number of these parameters MUST be equal to the + value specified by "openid.ax.count.<alias>". + +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.2"></a><h3>6.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.2.1"></a><h3>6.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.2.2"></a><h3>6.2.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7"></a><h3>7. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8"></a><h3>8. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9"></a><h3>9. +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"> TOC </a></td></tr></tbody></table> +<h3>9.1. 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 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 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 14, RFC 2119, March 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 63, RFC 3629, November 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"> TOC </a></td></tr></tbody></table> +<h3>9.2. 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 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"> TOC </a></td></tr></tbody></table> +<h3>Authors' Addresses</h3> +<table border="0" cellpadding="0" cellspacing="0" width="99%"> +<tbody><tr><td class="author-text"> </td> +<td class="author-text">Dick Hardt</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Sxip Identity</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">798 Beatty Street</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Vancouver, BC V6B 2M1</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">CA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:dick@sxip.com">dick@sxip.com</a></td></tr> +<tr><td class="author" align="right">URI: </td> +<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Johnny Bufu</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Sxip Identity</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">798 Beatty Street</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Vancouver, BC V6B 2M1</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">CA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:johnny@sxip.com">johnny@sxip.com</a></td></tr> +<tr><td class="author" align="right">URI: </td> +<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Josh Hoyt</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">JanRain</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">5331 SW Macadam Ave. #375</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Portland, OR 97239</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">US</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:josh@janrain.com">josh@janrain.com</a></td></tr> +<tr><td class="author" align="right">URI: </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"> TOC </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">D. Recordon</td></tr> +<tr><td class="header"> </td><td class="header">B. Fitzpatrick</td></tr> +<tr><td class="header"> </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> +Requirements Notation<br> +<a href="#anchor2">2.</a> +Terminology<br> +<a href="#anchor3">3.</a> +Overview<br> + <a href="#anchor4">3.1.</a> +Transforming a HTML Document Into an Identifier<br> + <a href="#delegating_authentication">3.1.1.</a> +Delegating Authentication<br> + <a href="#anchor6">3.2.</a> +Submitting a Claimed Identifier<br> + <a href="#anchor8">3.3.</a> +Consumer Site Fetches the Identifier URL<br> + <a href="#smart_vs_dumb">3.4.</a> +Smart vs Dumb Mode<br> + <a href="#anchor11">3.5.</a> +Consumer Verifies the Identifier<br> +<a href="#anchor12">4.</a> +Modes<br> + <a href="#mode_associate">4.1.</a> +associate<br> + <a href="#anchor13">4.1.1.</a> +Request Parameters<br> + <a href="#anchor14">4.1.2.</a> +Response Parameters<br> + <a href="#anchor15">4.1.3.</a> +Extra Notes<br> + <a href="#mode_checkid_immediate">4.2.</a> +checkid_immediate<br> + <a href="#anchor16">4.2.1.</a> +Request Parameters<br> + <a href="#anchor17">4.2.2.</a> +Response Parameters<br> + <a href="#anchor21">4.2.3.</a> +Extra Notes<br> + <a href="#mode_checkid_setup">4.3.</a> +checkid_setup<br> + <a href="#anchor22">4.3.1.</a> +Request Parameters<br> + <a href="#anchor23">4.3.2.</a> +Respone Parameters<br> + <a href="#anchor26">4.3.3.</a> +Extra Notes<br> + <a href="#mode_check_authentication">4.4.</a> +check_authentication<br> + <a href="#anchor27">4.4.1.</a> +Request Parameters<br> + <a href="#anchor28">4.4.2.</a> +Response Parameters<br> + <a href="#anchor29">4.4.3.</a> +Extra Notes<br> +<a href="#anchor30">5.</a> +Security Considerations<br> +<a href="#defaults">Appendix A.</a> +Default Values<br> +<a href="#pvalue">Appendix A.1.</a> +Diffie-Hellman P Value<br> +<a href="#anchor31">Appendix B.</a> +Error Responses<br> +<a href="#anchor32">Appendix C.</a> +Key-Value Format<br> +<a href="#limits">Appendix D.</a> +Limits<br> +<a href="#anchor33">Appendix E.</a> +Misc<br> +<a href="#rfc.references1">6.</a> +Normative References<br> +<a href="#rfc.authors">§</a> +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1"></a><h3>1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.2"></a><h3>2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3"></a><h3>3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.1"></a><h3>3.1. 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><link rel="openid.server" + href="http://openid.example.com/"> +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.1.1"></a><h3>3.1.1. 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><link rel="openid.server" + href="http://www.livejournal.com/openid/server.bml"> +</p> +<p><link rel="openid.delegate" + href="http://exampleuser.livejournal.com/"> +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.1.2"></a><h3>3.1.2. 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 &, <, >, + 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.2"></a><h3>3.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.2.1"></a><h3>3.2.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.3"></a><h3>3.3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.3.1"></a><h3>3.3.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.4"></a><h3>3.4. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.4.1"></a><h3>3.4.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3.5"></a><h3>3.5. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4"></a><h3>4. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1"></a><h3>4.1. 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 -> IdP -> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.1"></a><h3>4.1.1. 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.2"></a><h3>4.1.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.3"></a><h3>4.1.3. 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 <= y < 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2"></a><h3>4.2. 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 -> User-Agent -> IdP -> User-Agent -> + 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.1"></a><h3>4.2.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.2"></a><h3>4.2.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.2.1"></a><h3>4.2.2.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.2.2"></a><h3>4.2.2.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.2.3"></a><h3>4.2.2.3. 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2.3"></a><h3>4.2.3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3"></a><h3>4.3. 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 -> User-Agent -> [IdP -> User-Agent + ->]+ 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3.1"></a><h3>4.3.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3.2"></a><h3>4.3.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3.2.1"></a><h3>4.3.2.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3.2.2"></a><h3>4.3.2.2. 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.3.3"></a><h3>4.3.3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.4"></a><h3>4.4. 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 -> IdP -> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.4.1"></a><h3>4.4.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.4.2"></a><h3>4.4.2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.4.3"></a><h3>4.4.3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5"></a><h3>5. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A"></a><h3>Appendix A. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.1"></a><h3>Appendix A.1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.B"></a><h3>Appendix B. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.C"></a><h3>Appendix C. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.D"></a><h3>Appendix D. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.E"></a><h3>Appendix E. 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"> TOC </a></td></tr></tbody></table> +<h3>6. 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"> TOC </a></td></tr></tbody></table> +<h3>Authors' Addresses</h3> +<table border="0" cellpadding="0" cellspacing="0" width="99%"> +<tbody><tr><td class="author-text"> </td> +<td class="author-text">David + Recordon</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:drecordon@verisign.com">drecordon@verisign.com</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Brad + Fitzpatrick</td></tr> +<tr><td class="author" align="right">Email: </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"> TOC </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"> </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> +Requirements Notation and Conventions<br> +<a href="#terminology">2.</a> +Terminology<br> +<a href="#anchor2">3.</a> +Protocol Overview<br> +<a href="#anchor3">4.</a> +Data Formats<br> + <a href="#anchor4">4.1.</a> +Protocol Messages<br> + <a href="#btwoc">4.2.</a> +Integer Representations<br> +<a href="#anchor6">5.</a> +Communication Types<br> + <a href="#direct_comm">5.1.</a> +Direct Communication<br> + <a href="#indirect_comm">5.2.</a> +Indirect Communication<br> +<a href="#generating_signatures">6.</a> +Generating Signatures<br> + <a href="#anchor11">6.1.</a> +Procedure<br> + <a href="#sign_algos">6.2.</a> +Signature Algorithms<br> +<a href="#anchor12">7.</a> +Initiation and Discovery<br> + <a href="#initiation">7.1.</a> +Initiation<br> + <a href="#normalization">7.2.</a> +Normalization<br> + <a href="#discovery">7.3.</a> +Discovery<br> +<a href="#associations">8.</a> +Establishing Associations<br> + <a href="#anchor17">8.1.</a> +Association Session Request<br> + <a href="#anchor20">8.2.</a> +Association Session Response<br> + <a href="#assoc_types">8.3.</a> +Association Types<br> + <a href="#assoc_sess_types">8.4.</a> +Association Session Types<br> +<a href="#requesting_authentication">9.</a> +Requesting Authentication<br> + <a href="#anchor27">9.1.</a> +Request Parameters<br> + <a href="#realms">9.2.</a> +Realms<br> + <a href="#anchor28">9.3.</a> +Immediate Requests<br> +<a href="#responding_to_authentication">10.</a> +Responding to Authentication Requests<br> + <a href="#positive_assertions">10.1.</a> +Positive Assertions<br> + <a href="#negative_assertions">10.2.</a> +Negative Assertions<br> +<a href="#verification">11.</a> +Verifying Assertions<br> + <a href="#verify_return_to">11.1.</a> +Verifying the Return URL<br> + <a href="#verify_disco">11.2.</a> +Verifying Discovered Information<br> + <a href="#verify_nonce">11.3.</a> +Checking the Nonce<br> + <a href="#verifying_signatures">11.4.</a> +Verifying Signatures<br> + <a href="#identifying">11.5.</a> +Identifying the end user<br> +<a href="#extensions">12.</a> +Extensions<br> +<a href="#rp_discovery">13.</a> +Discovering OpenID Relying Parties<br> +<a href="#compat_mode">14.</a> +OpenID Authentication 1.1 Compatibility<br> + <a href="#anchor34">14.1.</a> +Changes from OpenID Authentication 1.1<br> + <a href="#anchor38">14.2.</a> +Implementing OpenID Authentication 1.1 Compatibility<br> +<a href="#security_considerations">15.</a> +Security Considerations<br> + <a href="#anchor41">15.1.</a> +Preventing Attacks<br> + <a href="#anchor43">15.2.</a> +User-Agents<br> + <a href="#anchor44">15.3.</a> +User Interface Considerations<br> + <a href="#anchor45">15.4.</a> +HTTP and HTTPS URL Identifiers<br> + <a href="#anchor46">15.5.</a> +Denial of Service Attacks<br> + <a href="#anchor47">15.6.</a> +Protocol Variants<br> +<a href="#anchor48">Appendix A.</a> +Examples<br> +<a href="#normalization_example">Appendix A.1.</a> +Normalization<br> +<a href="#anchor49">Appendix A.2.</a> +OP-Local Identifiers<br> +<a href="#XRDS_Sample">Appendix A.3.</a> +XRDS<br> +<a href="#anchor50">Appendix A.4.</a> +HTML Identifier Markup<br> +<a href="#anchor51">Appendix A.5.</a> +XRI CanonicalID<br> +<a href="#pvalue">Appendix B.</a> +Diffie-Hellman Key Exchange Default Value<br> +<a href="#anchor52">Appendix C.</a> +Acknowledgements<br> +<a href="#rfc.references1">16.</a> +Normative References<br> +<a href="#rfc.authors">§</a> +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1"></a><h3>1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.2"></a><h3>2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3"></a><h3>3. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4"></a><h3>4. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1"></a><h3>4.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.1"></a><h3>4.1.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.2"></a><h3>4.1.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.1.3"></a><h3>4.1.3. +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&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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4.2"></a><h3>4.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5"></a><h3>5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1"></a><h3>5.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1.1"></a><h3>5.1.1. +Direct Request</h3> + +<p> + The message MUST be encoded as a POST body, as specified + by <a class="info" href="#http_encoding">Section 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1.2"></a><h3>5.1.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1.2.1"></a><h3>5.1.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1.2.2"></a><h3>5.1.2.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2"></a><h3>5.2. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2.1"></a><h3>5.2.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2.2"></a><h3>5.2.2. +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 <form> element's "action" attribute value MUST + be the URL of the receiver. Each Key-Value pair MUST be + included in the form as an <input> 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2.3"></a><h3>5.2.3. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6"></a><h3>6. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.1"></a><h3>6.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.2"></a><h3>6.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7"></a><h3>7. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.1"></a><h3>7.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.2"></a><h3>7.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3"></a><h3>7.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.1"></a><h3>7.3.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2"></a><h3>7.3.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.1"></a><h3>7.3.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.1.1"></a><h3>7.3.2.1.1. +OP Identifier Element</h3> + +<p> + An OP Identifier Element is an <xrd:Service> + element with the following information: + + </p> +<blockquote class="text"><dl> +<dt></dt> +<dd> + An <xrd:Type> tag whose text content is + "http://specs.openid.net/auth/2.0/server". + +</dd> +<dt></dt> +<dd> + An <xrd:URI> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.1.2"></a><h3>7.3.2.1.2. +Claimed Identifier Element</h3> + +<p> + A Claimed Identifier Element is an + <xrd:Service> element with the following + information: + + </p> +<blockquote class="text"><dl> +<dt></dt> +<dd> + An <xrd:Type> tag whose text content is + "http://specs.openid.net/auth/2.0/signon". + +</dd> +<dt></dt> +<dd> + An <xrd:URI> tag whose text content is the + OP Endpoint URL. + +</dd> +<dt></dt> +<dd> + An <xrd:LocalID> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.2"></a><h3>7.3.2.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.3"></a><h3>7.3.2.3. +XRI and the CanonicalID Element</h3> + +<p> + When the Identifier is an XRI, the <xrd:XRD> + element that contains the OpenID Authentication + <xrd:Service> element MUST also contain a + <CanonicalID> element. The content of this element + MUST be used as the Claimed Identifier (see <a class="info" href="#identifying">Section 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 + <CanonicalID> 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 <CanonicalID> 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 <ProviderID> and + <CanonicalID> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.2.4"></a><h3>7.3.2.4. +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 + <xrd:Type>, 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 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 12<span> (</span><span class="info">Extensions</span><span>)</span></a>), the extensions SHOULD be listed as additional + <xrd:Type> child elements of the + <xrd:Service> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.7.3.3"></a><h3>7.3.3. +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;", "&lt;", + "&gt;", and "&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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8"></a><h3>8. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.1"></a><h3>8.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.1.1"></a><h3>8.1.1. +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 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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.1.2"></a><h3>8.1.2. +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 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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.2"></a><h3>8.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.2.1"></a><h3>8.2.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.2.2"></a><h3>8.2.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.2.3"></a><h3>8.2.3. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.2.4"></a><h3>8.2.4. +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 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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.3"></a><h3>8.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.3.1"></a><h3>8.3.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.3.2"></a><h3>8.3.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.4"></a><h3>8.4. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.4.1"></a><h3>8.4.1. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.8.4.2"></a><h3>8.4.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9"></a><h3>9. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9.1"></a><h3>9.1. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9.2"></a><h3>9.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9.2.1"></a><h3>9.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.9.3"></a><h3>9.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.10"></a><h3>10. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.10.1"></a><h3>10.1. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.10.2"></a><h3>10.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.10.2.1"></a><h3>10.2.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.10.2.2"></a><h3>10.2.2. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11"></a><h3>11. +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 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 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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.1"></a><h3>11.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.2"></a><h3>11.2. +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> Discovered Information to Authentication Response Mapping </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 <xrd:Service> element. There MAY be + unused fields in that <xrd:Service> element. + +</p> +<p>Non-normative example: +</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre><Service xmlns="xri://$xrd*($v*2.0)"> + <Type>http://specs.openid.net/auth/2.0/signon</Type> + <URI>http://provider.example.com/openid</URI> + <URI>https://provider.example.com/openid</URI> +</Service> +</pre></div> +<p> + In this example XRDS snippet, the <xrd:Service> + element has two <xrd:URI> elements, which map to OP + Endpoint URLs as per <a class="info" href="#discovered_info">Section 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 <xrd:Service> + element. The other <xrd:URI> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.3"></a><h3>11.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.4"></a><h3>11.4. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.4.1"></a><h3>11.4.1. +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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.4.2"></a><h3>11.4.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.4.2.1"></a><h3>11.4.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.4.2.2"></a><h3>11.4.2.2. +Response Parameters</h3> + +<p> + </p> +<ul class="text"> +<li> + ns + +<blockquote class="text"> +<p> + As specified in <a class="info" href="#direct_response">Section 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.5"></a><h3>11.5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.5.1"></a><h3>11.5.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.11.5.2"></a><h3>11.5.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.12"></a><h3>12. +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 <xrd:Type> element of an + OpenID <xrd:Service> 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 + "<http://example.com/ext/1.0>". + + </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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.13"></a><h3>13. +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 + <xrd:Service> elements: + + </p> +<ul class="text"> +<li> + Containing at least one <xrd:URI> element. + +</li> +<li> + Where all <xrd:URI> tags contain a URL that accepts + OpenID 2.0 Authentication responses. + +</li> +<li> + Containing a <xrd:Type> 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><Service xmlns="xri://$xrd*($v*2.0)"> + <Type>http://specs.openid.net/auth/2.0/return_to</Type> + <URI>http://consumer.example.com/return</URI> +</Service> +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14"></a><h3>14. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.1"></a><h3>14.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.1.1"></a><h3>14.1.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.1.2"></a><h3>14.1.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.1.3"></a><h3>14.1.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.2"></a><h3>14.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.2.1"></a><h3>14.2.1. +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 + <openid:Delegate> tag of the OpenID + <xrd:Service> element rather than in the + <xrd:LocalID> tag. In order to support + currently-deployed discovery code, both tags MAY + appear in the <xrd:Service> 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 + <xrd:Type> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.14.2.2"></a><h3>14.2.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15"></a><h3>15. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.1"></a><h3>15.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.1.1"></a><h3>15.1.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.1.2"></a><h3>15.1.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.1.2.1"></a><h3>15.1.2.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.2"></a><h3>15.2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.3"></a><h3>15.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.4"></a><h3>15.4. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.5"></a><h3>15.5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.15.6"></a><h3>15.6. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A"></a><h3>Appendix A. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.1"></a><h3>Appendix A.1. +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> User's Input to Identifier Normalization </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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.2"></a><h3>Appendix A.2. +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 7.3<span> (</span><span class="info">Discovery</span><span>)</span></a> and + <a class="info" href="#XRDS_Sample">Appendix 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.3"></a><h3>Appendix A.3. +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><Service xmlns="xri://$xrd*($v*2.0)"> + <Type>http://specs.openid.net/auth/2.0/signon</Type> + <URI>https://www.exampleprovider.com/endpoint/</URI> + <LocalID>https://exampleuser.exampleprovider.com/</LocalID> +</Service> +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.4"></a><h3>Appendix A.4. +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 <head> + of the HTML document located by the identifier URL: + +</p><div style="display: table; width: 0pt; margin-left: 3em; margin-right: auto;"><pre><link rel="openid2.provider openid.server" + href="http://www.livejournal.com/openid/server.bml"/> +<link rel="openid2.local_id openid.delegate" + href="http://exampleuser.livejournal.com/"/> +</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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.5"></a><h3>Appendix A.5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.B"></a><h3>Appendix B. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.C"></a><h3>Appendix C. +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) <author> +</p> +<p>Carl Howells (chowells@janrain.com) +</p> +<p>David Recordon (david@sixapart.com) <author/editor> +</p> +<p>Dick Hardt (dick@sxip.com) <author> +</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) <editor> +</p> +<p>Josh Hoyt (josh@janrain.com) <author/editor> +</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"> TOC </a></td></tr></tbody></table> +<h3>16. 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 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 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 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 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 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 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 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 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 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 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 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 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"> TOC </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"> </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"> TOC </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"> </td><td class="header">Six Apart</td></tr> +<tr><td class="header"> </td><td class="header">J. Bufu, Ed.</td></tr> +<tr><td class="header"> </td><td class="header">Sxip Identity</td></tr> +<tr><td class="header"> </td><td class="header">J. Hoyt, Ed.</td></tr> +<tr><td class="header"> </td><td class="header">JanRain</td></tr> +<tr><td class="header"> </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> +Definitions<br> + <a href="#anchor2">1.1.</a> +Requirements Notation<br> + <a href="#anchor3">1.2.</a> +Conventions<br> + <a href="#anchor4">1.3.</a> +Terminology<br> +<a href="#anchor5">2.</a> +Extension Overview<br> +<a href="#advertising">3.</a> +Advertising Supported Policies<br> +<a href="#auth_policies">4.</a> +Defined Authentication Policies<br> +<a href="#anchor8">5.</a> +Authentication Protocol<br> + <a href="#anchor9">5.1.</a> +Request Parameters<br> + <a href="#anchor10">5.2.</a> +Response Parameters<br> +<a href="#anchor11">6.</a> +Security Considerations<br> + <a href="#anchor12">6.1.</a> +NIST Assurance Levels<br> +<a href="#examples">Appendix A.</a> +Examples<br> +<a href="#anchor13">Appendix A.1.</a> +Authentication Method Classifications<br> +<a href="#anchor15">Appendix B.</a> +Acknowledgements<br> +<a href="#rfc.references1">7.</a> +Normative References<br> +<a href="#rfc.authors">§</a> +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1"></a><h3>1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1.1"></a><h3>1.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1.2"></a><h3>1.2. +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.<alias>=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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1.3"></a><h3>1.3. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.2"></a><h3>2. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3"></a><h3>3. +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 <xrd:Type> element of an OpenID + <xrd:Service> 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4"></a><h3>4. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5"></a><h3>5. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.1"></a><h3>5.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5.2"></a><h3>5.2. +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 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 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6"></a><h3>6. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.6.1"></a><h3>6.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A"></a><h3>Appendix A. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.1"></a><h3>Appendix A.1. +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.1.1"></a><h3>Appendix A.1.1. +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 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"> </td> +<td align="left"> </td> +<td align="left"> </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"> </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"> </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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.A.1.2"></a><h3>Appendix A.1.2. +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 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 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"> </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"> </td> +</tr> +<tr> +<td align="left">Passwords & PINs</td> +<td align="left">X</td> +<td align="left">X</td> +<td align="left"> </td> +<td align="left"> </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 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"> </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"> </td> +<td align="left"> </td> +<td align="left">X</td> +<td align="left">X</td> +</tr> +<tr> +<td align="left">Man-in-the-middle</td> +<td align="left"> </td> +<td align="left"> </td> +<td align="left">X</td> +<td align="left">X</td> +</tr> +<tr> +<td align="left">Session hijacking</td> +<td align="left"> </td> +<td align="left"> </td> +<td align="left"> </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 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"> </td> +<td align="left"> </td> +<td align="left"> </td> +</tr> +<tr> +<td align="left">Password via HTTPS</td> +<td align="left">Yes</td> +<td align="left">Yes</td> +<td align="left"> </td> +<td align="left"> </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"> </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"> </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"> </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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.B"></a><h3>Appendix B. +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"> TOC </a></td></tr></tbody></table> +<h3>7. 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 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 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 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"> TOC </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"> TOC </a></td></tr></tbody></table> +<h3>Authors' Addresses</h3> +<table border="0" cellpadding="0" cellspacing="0" width="99%"> +<tbody><tr><td class="author-text"> </td> +<td class="author-text">David Recordon</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Six Apart, Ltd.</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">548 4th Street</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">San Francisco, CA 94107</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">USA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:david@sixapart.com">david@sixapart.com</a></td></tr> +<tr><td class="author" align="right">URI: </td> +<td class="author-text"><a href="http://www.sixapart.com/">http://www.sixapart.com/</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Johnny Bufu (editor)</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Sxip Identity</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">798 Beatty Street</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Vancouver, BC V6B 2M1</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">CA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:johnny@sxip.com">johnny@sxip.com</a></td></tr> +<tr><td class="author" align="right">URI: </td> +<td class="author-text"><a href="http://sxip.com/">http://sxip.com/</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Jonathan Daugherty (editor)</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">JanRain</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">5331 SW Macadam Ave. #375</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Portland, OR 97239</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">US</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:cygnus@janrain.com">cygnus@janrain.com</a></td></tr> +<tr><td class="author" align="right">URI: </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"> TOC </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"> </td><td class="header">J. Daugherty</td></tr> +<tr><td class="header"> </td><td class="header">JanRain</td></tr> +<tr><td class="header"> </td><td class="header">D. Recordon</td></tr> +<tr><td class="header"> </td><td class="header">VeriSign</td></tr> +<tr><td class="header"> </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> +Requirements Notation<br> +<a href="#anchor2">2.</a> +Terminology<br> +<a href="#anchor3">3.</a> +Request Format<br> +<a href="#response_format">4.</a> +Response Format<br> +<a href="#anchor4">5.</a> +Security Considerations<br> +<a href="#rfc.references1">6.</a> +Normative References<br> +<a href="#rfc.authors">§</a> +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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.1"></a><h3>1. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.2"></a><h3>2. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.3"></a><h3>3. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.4"></a><h3>4. 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"> TOC </a></td></tr></tbody></table> +<a name="rfc.section.5"></a><h3>5. 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"> TOC </a></td></tr></tbody></table> +<h3>6. 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"> TOC </a></td></tr></tbody></table> +<h3>Authors' Addresses</h3> +<table border="0" cellpadding="0" cellspacing="0" width="99%"> +<tbody><tr><td class="author-text"> </td> +<td class="author-text">Josh Hoyt</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">JanRain, Inc.</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">5331 SW Macadam Avenue</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Suite #375</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Portland, OR 97239</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">USA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:josh@janrain.com">josh@janrain.com</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Jonathan Daugherty</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">JanRain, Inc.</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">5331 SW Macadam Avenue</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Suite #375</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Portland, OR 97239</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">USA</td></tr> +<tr><td class="author" align="right">Email: </td> +<td class="author-text"><a href="mailto:jonathan@janrain.com">jonathan@janrain.com</a></td></tr> +<tr cellpadding="3"><td> </td><td> </td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">David + Recordon</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">VeriSign, Inc.</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">487 E Middlefield Road</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">Mountain View, CA 94109</td></tr> +<tr><td class="author-text"> </td> +<td class="author-text">USA</td></tr> +<tr><td class="author" align="right">Email: </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 '{0}'.. + /// </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 '{0}' not under realm '{1}'.. + /// </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(); + } + } } } |