summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.Test
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.Test')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj5
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs8
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs48
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs260
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs394
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs242
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs376
10 files changed, 725 insertions, 622 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 27ea955..db97aac 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -187,6 +187,7 @@
<Compile Include="Mocks\InMemoryTokenManager.cs" />
<Compile Include="Mocks\MockHttpRequest.cs" />
<Compile Include="Mocks\MockIdentifier.cs" />
+ <Compile Include="Mocks\MockIdentifierDiscoveryService.cs" />
<Compile Include="Mocks\MockOpenIdExtension.cs" />
<Compile Include="Mocks\MockRealm.cs" />
<Compile Include="Mocks\MockTransformationBindingElement.cs" />
@@ -221,6 +222,8 @@
<Compile Include="Messaging\Bindings\StandardReplayProtectionBindingElementTests.cs" />
<Compile Include="OpenId\ChannelElements\SigningBindingElementTests.cs" />
<Compile Include="OpenId\DiffieHellmanTests.cs" />
+ <Compile Include="OpenId\DiscoveryServices\UriDiscoveryServiceTests.cs" />
+ <Compile Include="OpenId\DiscoveryServices\XriDiscoveryProxyServiceTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchRequestTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchResponseTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeExchangeRoundtripTests.cs" />
@@ -331,4 +334,4 @@
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
index 346dde9..73fd8c3 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
@@ -39,6 +39,10 @@ namespace DotNetOpenAuth.Test.Mocks {
mockHttpRequest.RegisterMockXrdsResponse(new Uri(wrappedIdentifier.ToString()), endpoints);
}
+ internal IEnumerable<ServiceEndpoint> DiscoveryEndpoints {
+ get { return this.endpoints; }
+ }
+
public override string ToString() {
return this.wrappedIdentifier.ToString();
}
@@ -51,10 +55,6 @@ namespace DotNetOpenAuth.Test.Mocks {
return this.wrappedIdentifier.GetHashCode();
}
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- return this.endpoints;
- }
-
internal override Identifier TrimFragment() {
return this;
}
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs
new file mode 100644
index 0000000..e02fa1f
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------
+// <copyright file="MockIdentifierDiscoveryService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Mocks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.DiscoveryServices;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ internal class MockIdentifierDiscoveryService : IIdentifierDiscoveryService {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MockIdentifierDiscoveryService"/> class.
+ /// </summary>
+ public MockIdentifierDiscoveryService() {
+ }
+
+ #region IIdentifierDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ public IEnumerable<ServiceEndpoint> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ var mockIdentifier = identifier as MockIdentifier;
+ if (mockIdentifier == null) {
+ abortDiscoveryChain = false;
+ return Enumerable.Empty<ServiceEndpoint>();
+ }
+
+ abortDiscoveryChain = true;
+ return mockIdentifier.DiscoveryEndpoints;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs
new file mode 100644
index 0000000..3d91fc0
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs
@@ -0,0 +1,260 @@
+//-----------------------------------------------------------------------
+// <copyright file="UriDiscoveryServiceTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class UriDiscoveryServiceTests : OpenIdTestBase {
+ [TestMethod]
+ public void DiscoveryWithRedirects() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, false);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+
+ // don't require secure SSL discovery for this test.
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, false);
+ Assert.AreEqual(1, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestMethod]
+ public void DiscoverRequireSslWithSecureRedirects() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ // All redirects should be secure.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri secureMidpointUri = new Uri("https://localhost/secureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
+ Assert.AreEqual(1, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void DiscoverRequireSslWithInsecureRedirect() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ // Include an insecure HTTP jump in those redirects to verify that
+ // the ultimate endpoint is never found as a result of high security profile.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
+ this.Discover(userSuppliedIdentifier);
+ }
+
+ [TestMethod]
+ public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+ Uri secureClaimedUri = new Uri("https://localhost/secureId");
+
+ string html = string.Format("<html><head><meta http-equiv='X-XRDS-Location' content='{0}'/></head><body></body></html>", insecureXrdsSource);
+ this.MockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
+ Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestMethod]
+ public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+
+ string html = "<html><head></head><body></body></html>";
+ WebHeaderCollection headers = new WebHeaderCollection {
+ { "X-XRDS-Location", insecureXrdsSource }
+ };
+ this.MockResponder.RegisterMockResponse(VanityUriSsl, VanityUriSsl, "text/html", headers, html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
+ Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestMethod]
+ public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+ string html = string.Format(
+ @"
+ <html><head>
+ <meta http-equiv='X-XRDS-Location' content='{0}'/> <!-- this one will be insecure and ignored -->
+ <link rel='openid2.provider' href='{1}' />
+ <link rel='openid2.local_id' href='{2}' />
+ </head><body></body></html>",
+ HttpUtility.HtmlEncode(insecureXrdsSource),
+ HttpUtility.HtmlEncode(OPUriSsl.AbsoluteUri),
+ HttpUtility.HtmlEncode(OPLocalIdentifiersSsl[1].AbsoluteUri));
+ this.MockResponder.RegisterMockResponse(VanityUriSsl, "text/html", html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
+
+ // We verify that the XRDS was ignored and the LINK tags were used
+ // because the XRDS OP-LocalIdentifier uses different local identifiers.
+ Assert.AreEqual(OPLocalIdentifiersSsl[1], this.Discover(userSuppliedIdentifier).Single().ProviderLocalIdentifier);
+ }
+
+ [TestMethod]
+ public void DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds() {
+ var insecureEndpoint = GetServiceEndpoint(0, ProtocolVersion.V20, 10, false);
+ var secureEndpoint = GetServiceEndpoint(1, ProtocolVersion.V20, 20, true);
+ UriIdentifier secureClaimedId = new UriIdentifier(VanityUriSsl, true);
+ this.MockResponder.RegisterMockXrdsResponse(secureClaimedId, new ServiceEndpoint[] { insecureEndpoint, secureEndpoint });
+ Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, this.Discover(secureClaimedId).Single().ProviderLocalIdentifier);
+ }
+
+ [TestMethod]
+ public void XrdsDirectDiscovery_10() {
+ this.FailDiscoverXrds("xrds-irrelevant");
+ this.DiscoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b");
+ this.DiscoverXrds("xrds11", ProtocolVersion.V11, null, "http://a/b");
+ this.DiscoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b");
+ }
+
+ [TestMethod]
+ public void XrdsDirectDiscovery_20() {
+ this.DiscoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b");
+ }
+
+ [TestMethod]
+ public void HtmlDiscover_11() {
+ this.DiscoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b");
+ this.DiscoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html10del");
+
+ // Verify that HTML discovery generates the 1.x endpoints when appropriate
+ this.DiscoverHtml("html2010", ProtocolVersion.V11, "http://g/h", "http://e/f");
+ this.DiscoverHtml("html1020", ProtocolVersion.V11, "http://g/h", "http://e/f");
+ this.DiscoverHtml("html2010combinedA", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedB", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ }
+
+ [TestMethod]
+ public void HtmlDiscover_20() {
+ this.DiscoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html20del");
+ this.DiscoverHtml("html2010", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html1020", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html20relative");
+ }
+
+ [TestMethod]
+ public void XrdsDiscoveryFromHead() {
+ this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
+ this.DiscoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b");
+ }
+
+ [TestMethod]
+ public void XrdsDiscoveryFromHttpHeader() {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add("X-XRDS-Location", new Uri("http://localhost/xrds1020.xml").AbsoluteUri);
+ this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
+ this.DiscoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, "http://a/b", headers);
+ }
+
+ private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect) {
+ this.Discover(url, version, expectedLocalId, providerEndpoint, expectSreg, useRedirect, null);
+ }
+
+ private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
+ Protocol protocol = Protocol.Lookup(version);
+ Uri baseUrl = new Uri("http://localhost/");
+ UriIdentifier claimedId = new Uri(baseUrl, url);
+ UriIdentifier userSuppliedIdentifier = new Uri(baseUrl, "Discovery/htmldiscovery/redirect.aspx?target=" + url);
+ if (expectedLocalId == null) {
+ expectedLocalId = claimedId;
+ }
+ Identifier idToDiscover = useRedirect ? userSuppliedIdentifier : claimedId;
+
+ string contentType;
+ if (url.EndsWith("html")) {
+ contentType = "text/html";
+ } else if (url.EndsWith("xml")) {
+ contentType = "application/xrds+xml";
+ } else {
+ throw new InvalidOperationException();
+ }
+ this.MockResponder.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType, headers ?? new WebHeaderCollection(), LoadEmbeddedFile(url));
+
+ ServiceEndpoint expected = ServiceEndpoint.CreateForClaimedIdentifier(
+ claimedId,
+ expectedLocalId,
+ new ProviderEndpointDescription(new Uri(providerEndpoint), new string[] { protocol.ClaimedIdentifierServiceTypeURI }), // services aren't checked by Equals
+ null,
+ null);
+
+ ServiceEndpoint se = this.Discover(idToDiscover).FirstOrDefault(ep => ep.Equals(expected));
+ Assert.IsNotNull(se, url + " failed to be discovered.");
+
+ // Do extra checking of service type URIs, which aren't included in
+ // the ServiceEndpoint.Equals method.
+ Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Count);
+ Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Contains(protocol.ClaimedIdentifierServiceTypeURI));
+ Assert.AreEqual(expectSreg, se.IsExtensionSupported<ClaimsRequest>());
+ }
+
+ private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
+ this.DiscoverXrds(page, version, expectedLocalId, providerEndpoint, null);
+ }
+
+ private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, WebHeaderCollection headers) {
+ if (!page.Contains(".")) {
+ page += ".xml";
+ }
+ this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, false, headers);
+ this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, true, headers);
+ }
+
+ private void DiscoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool useRedirect) {
+ this.Discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, providerEndpoint, false, useRedirect);
+ }
+
+ private void DiscoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
+ string page = scenario + ".html";
+ this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, false);
+ this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, true);
+ }
+
+ private void FailDiscover(string url) {
+ UriIdentifier userSuppliedId = new Uri(new Uri("http://localhost"), url);
+
+ this.MockResponder.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html", LoadEmbeddedFile(url));
+
+ Assert.AreEqual(0, this.Discover(userSuppliedId).Count()); // ... but that no endpoint info is discoverable
+ }
+
+ private void FailDiscoverHtml(string scenario) {
+ this.FailDiscover("/Discovery/htmldiscovery/" + scenario + ".html");
+ }
+
+ private void FailDiscoverXrds(string scenario) {
+ this.FailDiscover("/Discovery/xrdsdiscovery/" + scenario + ".xml");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs
new file mode 100644
index 0000000..15ed641
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs
@@ -0,0 +1,394 @@
+//-----------------------------------------------------------------------
+// <copyright file="XriDiscoveryProxyServiceTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class XriDiscoveryProxyServiceTests : OpenIdTestBase {
+ [TestMethod]
+ public void Discover() {
+ string xrds = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*Arnott</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:03:24.000Z</Expires>
+ <ProviderID>xri://=</ProviderID>
+ <LocalID>!9b72.7dd1.50a9.5ccd</LocalID>
+ <CanonicalID>=!9B72.7DD1.50A9.5CCD</CanonicalID>
+
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='default' select='false'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null' select='false'/>
+ <URI append='qxri' priority='1'>http://1id.com/contact/</URI>
+
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <URI append='qxri' priority='1'>http://1id.com/</URI>
+ </Service>
+
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='10'>http://1id.com/sso</URI>
+ </Service>
+</XRD>";
+ Dictionary<string, string> mocks = new Dictionary<string, string> {
+ { "https://xri.net/=Arnott?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
+ { "https://xri.net/=!9B72.7DD1.50A9.5CCD?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
+ };
+ this.MockResponder.RegisterMockXrdsResponses(mocks);
+
+ string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
+ ServiceEndpoint se = this.VerifyCanonicalId("=Arnott", expectedCanonicalId);
+ Assert.AreEqual(Protocol.V10, se.Protocol);
+ Assert.AreEqual("http://1id.com/sso", se.ProviderEndpoint.ToString());
+ Assert.AreEqual(se.ClaimedIdentifier, se.ProviderLocalIdentifier);
+ Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay);
+ }
+
+ [TestMethod]
+ public void DiscoverCommunityInameCanonicalIDs() {
+ string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*llli</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:21:06.000Z</Expires>
+ <ProviderID>xri://@</ProviderID>
+ <LocalID>!72cd.a072.157e.a9c6</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6</CanonicalID>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type match='null' select='false'/>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path match='default'/>
+ <Path>(+index)</Path>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI priority='10'>http://resolve.ezibroker.net/resolve/@llli/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+</XRD>
+";
+ string llliAreaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*area</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:07.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA0C</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI>http://resolve.ezibroker.net/resolve/@llli*area/</URI>
+ </Service>
+</XRD>";
+ string llliAreaCanadaUnattachedResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*canada.unattached</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:08.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA41</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI>http://resolve.ezibroker.net/resolve/@llli*area*canada.unattached/</URI>
+ </Service>
+</XRD>";
+ string llliAreaCanadaUnattachedAdaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*ada</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:10.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA01</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+</XRD>";
+ string webResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*Web</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:21:12.000Z</Expires>
+ <ProviderID>xri://=</ProviderID>
+ <LocalID>!91f2.8153.f600.ae24</LocalID>
+ <CanonicalID>=!91F2.8153.F600.AE24</CanonicalID>
+ <Service priority='10'>
+ <Type select='true'>xri://+i-service*(+locator)*($v*1.0)</Type>
+ <Path select='true'>(+locator)</Path>
+ <MediaType match='default' select='false'/>
+ <URI append='qxri'>http://locator.fullxri.com/locator/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://=web</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType select='true'>application/xrds+xml</MediaType>
+ <URI append='qxri' priority='1'>https://resolve.freexri.com/ns/=web/</URI>
+ <URI append='qxri' priority='2'>http://resolve.freexri.com/ns/=web/</URI>
+ </Service>
+ <Service priority='10'>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Type select='true'>http://specs.openid.net/auth/2.0/signon</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default' select='false'/>
+ <MediaType match='default' select='false'/>
+ <URI append='none' priority='2'>http://authn.fullxri.com/authentication/</URI>
+ <URI append='none' priority='1'>https://authn.fullxri.com/authentication/</URI>
+ </Service>
+ <Service priority='10'>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null' select='false'/>
+ <MediaType match='default' select='false'/>
+ <URI append='qxri'>http://contact.fullxri.com/contact/</URI>
+ </Service>
+ <KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
+ <X509Data>
+ <X509Certificate>
+MIIExzCCA6+gAwIBAgIJAM+MlFr0Sth6MA0GCSqGSIb3DQEBBQUAMIGdMR8wHQYD
+VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
+CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
+YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
+YWluLmVkdTAeFw0wNjA4MTcxOTU5NTNaFw0xMTA4MTYxOTU5NTNaMIGdMR8wHQYD
+VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
+CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
+YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
+YWluLmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6uFqas4dK6
+A2wTZL0viRQNJrPyFnFBDSZGib/2ijhgzed/vvmZIBM9sFpwahcuR5hvyKUe37/c
+/RSZXoNDi/eiNOx4qb0l9UB6bd8qvc4V1PnLE7L+ZYcmwrvTKm4x8qXMgEv1wca2
+FPsreHNPdLiTUZ8v0tDTWi3Mgi7y47VTzJaTkcfmO1nL6xAtln5sLdH0PbMM3LAp
+T1d3nwI3VdbhqqZ+6+OKEuC8gk5iH4lfrbr6C9bYS6vzIKrotHpZ3N2aIC3NMjJD
+PMw/mfCuADfRNlHXgZW+0zyUkwGTMDea8qgsoAMWJGdeTIw8I1I3RhnbgLzdsNQl
+b/1ZXx1uJRUCAwEAAaOCAQYwggECMB0GA1UdDgQWBBQe+xSjYTrlfraJARjMxscb
+j36jvDCB0gYDVR0jBIHKMIHHgBQe+xSjYTrlfraJARjMxscbj36jvKGBo6SBoDCB
+nTEfMB0GA1UEAxMWU3VwZXJ2aWxsYWluOiBUaGUgUm9vdDELMAkGA1UEBhMCVVMx
+ETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZHb3RoYW0xIDAeBgNVBAoTF1N1
+cGVydmlsbGFpbiBVbml2ZXJzaXR5MScwJQYJKoZIhvcNAQkBFhhwZW5ndWluQHN1
+cGVydmlsbGFpbi5lZHWCCQDPjJRa9ErYejAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
+DQEBBQUAA4IBAQC4SPBDGYAxfbXd8N5OvG0drM7a5hjXfcCZpiILlPSRpxp79yh7
+I5vVWxBxUfolwbei7PTBVy7CE27SUbSICeqWjcDCfjNjiZk6mLS80rm/TdLrHSyM
++Ujlw9MGcBGaLI+sdziDUMtTQDpeAyQTaGVbh1mx5874Hlo1VXqGYNo0RwR+iLfs
+x48VuO6GbWVyxtktkE2ypz1KLWiyI056YynydRvuBCBHeRqGUixPlH9CrmeSCP2S
+sfbiKnMOGXjIYbvbsTAMdW2iqg6IWa/fgxhvZoAXChM9bkhisJQc0qD0J5TJQwgr
+uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+</XRD>";
+ this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ { "https://xri.net/@llli?_xrd_r=application/xrd%2Bxml;sep=false", llliResponse },
+ { "https://xri.net/@llli*area?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaResponse },
+ { "https://xri.net/@llli*area*canada.unattached?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedResponse },
+ { "https://xri.net/@llli*area*canada.unattached*ada?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedAdaResponse },
+ { "https://xri.net/=Web?_xrd_r=application/xrd%2Bxml;sep=false", webResponse },
+ });
+ this.VerifyCanonicalId("@llli", "@!72CD.A072.157E.A9C6");
+ this.VerifyCanonicalId("@llli*area", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C");
+ this.VerifyCanonicalId("@llli*area*canada.unattached", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41");
+ this.VerifyCanonicalId("@llli*area*canada.unattached*ada", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01");
+ this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24");
+ }
+
+ [TestMethod]
+ public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
+ this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*andrew.arnott</Query>
+ <Status cid='absent' code='100'>Success</Status>
+ <ServerStatus code='100'>Success</ServerStatus>
+ <Expires>2008-07-14T03:30:59.722Z</Expires>
+ <ProviderID>=!91F2.8153.F600.AE24</ProviderID>
+ <Service>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
+ <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://contact.freexri.com/contact/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path select='true'>(+index)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://authn.freexri.com/authentication/</URI>
+ <URI append='none' priority='1'>https://authn.freexri.com/authentication/</URI>
+ </Service>
+ <ServedBy>OpenXRI</ServedBy>
+</XRD>" },
+ { "https://xri.net/@id*andrewarnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*andrewarnott</Query>
+ <Status cid='absent' code='100'>Success</Status>
+ <ServerStatus code='100'>Success</ServerStatus>
+ <Expires>2008-07-14T03:31:00.466Z</Expires>
+ <ProviderID>@!B1E8.C27B.E41C.25C3</ProviderID>
+ <Service>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
+ <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://contact.freexri.com/contact/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path select='true'>(+index)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
+ </Service>
+ <ServedBy>OpenXRI</ServedBy>
+</XRD>" },
+ });
+ // Consistent with spec section 7.3.2.3, we do not permit
+ // delegation on XRI discovery when there is no CanonicalID present.
+ this.VerifyCanonicalId("=Web*andrew.arnott", null);
+ this.VerifyCanonicalId("@id*andrewarnott", null);
+ }
+
+ private ServiceEndpoint VerifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
+ ServiceEndpoint se = this.Discover(iname).FirstOrDefault();
+ if (expectedClaimedIdentifier != null) {
+ Assert.IsNotNull(se);
+ Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname);
+ Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Count > 0);
+ } else {
+ Assert.IsNull(se);
+ }
+ return se;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
index 0f9d472..d4884e8 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
@@ -57,10 +57,12 @@ namespace DotNetOpenAuth.Test.OpenId {
private void EnsurePartiesAreInitialized() {
if (this.RelyingParty == null) {
this.RelyingParty = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore());
+ this.RelyingParty.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
}
if (this.Provider == null) {
this.Provider = new OpenIdProvider(new StandardProviderApplicationStore());
+ this.Provider.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
index 5034b7e..49fba81 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
@@ -6,12 +6,14 @@
namespace DotNetOpenAuth.Test.OpenId {
using System;
+ using System.Collections.Generic;
using System.IO;
using System.Reflection;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.DiscoveryServices;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
@@ -176,6 +178,12 @@ namespace DotNetOpenAuth.Test.OpenId {
}
}
+ internal IEnumerable<ServiceEndpoint> Discover(Identifier identifier) {
+ var rp = this.CreateRelyingParty(true);
+ rp.Channel.WebRequestHandler = this.RequestHandler;
+ return rp.Discover(identifier);
+ }
+
protected Realm GetMockRealm(bool useSsl) {
var rpDescription = new RelyingPartyEndpointDescription(useSsl ? RPUriSsl : RPUri, new string[] { Protocol.V20.RPReturnToTypeURI });
return new MockRealm(useSsl ? RPRealmUriSsl : RPRealmUri, rpDescription);
@@ -211,6 +219,7 @@ namespace DotNetOpenAuth.Test.OpenId {
protected OpenIdRelyingParty CreateRelyingParty(bool stateless) {
var rp = new OpenIdRelyingParty(stateless ? null : new StandardRelyingPartyApplicationStore());
rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ rp.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
return rp;
}
@@ -221,6 +230,7 @@ namespace DotNetOpenAuth.Test.OpenId {
protected OpenIdProvider CreateProvider() {
var op = new OpenIdProvider(new StandardProviderApplicationStore());
op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ op.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
return op;
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
index f6a57e7..7f0eb81 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
@@ -23,7 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
[TestMethod]
public void CreateRequestDumbMode() {
- var rp = new OpenIdRelyingParty(null);
+ var rp = this.CreateRelyingParty(true);
Identifier id = this.GetMockIdentifier(ProtocolVersion.V20);
var authReq = rp.CreateRequest(id, RPRealmUri, RPUri);
CheckIdRequest requestMessage = (CheckIdRequest)authReq.RedirectingResponse.OriginalMessage;
diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
index 5a5182f..d504cdf 100644
--- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
@@ -141,62 +141,6 @@ namespace DotNetOpenAuth.Test.OpenId {
}
[TestMethod]
- public void HtmlDiscover_11() {
- this.DiscoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b");
- this.DiscoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html10del");
-
- // Verify that HTML discovery generates the 1.x endpoints when appropriate
- this.DiscoverHtml("html2010", ProtocolVersion.V11, "http://g/h", "http://e/f");
- this.DiscoverHtml("html1020", ProtocolVersion.V11, "http://g/h", "http://e/f");
- this.DiscoverHtml("html2010combinedA", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedB", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b");
- }
-
- [TestMethod]
- public void HtmlDiscover_20() {
- this.DiscoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html20del");
- this.DiscoverHtml("html2010", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html1020", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html20relative");
- }
-
- [TestMethod]
- public void XrdsDiscoveryFromHead() {
- this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
- this.DiscoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b");
- }
-
- [TestMethod]
- public void XrdsDiscoveryFromHttpHeader() {
- WebHeaderCollection headers = new WebHeaderCollection();
- headers.Add("X-XRDS-Location", new Uri("http://localhost/xrds1020.xml").AbsoluteUri);
- this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
- this.DiscoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, "http://a/b", headers);
- }
-
- [TestMethod]
- public void XrdsDirectDiscovery_10() {
- this.FailDiscoverXrds("xrds-irrelevant");
- this.DiscoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b");
- this.DiscoverXrds("xrds11", ProtocolVersion.V11, null, "http://a/b");
- this.DiscoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b");
- }
-
- [TestMethod]
- public void XrdsDirectDiscovery_20() {
- this.DiscoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b");
- }
-
- [TestMethod]
public void NormalizeCase() {
// only the host name can be normalized in casing safely.
Identifier id = "http://HOST:80/PaTH?KeY=VaLUE#fRag";
@@ -221,21 +165,6 @@ namespace DotNetOpenAuth.Test.OpenId {
}
[TestMethod]
- public void DiscoveryWithRedirects() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, false);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
-
- // don't require secure SSL discovery for this test.
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, false);
- Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
public void TryRequireSslAdjustsIdentifier() {
Identifier secureId;
// Try Parse and ctor without explicit scheme
@@ -256,180 +185,13 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsTrue(secureId.IsDiscoverySecureEndToEnd, "Although the TryRequireSsl failed, the created identifier should retain the Ssl status.");
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover(this.RequestHandler).Count(), "Since TryRequireSsl failed, the created Identifier should never discover anything.");
+ Assert.AreEqual(0, Discover(secureId).Count(), "Since TryRequireSsl failed, the created Identifier should never discover anything.");
id = new UriIdentifier("http://www.yahoo.com");
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsTrue(secureId.IsDiscoverySecureEndToEnd);
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoverRequireSslWithSecureRedirects() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- // All redirects should be secure.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri secureMidpointUri = new Uri("https://localhost/secureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
- this.MockResponder.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
-
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod, ExpectedException(typeof(ProtocolException))]
- public void DiscoverRequireSslWithInsecureRedirect() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- // Include an insecure HTTP jump in those redirects to verify that
- // the ultimate endpoint is never found as a result of high security profile.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
-
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- userSuppliedIdentifier.Discover(this.RequestHandler);
- }
-
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
- Uri secureClaimedUri = new Uri("https://localhost/secureId");
-
- string html = string.Format("<html><head><meta http-equiv='X-XRDS-Location' content='{0}'/></head><body></body></html>", insecureXrdsSource);
- this.MockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
-
- string html = "<html><head></head><body></body></html>";
- WebHeaderCollection headers = new WebHeaderCollection {
- { "X-XRDS-Location", insecureXrdsSource }
- };
- this.MockResponder.RegisterMockResponse(VanityUriSsl, VanityUriSsl, "text/html", headers, html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
- string html = string.Format(
- @"
- <html><head>
- <meta http-equiv='X-XRDS-Location' content='{0}'/> <!-- this one will be insecure and ignored -->
- <link rel='openid2.provider' href='{1}' />
- <link rel='openid2.local_id' href='{2}' />
- </head><body></body></html>",
- HttpUtility.HtmlEncode(insecureXrdsSource),
- HttpUtility.HtmlEncode(OPUriSsl.AbsoluteUri),
- HttpUtility.HtmlEncode(OPLocalIdentifiersSsl[1].AbsoluteUri));
- this.MockResponder.RegisterMockResponse(VanityUriSsl, "text/html", html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
-
- // We verify that the XRDS was ignored and the LINK tags were used
- // because the XRDS OP-LocalIdentifier uses different local identifiers.
- Assert.AreEqual(OPLocalIdentifiersSsl[1], userSuppliedIdentifier.Discover(this.RequestHandler).Single().ProviderLocalIdentifier);
- }
-
- [TestMethod]
- public void DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds() {
- var insecureEndpoint = GetServiceEndpoint(0, ProtocolVersion.V20, 10, false);
- var secureEndpoint = GetServiceEndpoint(1, ProtocolVersion.V20, 20, true);
- UriIdentifier secureClaimedId = new UriIdentifier(VanityUriSsl, true);
- this.MockResponder.RegisterMockXrdsResponse(secureClaimedId, new ServiceEndpoint[] { insecureEndpoint, secureEndpoint });
- Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, secureClaimedId.Discover(this.RequestHandler).Single().ProviderLocalIdentifier);
- }
-
- private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect) {
- this.Discover(url, version, expectedLocalId, providerEndpoint, expectSreg, useRedirect, null);
- }
-
- private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
- Protocol protocol = Protocol.Lookup(version);
- Uri baseUrl = new Uri("http://localhost/");
- UriIdentifier claimedId = new Uri(baseUrl, url);
- UriIdentifier userSuppliedIdentifier = new Uri(baseUrl, "Discovery/htmldiscovery/redirect.aspx?target=" + url);
- if (expectedLocalId == null) {
- expectedLocalId = claimedId;
- }
- Identifier idToDiscover = useRedirect ? userSuppliedIdentifier : claimedId;
-
- string contentType;
- if (url.EndsWith("html")) {
- contentType = "text/html";
- } else if (url.EndsWith("xml")) {
- contentType = "application/xrds+xml";
- } else {
- throw new InvalidOperationException();
- }
- this.MockResponder.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType, headers ?? new WebHeaderCollection(), LoadEmbeddedFile(url));
-
- ServiceEndpoint expected = ServiceEndpoint.CreateForClaimedIdentifier(
- claimedId,
- expectedLocalId,
- new ProviderEndpointDescription(new Uri(providerEndpoint), new string[] { protocol.ClaimedIdentifierServiceTypeURI }), // services aren't checked by Equals
- null,
- null);
-
- ServiceEndpoint se = idToDiscover.Discover(this.RequestHandler).FirstOrDefault(ep => ep.Equals(expected));
- Assert.IsNotNull(se, url + " failed to be discovered.");
-
- // Do extra checking of service type URIs, which aren't included in
- // the ServiceEndpoint.Equals method.
- Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Count);
- Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Contains(protocol.ClaimedIdentifierServiceTypeURI));
- Assert.AreEqual(expectSreg, se.IsExtensionSupported<ClaimsRequest>());
- }
-
- private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
- this.DiscoverXrds(page, version, expectedLocalId, providerEndpoint, null);
- }
-
- private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, WebHeaderCollection headers) {
- if (!page.Contains(".")) {
- page += ".xml";
- }
- this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, false, headers);
- this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, true, headers);
- }
-
- private void DiscoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool useRedirect) {
- this.Discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, providerEndpoint, false, useRedirect);
- }
-
- private void DiscoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
- string page = scenario + ".html";
- this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, false);
- this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, true);
- }
-
- private void FailDiscover(string url) {
- UriIdentifier userSuppliedId = new Uri(new Uri("http://localhost"), url);
-
- this.MockResponder.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html", LoadEmbeddedFile(url));
-
- Assert.AreEqual(0, userSuppliedId.Discover(this.RequestHandler).Count()); // ... but that no endpoint info is discoverable
- }
-
- private void FailDiscoverHtml(string scenario) {
- this.FailDiscover("/Discovery/htmldiscovery/" + scenario + ".html");
- }
-
- private void FailDiscoverXrds(string scenario) {
- this.FailDiscover("/Discovery/xrdsdiscovery/" + scenario + ".xml");
+ Assert.AreEqual(0, Discover(secureId).Count());
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
index 46427bb..d5a51cf 100644
--- a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
@@ -88,386 +88,10 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri));
}
- [TestMethod]
- public void Discover() {
- string xrds = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*Arnott</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:03:24.000Z</Expires>
- <ProviderID>xri://=</ProviderID>
- <LocalID>!9b72.7dd1.50a9.5ccd</LocalID>
- <CanonicalID>=!9B72.7DD1.50A9.5CCD</CanonicalID>
-
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='default' select='false'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null' select='false'/>
- <URI append='qxri' priority='1'>http://1id.com/contact/</URI>
-
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <URI append='qxri' priority='1'>http://1id.com/</URI>
- </Service>
-
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='10'>http://1id.com/sso</URI>
- </Service>
-</XRD>";
- Dictionary<string, string> mocks = new Dictionary<string, string> {
- { "https://xri.net/=Arnott?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
- { "https://xri.net/=!9B72.7DD1.50A9.5CCD?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
- };
- this.MockResponder.RegisterMockXrdsResponses(mocks);
-
- string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
- ServiceEndpoint se = this.VerifyCanonicalId("=Arnott", expectedCanonicalId);
- Assert.AreEqual(Protocol.V10, se.Protocol);
- Assert.AreEqual("http://1id.com/sso", se.ProviderEndpoint.ToString());
- Assert.AreEqual(se.ClaimedIdentifier, se.ProviderLocalIdentifier);
- Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay);
- }
-
- [TestMethod]
- public void DiscoverCommunityInameCanonicalIDs() {
- string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*llli</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:21:06.000Z</Expires>
- <ProviderID>xri://@</ProviderID>
- <LocalID>!72cd.a072.157e.a9c6</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6</CanonicalID>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type match='null' select='false'/>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path match='default'/>
- <Path>(+index)</Path>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI priority='10'>http://resolve.ezibroker.net/resolve/@llli/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
-</XRD>
-";
- string llliAreaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*area</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:07.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA0C</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI>http://resolve.ezibroker.net/resolve/@llli*area/</URI>
- </Service>
-</XRD>";
- string llliAreaCanadaUnattachedResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*canada.unattached</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:08.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA41</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI>http://resolve.ezibroker.net/resolve/@llli*area*canada.unattached/</URI>
- </Service>
-</XRD>";
- string llliAreaCanadaUnattachedAdaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*ada</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:10.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA01</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
-</XRD>";
- string webResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*Web</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:21:12.000Z</Expires>
- <ProviderID>xri://=</ProviderID>
- <LocalID>!91f2.8153.f600.ae24</LocalID>
- <CanonicalID>=!91F2.8153.F600.AE24</CanonicalID>
- <Service priority='10'>
- <Type select='true'>xri://+i-service*(+locator)*($v*1.0)</Type>
- <Path select='true'>(+locator)</Path>
- <MediaType match='default' select='false'/>
- <URI append='qxri'>http://locator.fullxri.com/locator/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://=web</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType select='true'>application/xrds+xml</MediaType>
- <URI append='qxri' priority='1'>https://resolve.freexri.com/ns/=web/</URI>
- <URI append='qxri' priority='2'>http://resolve.freexri.com/ns/=web/</URI>
- </Service>
- <Service priority='10'>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Type select='true'>http://specs.openid.net/auth/2.0/signon</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default' select='false'/>
- <MediaType match='default' select='false'/>
- <URI append='none' priority='2'>http://authn.fullxri.com/authentication/</URI>
- <URI append='none' priority='1'>https://authn.fullxri.com/authentication/</URI>
- </Service>
- <Service priority='10'>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null' select='false'/>
- <MediaType match='default' select='false'/>
- <URI append='qxri'>http://contact.fullxri.com/contact/</URI>
- </Service>
- <KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
- <X509Data>
- <X509Certificate>
-MIIExzCCA6+gAwIBAgIJAM+MlFr0Sth6MA0GCSqGSIb3DQEBBQUAMIGdMR8wHQYD
-VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
-CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
-YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
-YWluLmVkdTAeFw0wNjA4MTcxOTU5NTNaFw0xMTA4MTYxOTU5NTNaMIGdMR8wHQYD
-VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
-CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
-YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
-YWluLmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6uFqas4dK6
-A2wTZL0viRQNJrPyFnFBDSZGib/2ijhgzed/vvmZIBM9sFpwahcuR5hvyKUe37/c
-/RSZXoNDi/eiNOx4qb0l9UB6bd8qvc4V1PnLE7L+ZYcmwrvTKm4x8qXMgEv1wca2
-FPsreHNPdLiTUZ8v0tDTWi3Mgi7y47VTzJaTkcfmO1nL6xAtln5sLdH0PbMM3LAp
-T1d3nwI3VdbhqqZ+6+OKEuC8gk5iH4lfrbr6C9bYS6vzIKrotHpZ3N2aIC3NMjJD
-PMw/mfCuADfRNlHXgZW+0zyUkwGTMDea8qgsoAMWJGdeTIw8I1I3RhnbgLzdsNQl
-b/1ZXx1uJRUCAwEAAaOCAQYwggECMB0GA1UdDgQWBBQe+xSjYTrlfraJARjMxscb
-j36jvDCB0gYDVR0jBIHKMIHHgBQe+xSjYTrlfraJARjMxscbj36jvKGBo6SBoDCB
-nTEfMB0GA1UEAxMWU3VwZXJ2aWxsYWluOiBUaGUgUm9vdDELMAkGA1UEBhMCVVMx
-ETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZHb3RoYW0xIDAeBgNVBAoTF1N1
-cGVydmlsbGFpbiBVbml2ZXJzaXR5MScwJQYJKoZIhvcNAQkBFhhwZW5ndWluQHN1
-cGVydmlsbGFpbi5lZHWCCQDPjJRa9ErYejAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4IBAQC4SPBDGYAxfbXd8N5OvG0drM7a5hjXfcCZpiILlPSRpxp79yh7
-I5vVWxBxUfolwbei7PTBVy7CE27SUbSICeqWjcDCfjNjiZk6mLS80rm/TdLrHSyM
-+Ujlw9MGcBGaLI+sdziDUMtTQDpeAyQTaGVbh1mx5874Hlo1VXqGYNo0RwR+iLfs
-x48VuO6GbWVyxtktkE2ypz1KLWiyI056YynydRvuBCBHeRqGUixPlH9CrmeSCP2S
-sfbiKnMOGXjIYbvbsTAMdW2iqg6IWa/fgxhvZoAXChM9bkhisJQc0qD0J5TJQwgr
-uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
- </X509Certificate>
- </X509Data>
- </KeyInfo>
-</XRD>";
- this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
- { "https://xri.net/@llli?_xrd_r=application/xrd%2Bxml;sep=false", llliResponse },
- { "https://xri.net/@llli*area?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaResponse },
- { "https://xri.net/@llli*area*canada.unattached?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedResponse },
- { "https://xri.net/@llli*area*canada.unattached*ada?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedAdaResponse },
- { "https://xri.net/=Web?_xrd_r=application/xrd%2Bxml;sep=false", webResponse },
- });
- this.VerifyCanonicalId("@llli", "@!72CD.A072.157E.A9C6");
- this.VerifyCanonicalId("@llli*area", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C");
- this.VerifyCanonicalId("@llli*area*canada.unattached", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41");
- this.VerifyCanonicalId("@llli*area*canada.unattached*ada", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01");
- this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24");
- }
-
- [TestMethod]
- public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
- this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
- { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*andrew.arnott</Query>
- <Status cid='absent' code='100'>Success</Status>
- <ServerStatus code='100'>Success</ServerStatus>
- <Expires>2008-07-14T03:30:59.722Z</Expires>
- <ProviderID>=!91F2.8153.F600.AE24</ProviderID>
- <Service>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
- <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://contact.freexri.com/contact/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path select='true'>(+index)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://authn.freexri.com/authentication/</URI>
- <URI append='none' priority='1'>https://authn.freexri.com/authentication/</URI>
- </Service>
- <ServedBy>OpenXRI</ServedBy>
-</XRD>" },
- { "https://xri.net/@id*andrewarnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*andrewarnott</Query>
- <Status cid='absent' code='100'>Success</Status>
- <ServerStatus code='100'>Success</ServerStatus>
- <Expires>2008-07-14T03:31:00.466Z</Expires>
- <ProviderID>@!B1E8.C27B.E41C.25C3</ProviderID>
- <Service>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
- <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://contact.freexri.com/contact/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path select='true'>(+index)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
- </Service>
- <ServedBy>OpenXRI</ServedBy>
-</XRD>" },
- });
- // Consistent with spec section 7.3.2.3, we do not permit
- // delegation on XRI discovery when there is no CanonicalID present.
- this.VerifyCanonicalId("=Web*andrew.arnott", null);
- this.VerifyCanonicalId("@id*andrewarnott", null);
- }
-
[TestMethod, Ignore] // XRI parsing and normalization is not implemented (yet).
public void NormalizeCase() {
Identifier id = "=!9B72.7dd1.50a9.5ccd";
Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", id.ToString());
}
-
- private ServiceEndpoint VerifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
- ServiceEndpoint se = iname.Discover(this.RequestHandler).FirstOrDefault();
- if (expectedClaimedIdentifier != null) {
- Assert.IsNotNull(se);
- Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname);
- Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Count > 0);
- } else {
- Assert.IsNull(se);
- }
- return se;
- }
}
}