Skip to content
This repository has been archived by the owner on Mar 20, 2019. It is now read-only.

Commit

Permalink
Merged v2.5 into v2.6.
Browse files Browse the repository at this point in the history
  • Loading branch information
AArnott committed Feb 16, 2009
2 parents bccc70e + 6482839 commit 247c517
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 81 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -1,8 +1,10 @@
bin
obj
TestResult.xml
TestResults
*.VisualState.xml
Drop
drop
drops
DotNetOpenId-*
StyleCop.Cache
84 changes: 50 additions & 34 deletions src/DotNetOpenId.Test/UriIdentifierTests.cs
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
Expand Down Expand Up @@ -139,10 +140,10 @@ public class UriIdentifierTests {
Assert.AreEqual(Uri.EscapeUriString(unicodeUrl), id.ToString());
}

void discover(string url, ProtocolVersion version, Identifier expectedLocalId, bool expectSreg, bool useRedirect) {
discover(url, version, expectedLocalId, expectSreg, useRedirect, null);
void discover(string url, ProtocolVersion version, Identifier expectedLocalId, Uri providerEndpoint, bool expectSreg, bool useRedirect) {
discover(url, version, expectedLocalId, providerEndpoint, expectSreg, useRedirect, null);
}
void discover(string url, ProtocolVersion version, Identifier expectedLocalId, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
void discover(string url, ProtocolVersion version, Identifier expectedLocalId, Uri providerEndpoint, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
Protocol protocol = Protocol.Lookup(version);
UriIdentifier claimedId = TestSupport.GetFullUrl(url);
UriIdentifier userSuppliedIdentifier = TestSupport.GetFullUrl(
Expand All @@ -161,30 +162,38 @@ public class UriIdentifierTests {
MockHttpRequest.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType,
headers ?? new WebHeaderCollection(), TestSupport.LoadEmbeddedFile(url));

ServiceEndpoint se = idToDiscover.Discover().FirstOrDefault();
ServiceEndpoint expected = ServiceEndpoint.CreateForClaimedIdentifier(
claimedId,
expectedLocalId,
providerEndpoint,
new string[] { protocol.ClaimedIdentifierServiceTypeURI }, // this isn't checked by Equals
null,
null);

ServiceEndpoint se = idToDiscover.Discover().FirstOrDefault(ep => ep.Equals(expected));
Assert.IsNotNull(se, url + " failed to be discovered.");
Assert.AreSame(protocol, se.Protocol);
Assert.AreEqual(claimedId, se.ClaimedIdentifier);
Assert.AreEqual(expectedLocalId, se.ProviderLocalIdentifier);

// Do extra checking of service type URIs, which aren't included in
// the ServiceEndpoint.Equals method.
Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Length);
Assert.IsTrue(Array.IndexOf(se.ProviderSupportedServiceTypeUris, protocol.ClaimedIdentifierServiceTypeURI) >= 0);
Assert.AreEqual(expectSreg, se.IsExtensionSupported(new ClaimsRequest()));
}
void discoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId) {
discoverXrds(page, version, expectedLocalId, null);
void discoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
discoverXrds(page, version, expectedLocalId, providerEndpoint, null);
}
void discoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, WebHeaderCollection headers) {
void discoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, WebHeaderCollection headers) {
if (!page.Contains(".")) page += ".xml";
discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, true, false, headers);
discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, true, true, headers);
discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, new Uri(providerEndpoint), true, false, headers);
discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, new Uri(providerEndpoint), true, true, headers);
}
void discoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, bool useRedirect) {
discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, false, useRedirect);
void discoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool useRedirect) {
discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, new Uri(providerEndpoint), false, useRedirect);
}
void discoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId) {
void discoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
string page = scenario + ".html";
discoverHtml(page, version, expectedLocalId, false);
discoverHtml(page, version, expectedLocalId, true);
discoverHtml(page, version, expectedLocalId, providerEndpoint, false);
discoverHtml(page, version, expectedLocalId, providerEndpoint, true);
}
void failDiscover(string url) {
UriIdentifier userSuppliedId = TestSupport.GetFullUrl(url);
Expand All @@ -202,48 +211,55 @@ public class UriIdentifierTests {
}
[Test]
public void HtmlDiscover_11() {
discoverHtml("html10prov", ProtocolVersion.V11, null);
discoverHtml("html10both", ProtocolVersion.V11, "http://c/d");
discoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b");
discoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b");
failDiscoverHtml("html10del");

// Verify that HTML discovery generates the 1.x endpoints when appropriate
discoverHtml("html2010", ProtocolVersion.V11, "http://g/h", "http://e/f");
discoverHtml("html1020", ProtocolVersion.V11, "http://g/h", "http://e/f");
discoverHtml("html2010combinedA", ProtocolVersion.V11, "http://c/d", "http://a/b");
discoverHtml("html2010combinedB", ProtocolVersion.V11, "http://c/d", "http://a/b");
discoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b");
}
[Test]
public void HtmlDiscover_20() {
discoverHtml("html20prov", ProtocolVersion.V20, null);
discoverHtml("html20both", ProtocolVersion.V20, "http://c/d");
discoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b");
discoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b");
failDiscoverHtml("html20del");
discoverHtml("html2010", ProtocolVersion.V20, "http://c/d");
discoverHtml("html1020", ProtocolVersion.V20, "http://c/d");
discoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d");
discoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d");
discoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d");
discoverHtml("html2010", ProtocolVersion.V20, "http://c/d", "http://a/b");
discoverHtml("html1020", ProtocolVersion.V20, "http://c/d", "http://a/b");
discoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d", "http://a/b");
discoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d", "http://a/b");
discoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d", "http://a/b");
failDiscoverHtml("html20relative");
}
[Test]
public void XrdsDiscoveryFromHead() {
Mocks.MockHttpRequest.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"),
"application/xrds+xml", TestSupport.LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
discoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null);
discoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b");
}
[Test]
public void XrdsDiscoveryFromHttpHeader() {
WebHeaderCollection headers = new WebHeaderCollection();
headers.Add("X-XRDS-Location", TestSupport.GetFullUrl("http://localhost/xrds1020.xml").AbsoluteUri);
Mocks.MockHttpRequest.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"),
"application/xrds+xml", TestSupport.LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
discoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, headers);
discoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, "http://a/b", headers);
}
[Test]
public void XrdsDirectDiscovery_10() {
failDiscoverXrds("xrds-irrelevant");
discoverXrds("xrds10", ProtocolVersion.V10, null);
discoverXrds("xrds11", ProtocolVersion.V11, null);
discoverXrds("xrds1020", ProtocolVersion.V10, null);
discoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b");
discoverXrds("xrds11", ProtocolVersion.V11, null, "http://a/b");
discoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b");
}
[Test]
public void XrdsDirectDiscovery_20() {
discoverXrds("xrds20", ProtocolVersion.V20, null);
discoverXrds("xrds2010a", ProtocolVersion.V20, null);
discoverXrds("xrds2010b", ProtocolVersion.V20, null);
discoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b");
discoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b");
discoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b");
}

