summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-11-24 19:44:57 -0800
committerAndrew <andrewarnott@gmail.com>2008-11-24 19:44:57 -0800
commit143d80b2ce76ef6eee4bddda9039a0b0f9673356 (patch)
treebcbf7ee6e089d85a3e4ee834871b5edb1a8a43fa /src
parente81621138e95624e12db5667c5720cde1f0475d9 (diff)
downloadDotNetOpenAuth-143d80b2ce76ef6eee4bddda9039a0b0f9673356.zip
DotNetOpenAuth-143d80b2ce76ef6eee4bddda9039a0b0f9673356.tar.gz
DotNetOpenAuth-143d80b2ce76ef6eee4bddda9039a0b0f9673356.tar.bz2
Added discovery and around 60 tests. The discovery and a few other tests still fail, but we're making progress.
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj33
-rw-r--r--src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs61
-rw-r--r--src/DotNetOpenAuth.Test/Hosting/HttpHost.cs93
-rw-r--r--src/DotNetOpenAuth.Test/Hosting/TestingWorkerRequest.cs91
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs179
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs68
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/TestWebRequestHandler.cs18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html1020.html12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10both.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10del.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10prov.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010.html12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedA.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedB.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedC.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20both.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20del.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20prov.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20relative.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHead.html12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHttpHeader.html9
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds-irrelevant.xml12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds10.xml14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds1020.xml18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds11.xml13
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20.xml13
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010a.xml18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010b.xml18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs13
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/TestSupport.cs364
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/UI/UITestSupport.cs21
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs107
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs37
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj1
-rw-r--r--src/DotNetOpenAuth/Messaging/IDirectSslWebRequestHandler.cs39
-rw-r--r--src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs7
-rw-r--r--src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs84
-rw-r--r--src/DotNetOpenAuth/OpenId/Identifier.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Realm.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/UriIdentifier.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/XriIdentifier.cs12
-rw-r--r--src/DotNetOpenAuth/Yadis/Yadis.cs14
45 files changed, 1391 insertions, 139 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 6e294e5..a0f6549 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -60,6 +60,9 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CoordinatorBase.cs" />
+ <Compile Include="Hosting\AspNetHost.cs" />
+ <Compile Include="Hosting\HttpHost.cs" />
+ <Compile Include="Hosting\TestingWorkerRequest.cs" />
<Compile Include="Messaging\CollectionAssert.cs" />
<Compile Include="Messaging\ErrorUtilitiesTests.cs" />
<Compile Include="Messaging\MessageSerializerTests.cs" />
@@ -75,6 +78,8 @@
<Compile Include="Messaging\Reflection\ValueMappingTests.cs" />
<Compile Include="Mocks\CoordinatingChannel.cs" />
<Compile Include="Mocks\InMemoryTokenManager.cs" />
+ <Compile Include="Mocks\MockHttpRequest.cs" />
+ <Compile Include="Mocks\MockIdentifier.cs" />
<Compile Include="Mocks\MockTransformationBindingElement.cs" />
<Compile Include="Mocks\MockReplayProtectionBindingElement.cs" />
<Compile Include="Mocks\TestBaseMessage.cs" />
@@ -97,6 +102,7 @@
<Compile Include="OAuth\ProtocolTests.cs" />
<Compile Include="OAuth\ServiceProviderDescriptionTests.cs" />
<Compile Include="OpenId\ChannelElements\KeyValueFormEncodingTests.cs" />
+ <Compile Include="OpenId\IdentifierTests.cs" />
<Compile Include="OpenId\Messages\AssociateDiffieHellmanRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateUnsuccessfulResponseTests.cs" />
@@ -109,6 +115,10 @@
<Compile Include="OpenId\AssociationHandshakeTests.cs" />
<Compile Include="OpenId\OpenIdTestBase.cs" />
<Compile Include="OpenId\RealmTests.cs" />
+ <Compile Include="OpenId\TestSupport.cs" />
+ <Compile Include="OpenId\UI\UITestSupport.cs" />
+ <Compile Include="OpenId\UriIdentifierTests.cs" />
+ <Compile Include="OpenId\XriIdentifierTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Messaging\ResponseTests.cs" />
<Compile Include="OAuth\AppendixScenarios.cs" />
@@ -130,6 +140,29 @@
<ItemGroup>
<Shadow Include="Test References\DotNetOpenAuth.accessor" />
</ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html1020.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html10both.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html10del.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html10prov.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html2010.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html2010combinedA.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html2010combinedB.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html2010combinedC.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20both.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20del.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20prov.html" />
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20relative.html" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds-irrelevant.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds10.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds1020.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds11.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds20.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds2010a.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds2010b.xml" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\XrdsReferencedInHead.html" />
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\XrdsReferencedInHttpHeader.html" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs b/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs
new file mode 100644
index 0000000..0bbca5e
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs
@@ -0,0 +1,61 @@
+namespace DotNetOpenAuth.Test.Hosting {
+ using System;
+ using System.IO;
+ using System.Net;
+ using System.Threading;
+ using System.Web;
+ using System.Web.Hosting;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Test.OpenId;
+
+ /// <summary>
+ /// Hosts a 'portable' version of the OpenIdProvider for testing itself and the
+ /// RelyingParty against it.
+ /// </summary>
+ class AspNetHost : MarshalByRefObject {
+ HttpHost httpHost;
+
+ public AspNetHost() {
+ httpHost = HttpHost.CreateHost(this);
+ ////if (!UntrustedWebRequestHandler.WhitelistHosts.Contains("localhost"))
+ //// UntrustedWebRequestHandler.WhitelistHosts.Add("localhost");
+ }
+
+ public Uri BaseUri {
+ get { return httpHost.BaseUri; }
+ }
+
+ public static AspNetHost CreateHost(string webDirectory) {
+ AspNetHost host = (AspNetHost)ApplicationHost.
+ CreateApplicationHost(typeof(AspNetHost), "/", webDirectory);
+ return host;
+ }
+
+ public string ProcessRequest(string url) {
+ return httpHost.ProcessRequest(url);
+ }
+
+ public string ProcessRequest(string url, string body) {
+ return httpHost.ProcessRequest(url, body);
+ }
+
+ public void BeginProcessRequest(HttpListenerContext context) {
+ ThreadPool.QueueUserWorkItem(state => { ProcessRequest(context); });
+ }
+
+ public void ProcessRequest(HttpListenerContext context) {
+ try {
+ using (TextWriter tw = new StreamWriter(context.Response.OutputStream)) {
+ HttpRuntime.ProcessRequest(new TestingWorkerRequest(context, tw));
+ }
+ } catch (Exception ex) {
+ Logger.Error("Exception in AspNetHost", ex);
+ throw;
+ }
+ }
+
+ public void CloseHttp() {
+ httpHost.Dispose();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Hosting/HttpHost.cs b/src/DotNetOpenAuth.Test/Hosting/HttpHost.cs
new file mode 100644
index 0000000..9606cb7
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Hosting/HttpHost.cs
@@ -0,0 +1,93 @@
+namespace DotNetOpenAuth.Test.Hosting {
+ using System;
+ using System.Globalization;
+ using System.IO;
+ using System.Net;
+ using System.Threading;
+
+ class HttpHost : IDisposable {
+ HttpListener listener;
+ public int Port { get; private set; }
+ Thread listenerThread;
+ AspNetHost aspNetHost;
+
+ HttpHost(AspNetHost aspNetHost) {
+ this.aspNetHost = aspNetHost;
+
+ Port = 59687;
+ Random r = new Random();
+ tryAgain:
+ try {
+ listener = new HttpListener();
+ listener.Prefixes.Add(string.Format(CultureInfo.InvariantCulture,
+ "http://localhost:{0}/", Port));
+ listener.Start();
+ } catch (HttpListenerException ex) {
+ if (ex.Message.Contains("conflicts")) {
+ Port += r.Next(1, 20);
+ goto tryAgain;
+ }
+ throw;
+ }
+ listenerThread = new Thread(processRequests);
+ listenerThread.Start();
+ }
+
+ public static HttpHost CreateHost(AspNetHost aspNetHost) {
+ return new HttpHost(aspNetHost);
+ }
+
+ public static HttpHost CreateHost(string webDirectory) {
+ return new HttpHost(AspNetHost.CreateHost(webDirectory));
+ }
+ void processRequests() {
+ try {
+ while (true) {
+ var context = listener.GetContext();
+ aspNetHost.BeginProcessRequest(context);
+ }
+ } catch (HttpListenerException) {
+ // the listener is probably being shut down
+ }
+ }
+
+ public Uri BaseUri {
+ get { return new Uri("http://localhost:" + Port.ToString() + "/"); }
+ }
+ public string ProcessRequest(string url) {
+ return ProcessRequest(url, null);
+ }
+ public string ProcessRequest(string url, string body) {
+ WebRequest request = WebRequest.Create(new Uri(BaseUri, url));
+ if (body != null) {
+ request.Method = "POST";
+ request.ContentLength = body.Length;
+ using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))
+ sw.Write(body);
+ }
+ try {
+ using (WebResponse response = request.GetResponse()) {
+ using (StreamReader sr = new StreamReader(response.GetResponseStream()))
+ return sr.ReadToEnd();
+ }
+ } catch (WebException ex) {
+ Logger.Error("Exception in HttpHost", ex);
+ using (StreamReader sr = new StreamReader(ex.Response.GetResponseStream())) {
+ string streamContent = sr.ReadToEnd();
+ Logger.ErrorFormat("Error content stream follows: {0}", streamContent);
+ }
+ throw;
+ }
+ }
+
+ #region IDisposable Members
+
+ public void Dispose() {
+ listener.Close();
+ listenerThread.Join(1000);
+ listenerThread.Abort();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Hosting/TestingWorkerRequest.cs b/src/DotNetOpenAuth.Test/Hosting/TestingWorkerRequest.cs
new file mode 100644
index 0000000..29f1c4c
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Hosting/TestingWorkerRequest.cs
@@ -0,0 +1,91 @@
+namespace DotNetOpenAuth.Test.Hosting {
+ using System;
+ using System.IO;
+ using System.Net;
+ using System.Web.Hosting;
+
+ class TestingWorkerRequest : SimpleWorkerRequest {
+ public TestingWorkerRequest(string page, string query, Stream entityStream, TextWriter writer)
+ : base(page, query, writer) {
+ this.entityStream = entityStream;
+ this.writer = writer;
+ }
+ public TestingWorkerRequest(HttpListenerContext context, TextWriter output)
+ : base(context.Request.Url.LocalPath.TrimStart('/'), context.Request.Url.Query, output) {
+ this.entityStream = context.Request.InputStream;
+ this.context = context;
+ this.writer = output;
+ }
+
+ Stream entityStream;
+ HttpListenerContext context;
+ TextWriter writer;
+ public override string GetFilePath() {
+ string filePath = context.Request.Url.LocalPath.Replace("/", "\\");
+ if (filePath.EndsWith("\\", StringComparison.Ordinal))
+ filePath += "default.aspx";
+ return filePath;
+ }
+ public override int GetLocalPort() {
+ return context.Request.Url.Port;
+ }
+ public override string GetServerName() {
+ return context.Request.Url.Host;
+ }
+ public override string GetQueryString() {
+ return context.Request.Url.Query.TrimStart('?');
+ }
+ public override string GetHttpVerbName() {
+ return context.Request.HttpMethod;
+ }
+ public override string GetLocalAddress() {
+ return context.Request.LocalEndPoint.Address.ToString();
+ }
+ public override string GetHttpVersion() {
+ return "HTTP/1.1";
+ }
+ public override string GetProtocol() {
+ return context.Request.Url.Scheme;
+ }
+ public override string GetRawUrl() {
+ return context.Request.RawUrl;
+ }
+ public override int GetTotalEntityBodyLength() {
+ return (int)context.Request.ContentLength64;
+ }
+ public override string GetKnownRequestHeader(int index) {
+ return context.Request.Headers[GetKnownRequestHeaderName(index)];
+ }
+ public override string GetUnknownRequestHeader(string name) {
+ return context.Request.Headers[name];
+ }
+ public override bool IsEntireEntityBodyIsPreloaded() {
+ return false;
+ }
+ public override int ReadEntityBody(byte[] buffer, int size) {
+ return entityStream.Read(buffer, 0, size);
+ }
+ public override int ReadEntityBody(byte[] buffer, int offset, int size) {
+ return entityStream.Read(buffer, offset, size);
+ }
+ public override void SendCalculatedContentLength(int contentLength) {
+ context.Response.ContentLength64 = contentLength;
+ }
+ public override void SendStatus(int statusCode, string statusDescription) {
+ if (context != null) {
+ context.Response.StatusCode = statusCode;
+ context.Response.StatusDescription = statusDescription;
+ }
+ }
+ public override void SendKnownResponseHeader(int index, string value) {
+ if (context != null) {
+ context.Response.Headers[(HttpResponseHeader)index] = value;
+ }
+ }
+ public override void SendUnknownResponseHeader(string name, string value) {
+ if (context != null) {
+ context.Response.Headers[name] = value;
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs
new file mode 100644
index 0000000..a9c6ad4
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs
@@ -0,0 +1,179 @@
+namespace DotNetOpenAuth.Test.Mocks {
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Net;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Yadis;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.Test.OpenId;
+
+ internal class MockHttpRequest {
+ private readonly Dictionary<Uri, DirectWebResponse> registeredMockResponses = new Dictionary<Uri, DirectWebResponse>();
+ private readonly TestWebRequestHandler mockHandler;
+
+ internal MockHttpRequest(TestWebRequestHandler mockHandler) {
+ ErrorUtilities.VerifyArgumentNotNull(mockHandler, "mockHandler");
+ this.mockHandler = mockHandler;
+ this.mockHandler.Callback = this.GetMockResponse;
+ }
+
+ private DirectWebResponse GetMockResponse(HttpWebRequest request) {
+ DirectWebResponse response;
+ if (this.registeredMockResponses.TryGetValue(request.RequestUri, out response)) {
+ // reset response stream position so this response can be reused on a subsequent request.
+ response.ResponseStream.Seek(0, SeekOrigin.Begin);
+ return response;
+ } else {
+ ////Assert.Fail("Unexpected HTTP request: {0}", uri);
+ Logger.WarnFormat("Unexpected HTTP request: {0}", request.RequestUri);
+ return new DirectWebResponse(request.RequestUri, request.RequestUri, new WebHeaderCollection(), HttpStatusCode.NotFound,
+ "text/html", null, new MemoryStream());
+ }
+ }
+
+ /// <summary>
+ /// Clears all all mock HTTP responses and deactivates HTTP mocking.
+ /// </summary>
+ internal void Reset() {
+ this.registeredMockResponses.Clear();
+ }
+
+ internal void RegisterMockResponse(DirectWebResponse response) {
+ if (response == null) throw new ArgumentNullException("response");
+ if (registeredMockResponses.ContainsKey(response.RequestUri)) {
+ Logger.WarnFormat("Mock HTTP response already registered for {0}.", response.RequestUri);
+ } else {
+ registeredMockResponses.Add(response.RequestUri, response);
+ }
+ }
+
+ internal void RegisterMockResponse(Uri requestUri, string contentType, string responseBody) {
+ RegisterMockResponse(requestUri, requestUri, contentType, responseBody);
+ }
+
+ internal void RegisterMockResponse(Uri requestUri, Uri responseUri, string contentType, string responseBody) {
+ RegisterMockResponse(requestUri, responseUri, contentType, new WebHeaderCollection(), responseBody);
+ }
+
+ internal void RegisterMockResponse(Uri requestUri, Uri responseUri, string contentType, WebHeaderCollection headers, string responseBody) {
+ if (requestUri == null) throw new ArgumentNullException("requestUri");
+ if (responseUri == null) throw new ArgumentNullException("responseUri");
+ if (String.IsNullOrEmpty(contentType)) throw new ArgumentNullException("contentType");
+
+ // Set up the redirect if appropriate
+ if (requestUri != responseUri) {
+ RegisterMockRedirect(requestUri, responseUri);
+ }
+
+ string contentEncoding = null;
+ MemoryStream stream = new MemoryStream();
+ StreamWriter sw = new StreamWriter(stream);
+ sw.Write(responseBody);
+ sw.Flush();
+ stream.Seek(0, SeekOrigin.Begin);
+ RegisterMockResponse(new DirectWebResponse(responseUri, responseUri, headers ?? new WebHeaderCollection(),
+ HttpStatusCode.OK, contentType, contentEncoding, stream));
+ }
+
+ internal void RegisterMockXrdsResponses(IDictionary<string, string> requestUriAndResponseBody) {
+ foreach (var pair in requestUriAndResponseBody) {
+ RegisterMockResponse(new Uri(pair.Key), "text/xml; saml=false; https=false; charset=UTF-8", pair.Value);
+ }
+ }
+
+ internal void RegisterMockXrdsResponse(ServiceEndpoint endpoint) {
+ if (endpoint == null) throw new ArgumentNullException("endpoint");
+
+ string identityUri;
+ if (endpoint.ClaimedIdentifier == endpoint.Protocol.ClaimedIdentifierForOPIdentifier) {
+ identityUri = endpoint.UserSuppliedIdentifier;
+ } else {
+ identityUri = endpoint.UserSuppliedIdentifier ?? endpoint.ClaimedIdentifier;
+ }
+ RegisterMockXrdsResponse(new Uri(identityUri), new ServiceEndpoint[] { endpoint });
+ }
+
+ internal void RegisterMockXrdsResponse(Uri respondingUri, IEnumerable<ServiceEndpoint> endpoints) {
+ if (endpoints == null) throw new ArgumentNullException("endpoints");
+
+ StringBuilder xrds = new StringBuilder();
+ xrds.AppendLine(@"<xrds:XRDS xmlns:xrds='xri://$xrds' xmlns:openid='http://openid.net/xmlns/1.0' xmlns='xri://$xrd*($v*2.0)'>
+ <XRD>");
+ foreach (var endpoint in endpoints) {
+ string template = @"
+ <Service priority='10'>
+ <Type>{0}</Type>
+ <URI>{1}</URI>
+ <LocalID>{2}</LocalID>
+ <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>{2}</openid:Delegate>
+ </Service>";
+ string serviceTypeUri;
+ if (endpoint.ClaimedIdentifier == endpoint.Protocol.ClaimedIdentifierForOPIdentifier) {
+ serviceTypeUri = endpoint.Protocol.OPIdentifierServiceTypeURI;
+ } else {
+ serviceTypeUri = endpoint.Protocol.ClaimedIdentifierServiceTypeURI;
+ }
+ string xrd = string.Format(CultureInfo.InvariantCulture, template,
+ HttpUtility.HtmlEncode(serviceTypeUri),
+ HttpUtility.HtmlEncode(endpoint.ProviderEndpoint.AbsoluteUri),
+ HttpUtility.HtmlEncode(endpoint.ProviderLocalIdentifier));
+ xrds.Append(xrd);
+ }
+ xrds.Append(@"
+ </XRD>
+</xrds:XRDS>");
+
+ RegisterMockResponse(respondingUri, ContentTypes.Xrds, xrds.ToString());
+ }
+ internal void RegisterMockXrdsResponse(UriIdentifier directedIdentityAssignedIdentifier, ServiceEndpoint providerEndpoint) {
+ ServiceEndpoint identityEndpoint = ServiceEndpoint.CreateForClaimedIdentifier(
+ directedIdentityAssignedIdentifier,
+ directedIdentityAssignedIdentifier,
+ providerEndpoint.ProviderEndpoint,
+ new string[] { providerEndpoint.Protocol.ClaimedIdentifierServiceTypeURI },
+ 10,
+ 10);
+ RegisterMockXrdsResponse(identityEndpoint);
+ }
+ internal Identifier RegisterMockXrdsResponse(string embeddedResourcePath) {
+ UriIdentifier id = TestSupport.GetFullUrl(embeddedResourcePath);
+ RegisterMockResponse(id, "application/xrds+xml", TestSupport.LoadEmbeddedFile(embeddedResourcePath));
+ return id;
+ }
+ internal void RegisterMockRPDiscovery() {
+ Uri rpRealmUri = TestSupport.Realm.UriWithWildcardChangedToWww;
+
+ string template = @"<xrds:XRDS xmlns:xrds='xri://$xrds' xmlns:openid='http://openid.net/xmlns/1.0' xmlns='xri://$xrd*($v*2.0)'>
+ <XRD>
+ <Service priority='10'>
+ <Type>{0}</Type>
+ <URI>{1}</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>";
+ string xrds = string.Format(CultureInfo.InvariantCulture, template,
+ HttpUtility.HtmlEncode(Protocol.V20.RPReturnToTypeURI),
+ HttpUtility.HtmlEncode(rpRealmUri.AbsoluteUri));
+
+ RegisterMockResponse(rpRealmUri, ContentTypes.Xrds, xrds);
+ }
+
+ internal void DeleteResponse(Uri requestUri) {
+ this.registeredMockResponses.Remove(requestUri);
+ }
+
+ internal void RegisterMockRedirect(Uri origin, Uri redirectLocation) {
+ var redirectionHeaders = new WebHeaderCollection {
+ { HttpResponseHeader.Location, redirectLocation.AbsoluteUri },
+ };
+ DirectWebResponse response = new DirectWebResponse(origin, origin,
+ redirectionHeaders, HttpStatusCode.Redirect, null, null, new MemoryStream());
+ RegisterMockResponse(response);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
new file mode 100644
index 0000000..2b7a7a9
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------
+// <copyright file="MockIdentifier.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Mocks {
+ using System;
+ using System.Collections.Generic;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.OpenId;
+using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// Performs similar to an ordinary <see cref="Identifier"/>, but when called upon
+ /// to perform discovery, it returns a preset list of sevice endpoints to avoid
+ /// having a dependency on a hosted web site to actually perform discovery on.
+ /// </summary>
+ class MockIdentifier : Identifier {
+ IEnumerable<ServiceEndpoint> endpoints;
+ MockHttpRequest mockHttpRequest;
+ Identifier wrappedIdentifier;
+
+ public MockIdentifier(Identifier wrappedIdentifier, MockHttpRequest mockHttpRequest, IEnumerable<ServiceEndpoint> endpoints)
+ : base(false) {
+ ErrorUtilities.VerifyArgumentNotNull(wrappedIdentifier, "wrappedIdentifier");
+ ErrorUtilities.VerifyArgumentNotNull(mockHttpRequest, "mockHttpRequest");
+ ErrorUtilities.VerifyArgumentNotNull(endpoints, "endpoints");
+
+ this.wrappedIdentifier = wrappedIdentifier;
+ this.endpoints = endpoints;
+ this.mockHttpRequest = mockHttpRequest;
+
+ // Register a mock HTTP response to enable discovery of this identifier within the RP
+ // without having to host an ASP.NET site within the test.
+ mockHttpRequest.RegisterMockXrdsResponse(new Uri(wrappedIdentifier.ToString()), endpoints);
+ }
+
+ internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) {
+ return endpoints;
+ }
+
+ internal override Identifier TrimFragment() {
+ return this;
+ }
+
+ internal override bool TryRequireSsl(out Identifier secureIdentifier) {
+ // We take special care to make our wrapped identifier secure, but still
+ // return a mocked (secure) identifier.
+ Identifier secureWrappedIdentifier;
+ bool result = wrappedIdentifier.TryRequireSsl(out secureWrappedIdentifier);
+ secureIdentifier = new MockIdentifier(secureWrappedIdentifier, this.mockHttpRequest, this.endpoints);
+ return result;
+ }
+
+ public override string ToString() {
+ return wrappedIdentifier.ToString();
+ }
+
+ public override bool Equals(object obj) {
+ return wrappedIdentifier.Equals(obj);
+ }
+
+ public override int GetHashCode() {
+ return wrappedIdentifier.GetHashCode();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Mocks/TestWebRequestHandler.cs b/src/DotNetOpenAuth.Test/Mocks/TestWebRequestHandler.cs
index af971a0..e655238 100644
--- a/src/DotNetOpenAuth.Test/Mocks/TestWebRequestHandler.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/TestWebRequestHandler.cs
@@ -12,7 +12,7 @@ namespace DotNetOpenAuth.Test.Mocks {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth.ChannelElements;
- internal class TestWebRequestHandler : IDirectWebRequestHandler {
+ internal class TestWebRequestHandler : IDirectSslWebRequestHandler {
private StringBuilder postEntity;
/// <summary>
@@ -72,5 +72,21 @@ namespace DotNetOpenAuth.Test.Mocks {
}
#endregion
+
+ #region IDirectSslWebRequestHandler Members
+
+ public TextWriter GetRequestStream(HttpWebRequest request, bool requireSsl) {
+ ErrorUtilities.VerifyProtocol(!requireSsl || request.RequestUri.Scheme == Uri.UriSchemeHttps, "disallowed request");
+ return this.GetRequestStream(request);
+ }
+
+ public DirectWebResponse GetResponse(HttpWebRequest request, bool requireSsl) {
+ ErrorUtilities.VerifyProtocol(!requireSsl || request.RequestUri.Scheme == Uri.UriSchemeHttps, "disallowed request");
+ var result = this.GetResponse(request);
+ ErrorUtilities.VerifyProtocol(!requireSsl || result.FinalUri.Scheme == Uri.UriSchemeHttps, "disallowed request");
+ return result;
+ }
+
+ #endregion
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html1020.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html1020.html
new file mode 100644
index 0000000..5fc841f
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html1020.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid.server" href="http://e/f" />
+ <link rel="openid.delegate" href="http://g/h" />
+ <link rel="openid2.provider" href="http://a/b" />
+ <link rel="openid2.local_id" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10both.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10both.html
new file mode 100644
index 0000000..d350abe
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10both.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid.server" href="http://a/b" />
+ <link rel="openid.delegate" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10del.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10del.html
new file mode 100644
index 0000000..c19028b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10del.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid.delegate" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10prov.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10prov.html
new file mode 100644
index 0000000..f787dce
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html10prov.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid.server" href="http://a/b" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010.html
new file mode 100644
index 0000000..61d1305
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.provider" href="http://a/b" />
+ <link rel="openid2.local_id" href="http://c/d" />
+ <link rel="openid.server" href="http://e/f" />
+ <link rel="openid.delegate" href="http://g/h" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedA.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedA.html
new file mode 100644
index 0000000..883344b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedA.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.provider B openid.server" href="http://a/b" />
+ <link rel="openid2.local_id B openid.delegate" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedB.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedB.html
new file mode 100644
index 0000000..3da5a73
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedB.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="A openid2.provider openid.server" href="http://a/b" />
+ <link rel="A openid2.local_id openid.delegate" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedC.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedC.html
new file mode 100644
index 0000000..2950500
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html2010combinedC.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid.server B openid2.provider" href="http://a/b" />
+ <link rel="openid.delegate B openid2.local_id" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20both.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20both.html
new file mode 100644
index 0000000..77d9346
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20both.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.provider" href="http://a/b" />
+ <link rel="openid2.local_id" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20del.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20del.html
new file mode 100644
index 0000000..b8d65c5
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20del.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.local_id" href="http://c/d" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20prov.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20prov.html
new file mode 100644
index 0000000..de51e42
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20prov.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.provider" href="http://a/b" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20relative.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20relative.html
new file mode 100644
index 0000000..0e9f341
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20relative.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <link rel="openid2.provider" href="../a/b" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHead.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHead.html
new file mode 100644
index 0000000..142ab4d
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHead.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head runat="server">
+ <title>Untitled Page</title>
+ <meta http-equiv="X-XRDS-Location" content="http://localhost/xrds1020.xml"/>
+</head>
+<body>
+ <form id="form1" runat="server">
+ </form>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHttpHeader.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHttpHeader.html
new file mode 100644
index 0000000..a394aff
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/XrdsReferencedInHttpHeader.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head runat="server">
+ <title>Untitled Page</title>
+</head>
+<body>
+ <form id="form1" runat="server">
+ </form>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds-irrelevant.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds-irrelevant.xml
new file mode 100644
index 0000000..5116c0b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds-irrelevant.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>junk</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds10.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds10.xml
new file mode 100644
index 0000000..c67b36e
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds10.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <!-- this next sreg one is deliberately an unofficial (but supported) sreg/1.0 typeUri, so we test it. -->
+ <Type>http://openid.net/sreg/1.0</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds1020.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds1020.xml
new file mode 100644
index 0000000..1b56f0f
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds1020.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ <Service priority="20">
+ <Type>http://specs.openid.net/auth/2.0/signon</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://c/d</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds11.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds11.xml
new file mode 100644
index 0000000..2d6a7aa
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds11.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.1</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20.xml
new file mode 100644
index 0000000..870b540
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://specs.openid.net/auth/2.0/signon</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010a.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010a.xml
new file mode 100644
index 0000000..4f72ac2
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010a.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://specs.openid.net/auth/2.0/signon</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ <Service priority="20">
+ <Type>http://openid.net/signon/1.0</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://c/d</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010b.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010b.xml
new file mode 100644
index 0000000..8ad468f
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds2010b.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="20">
+ <Type>http://openid.net/signon/1.0</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://c/d</URI>
+ </Service>
+ <Service priority="10">
+ <Type>http://specs.openid.net/auth/2.0/signon</Type>
+ <Type>http://openid.net/extensions/sreg/1.1</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
index 8c3bc3b..941aa70 100644
--- a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
@@ -14,8 +14,8 @@ namespace DotNetOpenAuth.Test.OpenId {
[TestMethod]
public void Parse() {
- Assert.IsInstanceOfType(typeof(UriIdentifier), Identifier.Parse(uri));
- Assert.IsInstanceOfType(typeof(XriIdentifier), Identifier.Parse(xri));
+ Assert.IsInstanceOfType(Identifier.Parse(uri), typeof(UriIdentifier));
+ Assert.IsInstanceOfType(Identifier.Parse(xri), typeof(XriIdentifier));
}
/// <summary>
@@ -30,7 +30,7 @@ namespace DotNetOpenAuth.Test.OpenId {
prefixes.AddRange(symbols.Select(s => "xri://" + s.ToString()));
foreach (string prefix in prefixes) {
var id = Identifier.Parse(prefix + "andrew");
- Assert.IsInstanceOfType(typeof(XriIdentifier), id);
+ Assert.IsInstanceOfType(id, typeof(XriIdentifier));
}
}
@@ -41,15 +41,15 @@ namespace DotNetOpenAuth.Test.OpenId {
public void ParseEndUserSuppliedUriIdentifier() {
// verify a fully-qualified Uri
var id = Identifier.Parse(uri);
- Assert.IsInstanceOfType(typeof(UriIdentifier), id);
+ Assert.IsInstanceOfType(id, typeof(UriIdentifier));
Assert.AreEqual(uri, ((UriIdentifier)id).Uri.AbsoluteUri);
// verify an HTTPS Uri
id = Identifier.Parse(uriHttps);
- Assert.IsInstanceOfType(typeof(UriIdentifier), id);
+ Assert.IsInstanceOfType(id, typeof(UriIdentifier));
Assert.AreEqual(uriHttps, ((UriIdentifier)id).Uri.AbsoluteUri);
// verify that if the scheme is missing it is added automatically
id = Identifier.Parse(uriNoScheme);
- Assert.IsInstanceOfType(typeof(UriIdentifier), id);
+ Assert.IsInstanceOfType(id, typeof(UriIdentifier));
Assert.AreEqual(uri, ((UriIdentifier)id).Uri.AbsoluteUri);
}
@@ -58,7 +58,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Identifier.Parse(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
public void ParseEmpty() {
Identifier.Parse(string.Empty);
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
index 4b52634..4eff09f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
@@ -8,17 +8,26 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.Test.Mocks;
public class OpenIdTestBase : TestBase {
protected RelyingPartySecuritySettings RelyingPartySecuritySettings { get; private set; }
protected ProviderSecuritySettings ProviderSecuritySettings { get; private set; }
+ internal TestWebRequestHandler requestHandler;
+ internal MockHttpRequest mockResponder;
+
+ [TestInitialize]
public override void SetUp() {
base.SetUp();
- RelyingPartySecuritySettings = RelyingPartySection.Configuration.SecuritySettings.CreateSecuritySettings();
- ProviderSecuritySettings = ProviderSection.Configuration.SecuritySettings.CreateSecuritySettings();
+ this.RelyingPartySecuritySettings = RelyingPartySection.Configuration.SecuritySettings.CreateSecuritySettings();
+ this.ProviderSecuritySettings = ProviderSection.Configuration.SecuritySettings.CreateSecuritySettings();
+
+ this.requestHandler = new TestWebRequestHandler();
+ this.mockResponder = new MockHttpRequest(requestHandler);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs b/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs
new file mode 100644
index 0000000..4e742dc
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs
@@ -0,0 +1,364 @@
+//-----------------------------------------------------------------------
+// <copyright file="TestSupport.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Specialized;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Reflection;
+ using System.Web;
+ using DotNetOpenAuth;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Provider;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Mocks;
+ //using DotNetOpenAuth.Test.UI;
+ using log4net;
+ using IProviderAssociationStore = DotNetOpenAuth.OpenId.IAssociationStore<DotNetOpenAuth.OpenId.AssociationRelyingPartyType>;
+ using ProviderMemoryStore = DotNetOpenAuth.OpenId.AssociationMemoryStore<DotNetOpenAuth.OpenId.AssociationRelyingPartyType>;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOAuth.Test.OpenId.UI;
+ using DotNetOpenAuth.Messaging;
+
+ public class TestSupport {
+ public static readonly string TestWebDirectory = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\src\DotNetOpenId.TestWeb"));
+ public const string HostTestPage = "HostTest.aspx";
+ const string identityPage = "IdentityEndpoint.aspx";
+ const string directedIdentityPage = "DirectedIdentityEndpoint.aspx";
+ public const string ProviderPage = "ProviderEndpoint.aspx";
+ public const string DirectedProviderEndpoint = "DirectedProviderEndpoint.aspx";
+ public const string MobileConsumerPage = "RelyingPartyMobile.aspx";
+ public const string ConsumerPage = "RelyingParty.aspx";
+ public const string OPDefaultPage = "OPDefault.aspx";
+ public static Uri ReturnTo {
+ get { return TestSupport.GetFullUrl(TestSupport.ConsumerPage); }
+ }
+ public static Realm Realm {
+ get { return new Realm(TestSupport.GetFullUrl(TestSupport.ConsumerPage).AbsoluteUri); }
+ }
+ public readonly static ILog Logger = LogManager.GetLogger("DotNetOpenId.Test");
+
+ public enum Scenarios {
+ // Authentication test scenarios
+ AutoApproval,
+ AutoApprovalAddFragment,
+ ApproveOnSetup,
+ AlwaysDeny,
+
+ // Extension test scenarios
+ /// <summary>
+ /// Provides all required and requested fields.
+ /// </summary>
+ ExtensionFullCooperation,
+ /// <summary>
+ /// Provides only those fields marked as required.
+ /// </summary>
+ ExtensionPartialCooperation,
+ }
+
+ ////internal static UriIdentifier GetOPIdentityUrl(Scenarios scenario, bool useSsl) {
+ //// var args = new Dictionary<string, string> {
+ //// { "user", scenario.ToString() },
+ ////};
+ //// return new UriIdentifier(GetFullUrl("/" + OPDefaultPage, args, useSsl));
+ ////}
+ internal static UriIdentifier GetIdentityUrl(Scenarios scenario, ProtocolVersion providerVersion) {
+ return GetIdentityUrl(scenario, providerVersion, false);
+ }
+ internal static UriIdentifier GetIdentityUrl(Scenarios scenario, ProtocolVersion providerVersion, bool useSsl) {
+ return new UriIdentifier(GetFullUrl("/" + identityPage, new Dictionary<string, string> {
+ { "user", scenario.ToString() },
+ { "version", providerVersion.ToString() },
+ }, useSsl));
+ }
+ ////internal static UriIdentifier GetDirectedIdentityUrl(Scenarios scenario, ProtocolVersion providerVersion) {
+ //// return GetDirectedIdentityUrl(scenario, providerVersion, false);
+ ////}
+ ////internal static UriIdentifier GetDirectedIdentityUrl(Scenarios scenario, ProtocolVersion providerVersion, bool useSsl) {
+ //// return new UriIdentifier(GetFullUrl("/" + directedIdentityPage, new Dictionary<string, string> {
+ //// { "user", scenario.ToString() },
+ //// { "version", providerVersion.ToString() },
+ ////}, useSsl));
+ ////}
+ public static Identifier GetDelegateUrl(Scenarios scenario) {
+ return GetDelegateUrl(scenario, false);
+ }
+ public static Identifier GetDelegateUrl(Scenarios scenario, bool useSsl) {
+ return new UriIdentifier(GetFullUrl("/" + scenario, null, useSsl));
+ }
+ internal static MockIdentifier GetMockIdentifier(Scenarios scenario, MockHttpRequest mockRequest, ProtocolVersion providerVersion) {
+ return GetMockIdentifier(scenario, mockRequest, providerVersion, false);
+ }
+ internal static MockIdentifier GetMockIdentifier(Scenarios scenario, MockHttpRequest mockRequest, ProtocolVersion providerVersion, bool useSsl) {
+ ServiceEndpoint se = GetServiceEndpoint(scenario, providerVersion, 10, useSsl);
+ return new MockIdentifier(GetIdentityUrl(scenario, providerVersion, useSsl), mockRequest, new ServiceEndpoint[] { se });
+ }
+ internal static ServiceEndpoint GetServiceEndpoint(Scenarios scenario, ProtocolVersion providerVersion, int servicePriority, bool useSsl) {
+ return ServiceEndpoint.CreateForClaimedIdentifier(
+ GetIdentityUrl(scenario, providerVersion, useSsl),
+ GetDelegateUrl(scenario, useSsl),
+ GetFullUrl("/" + ProviderPage, null, useSsl),
+ new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI },
+ servicePriority,
+ 10);
+ }
+ ////internal static MockIdentifier GetMockOPIdentifier(Scenarios scenario, UriIdentifier expectedClaimedId) {
+ //// return GetMockOPIdentifier(scenario, expectedClaimedId, false, false);
+ ////}
+ ////internal static MockIdentifier GetMockOPIdentifier(Scenarios scenario, UriIdentifier expectedClaimedId, bool useSslOpIdentifier, bool useSslProviderEndpoint) {
+ //// var fields = new Dictionary<string, string> {
+ //// { "user", scenario.ToString() },
+ ////};
+ //// Uri opEndpoint = GetFullUrl(DirectedProviderEndpoint, fields, useSslProviderEndpoint);
+ //// Uri opIdentifier = GetOPIdentityUrl(scenario, useSslOpIdentifier);
+ //// ServiceEndpoint se = ServiceEndpoint.CreateForProviderIdentifier(
+ //// opIdentifier,
+ //// opEndpoint,
+ //// new string[] { Protocol.V20.OPIdentifierServiceTypeURI },
+ //// 10,
+ //// 10);
+
+ //// // Register the Claimed Identifier that directed identity will choose so that RP
+ //// // discovery on that identifier can be mocked up.
+ //// MockHttpRequest.RegisterMockXrdsResponse(expectedClaimedId, se);
+
+ //// return new MockIdentifier(opIdentifier, new ServiceEndpoint[] { se });
+ ////}
+ public static Uri GetFullUrl(string url) {
+ return GetFullUrl(url, null, false);
+ }
+ public static Uri GetFullUrl(string url, string key, object value) {
+ return GetFullUrl(url, new Dictionary<string, string> {
+ { key, value.ToString() },
+ }, false);
+ }
+ public static Uri GetFullUrl(string url, IDictionary<string, string> args, bool useSsl) {
+ Uri defaultUriBase = new Uri(useSsl ? "https://localhost/" : "http://localhost/");
+ Uri baseUri = UITestSupport.Host != null ? UITestSupport.Host.BaseUri : defaultUriBase;
+ UriBuilder builder = new UriBuilder(new Uri(baseUri, url));
+ MessagingUtilities.AppendQueryArgs(builder, args);
+ return builder.Uri;
+ }
+
+ /// <summary>
+ /// Returns the content of a given embedded resource.
+ /// </summary>
+ /// <param name="path">The path of the file as it appears within the project,
+ /// where the leading / marks the root directory of the project.</param>
+ internal static string LoadEmbeddedFile(string path) {
+ if (!path.StartsWith("/")) path = "/" + path;
+ path = "DotNetOpenAuth.Test.OpenId" + path.Replace('/', '.');
+ Stream resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
+ if (resource == null) throw new ArgumentException();
+ using (StreamReader sr = new StreamReader(resource)) {
+ return sr.ReadToEnd();
+ }
+ }
+
+ ////internal static IRelyingPartyApplicationStore RelyingPartyStore;
+ ////internal static IProviderAssociationStore ProviderStore;
+ /////// <summary>
+ /////// Generates a new, stateful <see cref="OpenIdRelyingParty"/> whose direct messages
+ /////// will be automatically handled by an internal <see cref="OpenIdProvider"/>
+ /////// that uses the shared <see cref="ProviderStore"/>.
+ /////// </summary>
+ ////internal static OpenIdRelyingParty CreateRelyingParty(NameValueCollection fields) {
+ //// return CreateRelyingParty(RelyingPartyStore, null, fields);
+ ////}
+ ////internal static OpenIdRelyingParty CreateRelyingParty(IRelyingPartyApplicationStore store, NameValueCollection fields) {
+ //// return CreateRelyingParty(store, null, fields);
+ ////}
+ /////// <summary>
+ /////// Generates a new <see cref="OpenIdRelyingParty"/> whose direct messages
+ /////// will be automatically handled by an internal <see cref="OpenIdProvider"/>
+ /////// that uses the shared <see cref="ProviderStore"/>.
+ /////// </summary>
+ ////internal static OpenIdRelyingParty CreateRelyingParty(IRelyingPartyApplicationStore store, Uri requestUrl, NameValueCollection fields) {
+ //// var rp = new OpenIdRelyingParty(store, requestUrl ?? GetFullUrl(ConsumerPage), fields ?? new NameValueCollection());
+ //// if (fields == null || fields.Count == 0) {
+ //// Assert.IsNull(rp.Response);
+ //// }
+ //// rp.DirectMessageChannel = new DirectMessageTestRedirector(ProviderStore);
+ //// return rp;
+ ////}
+ ////internal static DotNetOpenId.RelyingParty.IAuthenticationRequest CreateRelyingPartyRequest(bool stateless, Scenarios scenario, ProtocolVersion version, bool useSsl) {
+ //// // Publish RP discovery information
+ //// MockHttpRequest.RegisterMockRPDiscovery();
+
+ //// var rp = TestSupport.CreateRelyingParty(stateless ? null : RelyingPartyStore, null);
+ //// var rpReq = rp.CreateRequest(TestSupport.GetMockIdentifier(scenario, version, useSsl), Realm, ReturnTo);
+
+ //// // Sidetrack: verify URLs and other default properties
+ //// {
+ //// Assert.AreEqual(AuthenticationRequestMode.Setup, rpReq.Mode);
+ //// Assert.AreEqual(Realm, rpReq.Realm);
+ //// Assert.AreEqual(ReturnTo, rpReq.ReturnToUrl);
+ //// }
+
+ //// return rpReq;
+ ////}
+ /////// <summary>
+ /////// Generates a new <see cref="OpenIdRelyingParty"/> ready to process a
+ /////// response from an <see cref="OpenIdProvider"/>.
+ /////// </summary>
+ ////internal static IAuthenticationResponse CreateRelyingPartyResponse(IRelyingPartyApplicationStore store, IResponse providerResponse) {
+ //// return CreateRelyingPartyResponse(store, providerResponse, false);
+ ////}
+ ////internal static IAuthenticationResponse CreateRelyingPartyResponse(IRelyingPartyApplicationStore store, IResponse providerResponse, bool requireSsl) {
+ //// if (providerResponse == null) throw new ArgumentNullException("providerResponse");
+
+ //// var opAuthWebResponse = (Response)providerResponse;
+ //// var opAuthResponse = (EncodableResponse)opAuthWebResponse.EncodableMessage;
+ //// var rp = CreateRelyingParty(store, opAuthResponse.RedirectUrl,
+ //// opAuthResponse.EncodedFields.ToNameValueCollection());
+ //// rp.Settings.RequireSsl = requireSsl;
+ //// // Get the response now, before trying the replay attack. The Response
+ //// // property is lazily-evaluated, so the replay attack can be evaluated first
+ //// // and pass, while this one that SUPPOSED to pass fails, if we don't force it now.
+ //// var response = rp.Response;
+
+ //// // Side-track to test for replay attack while we're at it.
+ //// // This simulates a network sniffing user who caught the
+ //// // authenticating query en route to either the user agent or
+ //// // the consumer, and tries the same query to the consumer in an
+ //// // attempt to spoof the identity of the authenticating user.
+ //// try {
+ //// Logger.Info("Attempting replay attack...");
+ //// var replayRP = CreateRelyingParty(store, opAuthResponse.RedirectUrl,
+ //// opAuthResponse.EncodedFields.ToNameValueCollection());
+ //// replayRP.Settings.RequireSsl = requireSsl;
+ //// Assert.AreNotEqual(AuthenticationStatus.Authenticated, replayRP.Response.Status, "Replay attack succeeded!");
+ //// } catch (OpenIdException) { // nonce already used
+ //// // another way to pass
+ //// }
+
+ //// // Return the result of the initial response (not the replay attack one).
+ //// return response;
+ ////}
+ /////// <summary>
+ /////// Generates a new <see cref="OpenIdProvider"/> that uses the shared
+ /////// store in <see cref="ProviderStore"/>.
+ /////// </summary>
+ ////internal static OpenIdProvider CreateProvider(NameValueCollection fields) {
+ //// return CreateProvider(fields, false);
+ ////}
+ ////internal static OpenIdProvider CreateProvider(NameValueCollection fields, bool useSsl) {
+ //// Protocol protocol = fields != null ? Protocol.Detect(fields.ToDictionary()) : Protocol.V20;
+ //// Uri opEndpoint = GetFullUrl(ProviderPage, null, useSsl);
+ //// var provider = new OpenIdProvider(ProviderStore, opEndpoint, opEndpoint, fields ?? new NameValueCollection());
+ //// return provider;
+ ////}
+ ////internal static OpenIdProvider CreateProviderForRequest(DotNetOpenId.RelyingParty.IAuthenticationRequest request) {
+ //// IResponse relyingPartyAuthenticationRequest = request.RedirectingResponse;
+ //// var rpWebMessageToOP = (Response)relyingPartyAuthenticationRequest;
+ //// var rpMessageToOP = (IndirectMessageRequest)rpWebMessageToOP.EncodableMessage;
+ //// var opEndpoint = (ServiceEndpoint)request.Provider;
+ //// var provider = new OpenIdProvider(ProviderStore, opEndpoint.ProviderEndpoint,
+ //// opEndpoint.ProviderEndpoint, rpMessageToOP.EncodedFields.ToNameValueCollection());
+ //// return provider;
+ ////}
+ ////internal static IResponse CreateProviderResponseToRequest(
+ //// DotNetOpenId.RelyingParty.IAuthenticationRequest request,
+ //// Action<DotNetOpenId.Provider.IAuthenticationRequest> prepareProviderResponse) {
+ //// {
+ //// // Sidetrack: Verify the return_to and realm URLs
+ //// var consumerToProviderQuery = HttpUtility.ParseQueryString(request.RedirectingResponse.ExtractUrl().Query);
+ //// Protocol protocol = Protocol.Detect(consumerToProviderQuery.ToDictionary());
+ //// Assert.IsTrue(consumerToProviderQuery[protocol.openid.return_to].StartsWith(request.ReturnToUrl.AbsoluteUri, StringComparison.Ordinal));
+ //// Assert.AreEqual(request.Realm.ToString(), consumerToProviderQuery[protocol.openid.Realm]);
+ //// }
+
+ //// var op = TestSupport.CreateProviderForRequest(request);
+ //// var opReq = (DotNetOpenId.Provider.IAuthenticationRequest)op.Request;
+ //// prepareProviderResponse(opReq);
+ //// Assert.IsTrue(opReq.IsResponseReady);
+ //// return opReq.Response;
+ ////}
+ ////internal static IAuthenticationResponse CreateRelyingPartyResponseThroughProvider(
+ //// DotNetOpenId.RelyingParty.IAuthenticationRequest request,
+ //// Action<DotNetOpenId.Provider.IAuthenticationRequest> providerAction) {
+ //// var rpReq = (AuthenticationRequest)request;
+ //// var opResponse = CreateProviderResponseToRequest(rpReq, providerAction);
+ //// // Be careful to use whatever store the original RP was using.
+ //// var rp = CreateRelyingPartyResponse(rpReq.RelyingParty.Store, opResponse,
+ //// ((AuthenticationRequest)request).RelyingParty.Settings.RequireSsl);
+ //// Assert.IsNotNull(rp);
+ //// return rp;
+ ////}
+
+ ////[SetUp]
+ ////public void SetUp() {
+ //// log4net.Config.XmlConfigurator.Configure(Assembly.GetExecutingAssembly().GetManifestResourceStream("DotNetOpenId.Test.Logging.config"));
+
+ //// ResetStores();
+ ////}
+
+ ////[TearDown]
+ ////public void TearDown() {
+ //// log4net.LogManager.Shutdown();
+ ////}
+
+ ////internal static void ResetStores() {
+ //// RelyingPartyStore = new ApplicationMemoryStore();
+ //// ProviderStore = new ProviderMemoryStore();
+ ////}
+
+ ////internal static void SetAuthenticationFromScenario(Scenarios scenario, DotNetOpenId.Provider.IAuthenticationRequest request) {
+ //// Assert.IsTrue(request.IsReturnUrlDiscoverable);
+ //// switch (scenario) {
+ //// case TestSupport.Scenarios.ExtensionFullCooperation:
+ //// case TestSupport.Scenarios.ExtensionPartialCooperation:
+ //// case TestSupport.Scenarios.AutoApproval:
+ //// // immediately approve
+ //// request.IsAuthenticated = true;
+ //// break;
+ //// case TestSupport.Scenarios.AutoApprovalAddFragment:
+ //// request.SetClaimedIdentifierFragment("frag");
+ //// request.IsAuthenticated = true;
+ //// break;
+ //// case TestSupport.Scenarios.ApproveOnSetup:
+ //// request.IsAuthenticated = !request.Immediate;
+ //// break;
+ //// case TestSupport.Scenarios.AlwaysDeny:
+ //// request.IsAuthenticated = false;
+ //// break;
+ //// default:
+ //// throw new InvalidOperationException("Unrecognized scenario");
+ //// }
+ ////}
+
+ /////// <summary>
+ /////// Uses an RPs stored association to resign an altered message from a Provider,
+ /////// to simulate a Provider that deliberately sent a bad message in an attempt
+ /////// to thwart RP security.
+ /////// </summary>
+ ////internal static void Resign(NameValueCollection nvc, IRelyingPartyApplicationStore store) {
+ //// Debug.Assert(nvc != null);
+ //// Debug.Assert(store != null);
+ //// var dict = Util.NameValueCollectionToDictionary(nvc);
+ //// Protocol protocol = Protocol.Detect(dict);
+ //// Uri providerEndpoint = new Uri(nvc[protocol.openid.op_endpoint]);
+ //// string assoc_handle = nvc[protocol.openid.assoc_handle];
+ //// Association assoc = store.GetAssociation(providerEndpoint, assoc_handle);
+ //// Debug.Assert(assoc != null, "Association not found in RP's store. Maybe you're communicating with a hosted OP instead of the TestSupport one?");
+ //// IList<string> signed = nvc[protocol.openid.signed].Split(',');
+ //// var subsetDictionary = new Dictionary<string, string>();
+ //// foreach (string signedKey in signed) {
+ //// string keyName = protocol.openid.Prefix + signedKey;
+ //// subsetDictionary.Add(signedKey, dict[keyName]);
+ //// }
+ //// nvc[protocol.openid.sig] = Convert.ToBase64String(assoc.Sign(subsetDictionary, signed));
+ ////}
+
+ ////public static IAssociationStore<AssociationRelyingPartyType> ProviderStoreContext {
+ //// get {
+ //// return DotNetOpenId.Provider.OpenIdProvider.HttpApplicationStore;
+ //// }
+ ////}
+ }
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/OpenId/UI/UITestSupport.cs b/src/DotNetOpenAuth.Test/OpenId/UI/UITestSupport.cs
new file mode 100644
index 0000000..da18fa9
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/UI/UITestSupport.cs
@@ -0,0 +1,21 @@
+namespace DotNetOAuth.Test.OpenId.UI {
+ using DotNetOpenAuth.Test.Hosting;
+
+ ////[SetUpFixture]
+ public class UITestSupport {
+ internal static AspNetHost Host { get; private set; }
+
+ ////[SetUp]
+ ////public void SetUp() {
+ //// Host = AspNetHost.CreateHost(TestSupport.TestWebDirectory);
+ ////}
+
+ ////[TearDown]
+ ////public void TearDown() {
+ //// if (Host != null) {
+ //// Host.CloseHttp();
+ //// Host = null;
+ //// }
+ ////}
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
index e6e9149..da2c6cc 100644
--- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
@@ -1,13 +1,20 @@
-using System;
-using System.Linq;
-using System.Net;
-using System.Web;
-using DotNetOpenAuth.OpenId.RelyingParty;
-using DotNetOpenAuth.Test.Mocks;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using DotNetOpenAuth.OpenId;
+//-----------------------------------------------------------------------
+// <copyright file="UriIdentifierTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Test.OpenId {
+ using System;
+ using System.Linq;
+ using System.Net;
+ using System.Web;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Mocks;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.OpenId;
+using DotNetOpenAuth.Messaging;
+
[TestClass]
public class UriIdentifierTests : OpenIdTestBase {
string goodUri = "http://blog.nerdbank.net/";
@@ -16,13 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId {
[TestInitialize]
public override void SetUp() {
- if (!UntrustedWebRequest.WhitelistHosts.Contains("localhost"))
- UntrustedWebRequest.WhitelistHosts.Add("localhost");
- }
-
- [TestCleanup]
- public override void Cleanup() {
- Mocks.MockHttpRequest.Reset();
+ base.SetUp();
}
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
@@ -35,7 +36,7 @@ namespace DotNetOpenAuth.Test.OpenId {
new UriIdentifier((string)null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
public void CtorBlank() {
new UriIdentifier(string.Empty);
}
@@ -126,7 +127,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual(new UriIdentifier(goodUri), new UriIdentifier(goodUri + "#frag"));
Assert.AreNotEqual(new UriIdentifier(goodUri), new UriIdentifier(goodUri + "a"));
Assert.AreNotEqual(null, new UriIdentifier(goodUri));
- Assert.AreNotEqual(goodUri, new UriIdentifier(goodUri));
+ Assert.AreEqual(goodUri, new UriIdentifier(goodUri));
}
[TestMethod]
@@ -158,17 +159,19 @@ namespace DotNetOpenAuth.Test.OpenId {
} else {
throw new InvalidOperationException();
}
- MockHttpRequest.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType,
+ this.mockResponder.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType,
headers ?? new WebHeaderCollection(), TestSupport.LoadEmbeddedFile(url));
- ServiceEndpoint se = idToDiscover.Discover().FirstOrDefault();
+ ServiceEndpoint se = idToDiscover.Discover(this.requestHandler).FirstOrDefault();
Assert.IsNotNull(se, url + " failed to be discovered.");
Assert.AreSame(protocol, se.Protocol);
Assert.AreEqual(claimedId, se.ClaimedIdentifier);
Assert.AreEqual(expectedLocalId, se.ProviderLocalIdentifier);
Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Length);
Assert.IsTrue(Array.IndexOf(se.ProviderSupportedServiceTypeUris, protocol.ClaimedIdentifierServiceTypeURI) >= 0);
- Assert.AreEqual(expectSreg, se.IsExtensionSupported(new ClaimsRequest()));
+
+ // TODO: re-enable this line once extensions support is added back in.
+ ////Assert.AreEqual(expectSreg, se.IsExtensionSupported(new ClaimsRequest()));
}
void discoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId) {
discoverXrds(page, version, expectedLocalId, null);
@@ -189,10 +192,10 @@ namespace DotNetOpenAuth.Test.OpenId {
void failDiscover(string url) {
UriIdentifier userSuppliedId = TestSupport.GetFullUrl(url);
- Mocks.MockHttpRequest.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html",
+ this.mockResponder.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html",
TestSupport.LoadEmbeddedFile(url));
- Assert.AreEqual(0, userSuppliedId.Discover().Count()); // ... but that no endpoint info is discoverable
+ Assert.AreEqual(0, userSuppliedId.Discover(this.requestHandler).Count()); // ... but that no endpoint info is discoverable
}
void failDiscoverHtml(string scenario) {
failDiscover("/Discovery/htmldiscovery/" + scenario + ".html");
@@ -220,7 +223,7 @@ namespace DotNetOpenAuth.Test.OpenId {
}
[TestMethod]
public void XrdsDiscoveryFromHead() {
- Mocks.MockHttpRequest.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"),
+ this.mockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"),
"application/xrds+xml", TestSupport.LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
discoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null);
}
@@ -228,7 +231,7 @@ namespace DotNetOpenAuth.Test.OpenId {
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"),
+ this.mockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"),
"application/xrds+xml", TestSupport.LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
discoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, headers);
}
@@ -272,18 +275,17 @@ namespace DotNetOpenAuth.Test.OpenId {
[TestMethod]
public void DiscoveryWithRedirects() {
- MockHttpRequest.Reset();
- Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20);
+ Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, ProtocolVersion.V20);
// Add a couple of chained redirect pages that lead to the claimedId.
Uri userSuppliedUri = TestSupport.GetFullUrl("/someSecurePage", null, true);
Uri insecureMidpointUri = TestSupport.GetFullUrl("/insecureStop");
- MockHttpRequest.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- MockHttpRequest.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+ 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().Count());
+ Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.requestHandler).Count());
}
[TestMethod]
@@ -307,79 +309,78 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsFalse(secureId.IsDiscoverySecureEndToEnd);
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover().Count());
+ Assert.AreEqual(0, secureId.Discover(this.requestHandler).Count());
id = new UriIdentifier("http://www.yahoo.com");
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsFalse(secureId.IsDiscoverySecureEndToEnd);
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover().Count());
+ Assert.AreEqual(0, secureId.Discover(this.requestHandler).Count());
}
[TestMethod]
public void DiscoverRequireSslWithSecureRedirects() {
- MockHttpRequest.Reset();
- Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, true);
+ this.mockResponder.Reset();
+ Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, ProtocolVersion.V20, true);
// Add a couple of chained redirect pages that lead to the claimedId.
// All redirects should be secure.
Uri userSuppliedUri = TestSupport.GetFullUrl("/someSecurePage", null, true);
Uri secureMidpointUri = TestSupport.GetFullUrl("/secureStop", null, true);
- MockHttpRequest.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
- MockHttpRequest.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
+ this.mockResponder.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
+ this.mockResponder.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- Assert.AreEqual(1, userSuppliedIdentifier.Discover().Count());
+ Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.requestHandler).Count());
}
- [TestMethod, ExpectedException(typeof(OpenIdException))]
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
public void DiscoverRequireSslWithInsecureRedirect() {
- MockHttpRequest.Reset();
- Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, true);
+ Identifier claimedId = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, 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 = TestSupport.GetFullUrl("/someSecurePage", null, true);
Uri insecureMidpointUri = TestSupport.GetFullUrl("/insecureStop");
- MockHttpRequest.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- MockHttpRequest.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+ this.mockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
+ this.mockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- userSuppliedIdentifier.Discover();
+ userSuppliedIdentifier.Discover(this.requestHandler);
}
[TestMethod]
public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() {
- var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, false);
+ var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, ProtocolVersion.V20, false);
Uri secureClaimedUri = TestSupport.GetFullUrl("/secureId", null, true);
string html = string.Format("<html><head><meta http-equiv='X-XRDS-Location' content='{0}'/></head><body></body></html>",
insecureXrdsSource);
- MockHttpRequest.RegisterMockResponse(secureClaimedUri, "text/html", html);
+ this.mockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover().Count());
+ Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.requestHandler).Count());
}
[TestMethod]
public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() {
- var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, false);
+ var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, ProtocolVersion.V20, false);
Uri secureClaimedUri = TestSupport.GetFullUrl("/secureId", null, true);
string html = "<html><head></head><body></body></html>";
WebHeaderCollection headers = new WebHeaderCollection {
{ "X-XRDS-Location", insecureXrdsSource }
};
- MockHttpRequest.RegisterMockResponse(secureClaimedUri, secureClaimedUri, "text/html", headers, html);
+ this.mockResponder.RegisterMockResponse(secureClaimedUri, secureClaimedUri, "text/html", headers, html);
Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover().Count());
+ Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.requestHandler).Count());
}
[TestMethod]
public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() {
- var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, false);
+ var insecureXrdsSource = TestSupport.GetMockIdentifier(TestSupport.Scenarios.AutoApproval, this.mockResponder, ProtocolVersion.V20, false);
Uri secureClaimedUri = TestSupport.GetFullUrl("/secureId", null, true);
Identifier localIdForLinkTag = TestSupport.GetDelegateUrl(TestSupport.Scenarios.AlwaysDeny, true);
@@ -392,10 +393,10 @@ namespace DotNetOpenAuth.Test.OpenId {
HttpUtility.HtmlEncode(insecureXrdsSource),
HttpUtility.HtmlEncode(TestSupport.GetFullUrl("/" + TestSupport.ProviderPage, null, true).AbsoluteUri),
HttpUtility.HtmlEncode(localIdForLinkTag.ToString()));
- MockHttpRequest.RegisterMockResponse(secureClaimedUri, "text/html", html);
+ this.mockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
- Assert.AreEqual(localIdForLinkTag, userSuppliedIdentifier.Discover().Single().ProviderLocalIdentifier);
+ Assert.AreEqual(localIdForLinkTag, userSuppliedIdentifier.Discover(this.requestHandler).Single().ProviderLocalIdentifier);
}
[TestMethod]
@@ -403,8 +404,8 @@ namespace DotNetOpenAuth.Test.OpenId {
var insecureEndpoint = TestSupport.GetServiceEndpoint(TestSupport.Scenarios.AutoApproval, ProtocolVersion.V20, 10, false);
var secureEndpoint = TestSupport.GetServiceEndpoint(TestSupport.Scenarios.ApproveOnSetup, ProtocolVersion.V20, 20, true);
UriIdentifier secureClaimedId = new UriIdentifier(TestSupport.GetFullUrl("/claimedId", null, true), true);
- MockHttpRequest.RegisterMockXrdsResponse(secureClaimedId, new ServiceEndpoint[] { insecureEndpoint, secureEndpoint });
- Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, secureClaimedId.Discover().Single().ProviderLocalIdentifier);
+ this.mockResponder.RegisterMockXrdsResponse(secureClaimedId, new ServiceEndpoint[] { insecureEndpoint, secureEndpoint });
+ Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, secureClaimedId.Discover(this.requestHandler).Single().ProviderLocalIdentifier);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
index 1edc086..5f85f28 100644
--- a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
@@ -1,20 +1,21 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using DotNetOpenAuth.OpenId.RelyingParty;
-using DotNetOpenAuth.Test.Mocks;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using DotNetOpenAuth.OpenId;
+namespace DotNetOpenAuth.Test.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Mocks;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.Messaging;
-namespace DotNetOpenAuth.Test.OpenId {
[TestClass]
public class XriIdentifierTests : OpenIdTestBase {
string goodXri = "=Andrew*Arnott";
string badXri = "some\\wacky%^&*()non-XRI";
- [TestCleanup]
- public void TearDown() {
- MockHttpRequest.Reset();
+ [TestInitialize]
+ public override void SetUp() {
+ base.SetUp();
}
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
@@ -22,7 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId {
new XriIdentifier(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
public void CtorBlank() {
new XriIdentifier(string.Empty);
}
@@ -80,12 +81,11 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual(new XriIdentifier(goodXri), new XriIdentifier(goodXri));
Assert.AreNotEqual(new XriIdentifier(goodXri), new XriIdentifier(goodXri + "a"));
Assert.AreNotEqual(null, new XriIdentifier(goodXri));
- Assert.AreNotEqual(goodXri, new XriIdentifier(goodXri));
+ Assert.AreEqual(goodXri, new XriIdentifier(goodXri));
}
-#if DISCOVERY // TODO: Add discovery and then re-enable this code block
private ServiceEndpoint verifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
- ServiceEndpoint se = iname.Discover().FirstOrDefault();
+ 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);
@@ -95,7 +95,6 @@ namespace DotNetOpenAuth.Test.OpenId {
}
return se;
}
-#endif
[TestMethod]
public void Discover() {
@@ -134,7 +133,7 @@ namespace DotNetOpenAuth.Test.OpenId {
{ "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 },
};
- MockHttpRequest.RegisterMockXrdsResponses(mocks);
+ this.mockResponder.RegisterMockXrdsResponses(mocks);
string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
ServiceEndpoint se = verifyCanonicalId("=Arnott", expectedCanonicalId);
@@ -360,7 +359,7 @@ uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
</X509Data>
</KeyInfo>
</XRD>";
- MockHttpRequest.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ 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 },
@@ -376,7 +375,7 @@ uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
[TestMethod]
public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
- MockHttpRequest.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ 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>
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index d6ccb7b..9ee0b25 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -78,6 +78,7 @@
<Compile Include="Messaging\EmptyEnumerator.cs" />
<Compile Include="Messaging\EmptyList.cs" />
<Compile Include="Messaging\ErrorUtilities.cs" />
+ <Compile Include="Messaging\IDirectSslWebRequestHandler.cs" />
<Compile Include="Messaging\InternalErrorException.cs" />
<Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" />
<Compile Include="OAuth\ChannelElements\OAuthConsumerMessageFactory.cs" />
diff --git a/src/DotNetOpenAuth/Messaging/IDirectSslWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/IDirectSslWebRequestHandler.cs
new file mode 100644
index 0000000..084d6d2
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IDirectSslWebRequestHandler.cs
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="IDirectSslWebRequestHandler.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.IO;
+ using System.Net;
+
+ /// <summary>
+ /// A contract for <see cref="HttpWebRequest"/> handling,
+ /// with added support for SSL-only requests.
+ /// </summary>
+ public interface IDirectSslWebRequestHandler : IDirectWebRequestHandler {
+ /// <summary>
+ /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
+ /// </summary>
+ /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
+ /// <param name="requireSsl">if set to <c>true</c> all requests made with this instance must be completed using SSL.</param>
+ /// <returns>
+ /// The writer the caller should write out the entity data to.
+ /// </returns>
+ TextWriter GetRequestStream(HttpWebRequest request, bool requireSsl);
+
+ /// <summary>
+ /// Processes an <see cref="HttpWebRequest"/> and converts the
+ /// <see cref="HttpWebResponse"/> to a <see cref="DirectWebResponse"/> instance.
+ /// </summary>
+ /// <param name="request">The <see cref="HttpWebRequest"/> to handle.</param>
+ /// <param name="requireSsl">if set to <c>true</c> all requests made with this instance must be completed using SSL.</param>
+ /// <returns>An instance of <see cref="DirectWebResponse"/> describing the response.</returns>
+ DirectWebResponse GetResponse(HttpWebRequest request, bool requireSsl);
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
index bf2acfb..51513db 100644
--- a/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
+++ b/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
@@ -12,12 +12,17 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// A contract for <see cref="HttpWebRequest"/> handling.
/// </summary>
+ /// <remarks>
+ /// Implementations of this interface must be thread safe.
+ /// </remarks>
public interface IDirectWebRequestHandler {
/// <summary>
/// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
/// </summary>
/// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
- /// <returns>The writer the caller should write out the entity data to.</returns>
+ /// <returns>
+ /// The writer the caller should write out the entity data to.
+ /// </returns>
TextWriter GetRequestStream(HttpWebRequest request);
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs
index d173541..4cc8844 100644
--- a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs
+++ b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs
@@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Messaging {
/// If a particular host would be permitted but is in the blacklist, it is not allowed.
/// If a particular host would not be permitted but is in the whitelist, it is allowed.
/// </remarks>
- public class UntrustedWebRequestHandler : IDirectWebRequestHandler {
+ public class UntrustedWebRequestHandler : IDirectSslWebRequestHandler {
/// <summary>
/// Gets or sets the default cache policy to use for HTTP requests.
/// </summary>
@@ -63,17 +63,9 @@ namespace DotNetOpenAuth.Messaging {
private int maximumRedirections = Configuration.MaximumRedirections;
/// <summary>
- /// Backing store for the <see cref="RequireSsl"/> property.
- /// </summary>
- private readonly bool requireSsl;
-
- /// <summary>
/// Initializes a new instance of the <see cref="UntrustedWebRequestHandler"/> class.
/// </summary>
- /// <param name="requireSsl">if set to <c>true</c> all requests made with this instance must be completed using SSL.</param>
- public UntrustedWebRequestHandler(bool requireSsl) {
- this.requireSsl = requireSsl;
-
+ public UntrustedWebRequestHandler() {
this.ReadWriteTimeout = Configuration.ReadWriteTimeout;
this.Timeout = Configuration.Timeout;
#if LONGTIMEOUT
@@ -83,18 +75,6 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Gets a value indicating whether all requests (and redirects) will be required
- /// to use SSL encryption for the request to be completed successfully.
- /// </summary>
- /// <remarks>
- /// Many policies in this class can be configured after the class is instantiated.
- /// But requiring SSL is an immutable setting and can only be set in the constructor.
- /// </remarks>
- public bool RequireSsl {
- get { return this.requireSsl; }
- }
-
- /// <summary>
/// Gets or sets the total number of redirections to allow on any one request.
/// Default is 10.
/// </summary>
@@ -144,18 +124,19 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
public ICollection<Regex> BlacklistHostsRegex { get { return blacklistHostsRegex; } }
- #region IWebRequestHandler Members
+ #region IDirectUntrustedWebRequestHandler Members
/// <summary>
/// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
/// </summary>
/// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
+ /// <param name="requireSsl">if set to <c>true</c> all requests made with this instance must be completed using SSL.</param>
/// <returns>
/// The writer the caller should write out the entity data to.
/// </returns>
- public TextWriter GetRequestStream(HttpWebRequest request) {
+ public TextWriter GetRequestStream(HttpWebRequest request, bool requireSsl) {
ErrorUtilities.VerifyArgumentNotNull(request, "request");
- this.EnsureAllowableRequestUri(request.RequestUri);
+ this.EnsureAllowableRequestUri(request.RequestUri, requireSsl);
this.PrepareRequest(request);
@@ -172,9 +153,18 @@ namespace DotNetOpenAuth.Messaging {
}
}
- public DirectWebResponse GetResponse(HttpWebRequest request) {
+ /// <summary>
+ /// Processes an <see cref="HttpWebRequest"/> and converts the
+ /// <see cref="HttpWebResponse"/> to a <see cref="DirectWebResponse"/> instance.
+ /// </summary>
+ /// <param name="request">The <see cref="HttpWebRequest"/> to handle.</param>
+ /// <param name="requireSsl">if set to <c>true</c> all requests made with this instance must be completed using SSL.</param>
+ /// <returns>
+ /// An instance of <see cref="DirectWebResponse"/> describing the response.
+ /// </returns>
+ public DirectWebResponse GetResponse(HttpWebRequest request, bool requireSsl) {
ErrorUtilities.VerifyArgumentNotNull(request, "request");
- this.EnsureAllowableRequestUri(request.RequestUri);
+ this.EnsureAllowableRequestUri(request.RequestUri, requireSsl);
// This request MAY have already been prepared by GetRequestStream, but
// we have no guarantee, so do it just to be safe.
@@ -186,7 +176,32 @@ namespace DotNetOpenAuth.Messaging {
#endregion
- internal DirectWebResponse RequestWithManagedRedirects(HttpWebRequest request) {
+ #region IDirectWebRequestHandler Members
+
+ /// <summary>
+ /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity.
+ /// </summary>
+ /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param>
+ /// <returns>
+ /// The writer the caller should write out the entity data to.
+ /// </returns>
+ TextWriter IDirectWebRequestHandler.GetRequestStream(HttpWebRequest request) {
+ return this.GetRequestStream(request, false);
+ }
+
+ /// <summary>
+ /// Processes an <see cref="HttpWebRequest"/> and converts the
+ /// <see cref="HttpWebResponse"/> to a <see cref="DirectWebResponse"/> instance.
+ /// </summary>
+ /// <param name="request">The <see cref="HttpWebRequest"/> to handle.</param>
+ /// <returns>An instance of <see cref="DirectWebResponse"/> describing the response.</returns>
+ DirectWebResponse IDirectWebRequestHandler.GetResponse(HttpWebRequest request) {
+ return this.GetResponse(request, false);
+ }
+
+ #endregion
+
+ internal DirectWebResponse RequestWithManagedRedirects(HttpWebRequest request, bool requireSsl) {
ErrorUtilities.VerifyArgumentNotNull(request, "request");
// Since we may require SSL for every redirect, we handle each redirect manually
@@ -196,7 +211,7 @@ namespace DotNetOpenAuth.Messaging {
Uri originalRequestUri = request.RequestUri;
int i;
for (i = 0; i < MaximumRedirections; i++) {
- DirectWebResponse response = this.RequestCore(request, null, originalRequestUri);
+ DirectWebResponse response = this.RequestCore(request, null, originalRequestUri, requireSsl);
if (response.Status == HttpStatusCode.MovedPermanently ||
response.Status == HttpStatusCode.Redirect ||
response.Status == HttpStatusCode.RedirectMethod ||
@@ -281,9 +296,10 @@ namespace DotNetOpenAuth.Messaging {
/// Verify that the request qualifies under our security policies
/// </summary>
/// <param name="requestUri">The request URI.</param>
- private void EnsureAllowableRequestUri(Uri requestUri) {
+ private void EnsureAllowableRequestUri(Uri requestUri, bool requireSsl) {
ErrorUtilities.VerifyArgument(this.isUriAllowable(requestUri), MessagingStrings.UnsafeWebRequestDetected, requestUri);
- ErrorUtilities.VerifyProtocol(!this.RequireSsl || String.Equals(requestUri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase), MessagingStrings.InsecureWebRequestWithSslRequired, requestUri);
+
+ ErrorUtilities.VerifyProtocol(!requireSsl || String.Equals(requestUri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase), MessagingStrings.InsecureWebRequestWithSslRequired, requestUri);
}
private bool isUriAllowable(Uri uri) {
@@ -359,10 +375,10 @@ namespace DotNetOpenAuth.Messaging {
return request;
}
- private DirectWebResponse RequestCore(HttpWebRequest request, Stream postEntity, Uri originalRequestUri) {
+ private DirectWebResponse RequestCore(HttpWebRequest request, Stream postEntity, Uri originalRequestUri, bool requireSsl) {
ErrorUtilities.VerifyArgumentNotNull(request, "request");
ErrorUtilities.VerifyArgumentNotNull(originalRequestUri, "originalRequestUri");
- EnsureAllowableRequestUri(request.RequestUri);
+ EnsureAllowableRequestUri(request.RequestUri, requireSsl);
int postEntityLength = 0;
try {
@@ -391,7 +407,7 @@ namespace DotNetOpenAuth.Messaging {
request.ServicePoint.Expect100Continue = false; // TODO: investigate that CAS may throw here, and we can use request.Expect instead.
postEntity.Seek(-postEntityLength, SeekOrigin.Current);
request = CloneRequestWithNewUrl(request, request.RequestUri);
- return RequestCore(request, postEntity, originalRequestUri);
+ return RequestCore(request, postEntity, originalRequestUri, requireSsl);
}
}
return new DirectWebResponse(originalRequestUri, response, MaximumBytesToRead);
diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs
index 26108af..de20e6e 100644
--- a/src/DotNetOpenAuth/OpenId/Identifier.cs
+++ b/src/DotNetOpenAuth/OpenId/Identifier.cs
@@ -127,10 +127,11 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// Performs discovery on the Identifier.
/// </summary>
+ /// <param name="requestHandler">The web request handler to use for discovery.</param>
/// <returns>
/// An initialized structure containing the discovered provider endpoint information.
/// </returns>
- internal abstract IEnumerable<ServiceEndpoint> Discover();
+ internal abstract IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler);
/// <summary>
/// Tests equality between two <see cref="Identifier"/>s.
diff --git a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
index b563324..126a59c 100644
--- a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Collections.Generic;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.RelyingParty;
+ using System.Linq;
/// <summary>
/// Wraps an existing Identifier and prevents it from performing discovery.
@@ -30,8 +31,8 @@ namespace DotNetOpenAuth.OpenId {
this.wrappedIdentifier = wrappedIdentifier;
}
- internal override IEnumerable<ServiceEndpoint> Discover() {
- return new ServiceEndpoint[0];
+ internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) {
+ return Enumerable.Empty<ServiceEndpoint>();
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs
index 0bdaa33..5b1b10a 100644
--- a/src/DotNetOpenAuth/OpenId/Realm.cs
+++ b/src/DotNetOpenAuth/OpenId/Realm.cs
@@ -358,9 +358,9 @@ namespace DotNetOpenAuth.OpenId {
/// 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<RelyingPartyEndpointDescription> Discover(bool allowRedirects) {
+ internal IEnumerable<RelyingPartyEndpointDescription> Discover(IDirectSslWebRequestHandler requestHandler, bool allowRedirects) {
// Attempt YADIS discovery
- DiscoveryResult yadisResult = Yadis.Discover(UriWithWildcardChangedToWww, false);
+ DiscoveryResult yadisResult = Yadis.Discover(requestHandler, UriWithWildcardChangedToWww, false);
if (yadisResult != null) {
// Detect disallowed redirects, since realm discovery never allows them for security.
ErrorUtilities.VerifyProtocol(allowRedirects || yadisResult.NormalizedUri == yadisResult.RequestUri, OpenIdStrings.RealmCausedRedirectUponDiscovery, yadisResult.RequestUri);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index e00828a..2f0fb16 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -21,6 +21,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private RelyingPartySecuritySettings securitySettings;
/// <summary>
+ /// The untrusted web request handler we use (and share) by default across all RP instances.
+ /// </summary>
+ private static IDirectSslWebRequestHandler DefaultUntrustedWebRequestHandler = new UntrustedWebRequestHandler();
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingParty"/> class.
/// </summary>
/// <param name="associationStore">The association store. If null, the relying party will always operate in "dumb mode".</param>
@@ -30,6 +35,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.Channel = new OpenIdChannel();
this.AssociationStore = associationStore;
this.SecuritySettings = RelyingPartySection.Configuration.SecuritySettings.CreateSecuritySettings();
+ this.WebRequestHandler = DefaultUntrustedWebRequestHandler;
}
/// <summary>
@@ -60,6 +66,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
internal IAssociationStore<Uri> AssociationStore { get; private set; }
/// <summary>
+ /// Gets the web request handler to use for discovery and the part of
+ /// authentication where direct messages are sent to an untrusted remote party.
+ /// </summary>
+ internal IDirectSslWebRequestHandler WebRequestHandler { get; private set; }
+
+ /// <summary>
/// Gets an association between this Relying Party and a given Provider.
/// A new association is created if necessary and possible.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
index 1618c95..6885fa5 100644
--- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
@@ -252,10 +252,10 @@ namespace DotNetOpenAuth.OpenId {
providerEndpoint, typeURIs, (int?)null, (int?)null);
}
- internal override IEnumerable<ServiceEndpoint> Discover() {
+ internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) {
List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>();
// Attempt YADIS discovery
- DiscoveryResult yadisResult = Yadis.Discover(this, IsDiscoverySecureEndToEnd);
+ DiscoveryResult yadisResult = Yadis.Discover(requestHandler, this, IsDiscoverySecureEndToEnd);
if (yadisResult != null) {
if (yadisResult.IsXrds) {
XrdsDocument xrds = new XrdsDocument(yadisResult.ResponseText);
diff --git a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
index 13c8cdf..a6a7fe8 100644
--- a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
@@ -149,23 +149,23 @@ namespace DotNetOpenAuth.OpenId {
|| xri.StartsWith(XriScheme, StringComparison.OrdinalIgnoreCase);
}
- private XrdsDocument downloadXrds() {
- var xrdsResponse = Yadis.Request(this.XrdsUrl, this.IsDiscoverySecureEndToEnd);
+ private XrdsDocument downloadXrds(IDirectSslWebRequestHandler requestHandler) {
+ var xrdsResponse = Yadis.Request(requestHandler, this.XrdsUrl, this.IsDiscoverySecureEndToEnd);
XrdsDocument doc = new XrdsDocument(XmlReader.Create(xrdsResponse.ResponseStream));
ErrorUtilities.VerifyProtocol(doc.IsXrdResolutionSuccessful, OpenIdStrings.XriResolutionFailed);
return doc;
}
- internal override IEnumerable<ServiceEndpoint> Discover() {
- return downloadXrds().CreateServiceEndpoints(this);
+ internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) {
+ return downloadXrds(requestHandler).CreateServiceEndpoints(this);
}
/// <summary>
/// Performs discovery on THIS identifier, but generates <see cref="ServiceEndpoint"/>
/// instances that treat another given identifier as the user-supplied identifier.
/// </summary>
- internal IEnumerable<ServiceEndpoint> Discover(XriIdentifier userSuppliedIdentifier) {
- return downloadXrds().CreateServiceEndpoints(userSuppliedIdentifier);
+ internal IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler, XriIdentifier userSuppliedIdentifier) {
+ return downloadXrds(requestHandler).CreateServiceEndpoints(userSuppliedIdentifier);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Yadis/Yadis.cs b/src/DotNetOpenAuth/Yadis/Yadis.cs
index 7765575..1bbbc73 100644
--- a/src/DotNetOpenAuth/Yadis/Yadis.cs
+++ b/src/DotNetOpenAuth/Yadis/Yadis.cs
@@ -19,15 +19,12 @@ namespace DotNetOpenAuth.Yadis {
internal class Yadis {
internal const string HeaderName = "X-XRDS-Location";
- private static readonly IDirectWebRequestHandler discoveryRequestHandlerSsl = new UntrustedWebRequestHandler(true);
- private static readonly IDirectWebRequestHandler discoveryRequestHandler = new UntrustedWebRequestHandler(false);
-
/// <summary>
/// Gets or sets the cache that can be used for HTTP requests made during identifier discovery.
/// </summary>
internal readonly static RequestCachePolicy IdentifierDiscoveryCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.CacheIfAvailable);
- internal static DirectWebResponse Request(Uri uri, bool requireSsl, params string[] acceptTypes) {
+ internal static DirectWebResponse Request(IDirectSslWebRequestHandler requestHandler, Uri uri, bool requireSsl, params string[] acceptTypes) {
ErrorUtilities.VerifyArgumentNotNull(uri, "uri");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
@@ -36,8 +33,7 @@ namespace DotNetOpenAuth.Yadis {
request.Accept = string.Join(",", acceptTypes);
}
- IDirectWebRequestHandler handler = requireSsl ? discoveryRequestHandlerSsl : discoveryRequestHandler;
- return handler.GetResponse(request);
+ return requestHandler.GetResponse(request, requireSsl);
}
/// <summary>
@@ -51,14 +47,14 @@ namespace DotNetOpenAuth.Yadis {
/// or if <paramref name="requireSsl"/> is true but part of discovery
/// is not protected by SSL.
/// </returns>
- public static DiscoveryResult Discover(UriIdentifier uri, bool requireSsl) {
+ public static DiscoveryResult Discover(IDirectSslWebRequestHandler requestHandler, UriIdentifier uri, bool requireSsl) {
DirectWebResponse response;
try {
if (requireSsl && !string.Equals(uri.Uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) {
Logger.WarnFormat("Discovery on insecure identifier '{0}' aborted.", uri);
return null;
}
- response = Request(uri, requireSsl, ContentTypes.Html, ContentTypes.XHtml, ContentTypes.Xrds);
+ response = Request(requestHandler, uri, requireSsl, ContentTypes.Html, ContentTypes.XHtml, ContentTypes.Xrds);
if (response.Status != System.Net.HttpStatusCode.OK) {
return null;
}
@@ -87,7 +83,7 @@ namespace DotNetOpenAuth.Yadis {
}
if (url != null) {
if (!requireSsl || string.Equals(url.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) {
- response2 = Request(url, requireSsl);
+ response2 = Request(requestHandler, url, requireSsl);
if (response2.Status != System.Net.HttpStatusCode.OK) {
return null;
}