[Test]
Expand Down
16 changes: 16 additions & 0 deletions src/DotNetOpenId/RelyingParty/AuthenticationResponse.cs
Expand Up @@ -358,6 +358,22 @@ class AuthenticationResponse : IAuthenticationResponse, ISetupRequiredAuthentica
ServiceEndpoint tokenEndpoint, ServiceEndpoint responseEndpoint) {

Logger.Debug("Verifying assertion matches identifier discovery results...");

// Verify that the actual version of the OP endpoint matches discovery.
Protocol actualProtocol = Protocol.Detect(query);
Protocol discoveredProtocol = (tokenEndpoint ?? responseEndpoint).Protocol;
if (!actualProtocol.Equals(discoveredProtocol)) {
// Allow an exception so that v1.1 and v1.0 can be seen as identical for this
// verification. v1.0 has no spec, and v1.1 and v1.0 cannot be clearly distinguished
// from the protocol, so detecting their differences is meaningless, and throwing here
// would just break thing unnecessarily.
if (!(actualProtocol.Version.Major == 1 && discoveredProtocol.Version.Major == 1)) {
throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
Strings.OpenIdDiscoveredAndActualVersionMismatch,
actualProtocol.Version, discoveredProtocol.Version));
}
}

if ((tokenEndpoint ?? responseEndpoint).Protocol.Version.Major < 2) {
Debug.Assert(tokenEndpoint != null, "Our OpenID 1.x implementation requires an RP token. And this should have been verified by our caller.");
// For 1.x OPs, we only need to verify that the OP Local Identifier
Expand Down
11 changes: 10 additions & 1 deletion src/DotNetOpenId/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src/DotNetOpenId/Strings.resx
Expand Up @@ -328,4 +328,7 @@ Discovered endpoint info:
<data name="ClaimedIdentifierCannotBeSetOnDelegatedAuthentication" xml:space="preserve">
<value>The ClaimedIdentifier property cannot be set when IsDelegatedIdentifier is true to avoid breaking OpenID URL delegation.</value>
</data>
</root>
<data name="OpenIdDiscoveredAndActualVersionMismatch" xml:space="preserve">
<value>Positive assertion sent with OpenID version {0} but Identifier discovery suggested it would be {1}.</value>
</data>
</root>
82 changes: 37 additions & 45 deletions src/DotNetOpenId/UriIdentifier.cs
Expand Up @@ -143,50 +143,43 @@ internal UriIdentifier(Uri uri, bool requireSslDiscovery)
/// </param>
/// <param name="html">The HTML that was downloaded and should be searched.</param>
/// <returns>
/// An initialized ServiceEndpoint if the OpenID Provider information was
/// found. Otherwise null.
/// A sequence of any discovered ServiceEndpoints.
/// </returns>
/// <remarks>
/// OpenID 2.0 tags are always used if they are present, otherwise
/// OpenID 1.x tags are used if present.
/// </remarks>
private static ServiceEndpoint DiscoverFromHtml(Uri claimedIdentifier, string html) {
Uri providerEndpoint = null;
Protocol discoveredProtocol = null;
Identifier providerLocalIdentifier = null;
private static IEnumerable<ServiceEndpoint> DiscoverFromHtml(Uri claimedIdentifier, string html) {
var linkTags = new List<HtmlLink>(Yadis.HtmlParser.HeadTags<HtmlLink>(html));
foreach (var protocol in Protocol.AllVersions) {
foreach (var linkTag in linkTags) {
// rel attributes are supposed to be interpreted with case INsensitivity,
// and is a space-delimited list of values. (http://www.htmlhelp.com/reference/html40/values.html#linktypes)
if (Regex.IsMatch(linkTag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryProviderKey) + @"\b", RegexOptions.IgnoreCase)) {
if (Uri.TryCreate(linkTag.Href, UriKind.Absolute, out providerEndpoint)) {
discoveredProtocol = protocol;
break;
}
}
if (protocol.Equals(Protocol.v10)) {
// For HTML discovery, this is redunant with v1.1, so skip.
continue;
}
if (providerEndpoint != null) break;
}
if (providerEndpoint == null)
return null; // html did not contain openid.server link
// See if a LocalId tag of the discovered version exists
foreach (var linkTag in linkTags) {
if (Regex.IsMatch(linkTag.Attributes["rel"], @"\b" + Regex.Escape(discoveredProtocol.HtmlDiscoveryLocalIdKey) + @"\b", RegexOptions.IgnoreCase)) {
if (Identifier.IsValid(linkTag.Href)) {
providerLocalIdentifier = linkTag.Href;
break;
} else {
Logger.WarnFormat("Skipping endpoint data because local id is badly formed ({0}).", linkTag.Href);
return null; // badly formed URL used as LocalId

// rel attributes are supposed to be interpreted with case INsensitivity,
// and is a space-delimited list of values. (http://www.htmlhelp.com/reference/html40/values.html#linktypes)
var serverLinkTag = Util.FirstOrDefault(linkTags, tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryProviderKey) + @"\b", RegexOptions.IgnoreCase));
if (serverLinkTag == null) {
continue;
}

Uri providerEndpoint = null;
if (Uri.TryCreate(serverLinkTag.Href, UriKind.Absolute, out providerEndpoint)) {
// See if a LocalId tag of the discovered version exists
Identifier providerLocalIdentifier = null;
var delegateLinkTag = Util.FirstOrDefault(linkTags, tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryLocalIdKey) + @"\b", RegexOptions.IgnoreCase));
if (delegateLinkTag != null) {
if (Identifier.IsValid(delegateLinkTag.Href)) {
providerLocalIdentifier = delegateLinkTag.Href;
} else {
Logger.WarnFormat("Skipping endpoint data because local id is badly formed ({0}).", delegateLinkTag.Href);
continue; // skip to next version
}
}

// Choose the TypeURI to match the OpenID version detected.
string[] typeURIs = { protocol.ClaimedIdentifierServiceTypeURI };
yield return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier,
providerEndpoint, typeURIs, (int?)null, (int?)null);
}
}

// Choose the TypeURI to match the OpenID version detected.
string[] typeURIs = { discoveredProtocol.ClaimedIdentifierServiceTypeURI };
return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier,
providerEndpoint, typeURIs, (int?)null, (int?)null);
}

internal override IEnumerable<ServiceEndpoint> Discover() {
Expand All @@ -205,14 +198,13 @@ internal UriIdentifier(Uri uri, bool requireSslDiscovery)
}
// Failing YADIS discovery of an XRDS document, we try HTML discovery.
if (endpoints.Count == 0) {
ServiceEndpoint ep = DiscoverFromHtml(yadisResult.NormalizedUri, yadisResult.ResponseText);
if (ep != null) {
Logger.Debug("HTML discovery found a service endpoint.");
Logger.Debug(ep);
if (!IsDiscoverySecureEndToEnd || ep.IsSecure) {
endpoints.Add(ep);
} else {
Logger.Info("Skipping HTML discovered endpoint because it is not secure.");
var htmlEndpoints = new List<ServiceEndpoint>(DiscoverFromHtml(yadisResult.NormalizedUri, yadisResult.ResponseText));
if (htmlEndpoints.Count > 0) {
Logger.DebugFormat("Total services discovered in HTML: {0}", htmlEndpoints.Count);
Logger.Debug(Util.ToString(htmlEndpoints, true));
endpoints.AddRange(Util.Where(htmlEndpoints, ep => !IsDiscoverySecureEndToEnd || ep.IsSecure));
if (endpoints.Count == 0) {
Logger.Info("No HTML discovered endpoints met the security requirements.");
}
} else {
Logger.Debug("HTML discovery failed to find any endpoints.");
Expand Down

0 comments on commit 247c517

Please sign in to comment.