summaryrefslogtreecommitdiffstats
path: root/src/DotNetOAuth.Test/OAuth/ChannelElements
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-11-03 16:02:57 -0800
committerAndrew <andrewarnott@gmail.com>2008-11-03 16:02:57 -0800
commitaa1f55f58a561ff64dc268977d0d7c9decb92bbe (patch)
treefd685f00353d26493b40df7eaeac78745e27d1b8 /src/DotNetOAuth.Test/OAuth/ChannelElements
parentf1794fc8779ae39ac3d5bc6e8b811523e62ca482 (diff)
downloadDotNetOpenAuth-aa1f55f58a561ff64dc268977d0d7c9decb92bbe.zip
DotNetOpenAuth-aa1f55f58a561ff64dc268977d0d7c9decb92bbe.tar.gz
DotNetOpenAuth-aa1f55f58a561ff64dc268977d0d7c9decb92bbe.tar.bz2
Moved all the OAuth classes into its own namespace in preparation to receiving DotNetOpenId merge.
Diffstat (limited to 'src/DotNetOAuth.Test/OAuth/ChannelElements')
-rw-r--r--src/DotNetOAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs22
-rw-r--r--src/DotNetOAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs293
-rw-r--r--src/DotNetOAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs78
-rw-r--r--src/DotNetOAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs40
4 files changed, 433 insertions, 0 deletions
diff --git a/src/DotNetOAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs b/src/DotNetOAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs
new file mode 100644
index 0000000..d98e6be
--- /dev/null
+++ b/src/DotNetOAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------
+// <copyright file="HmacSha1SigningBindingElementTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOAuth.Test.OAuth.ChannelElements {
+ using DotNetOAuth.OAuth.ChannelElements;
+ using DotNetOAuth.OAuth.Messages;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class HmacSha1SigningBindingElementTests : MessagingTestBase {
+ [TestMethod]
+ public void SignatureTest() {
+ UnauthorizedTokenRequest message = SigningBindingElementBaseTests.CreateTestRequestTokenMessage();
+
+ HmacSha1SigningBindingElement_Accessor hmac = new HmacSha1SigningBindingElement_Accessor();
+ Assert.AreEqual("kR0LhH8UqylaLfR/esXVVlP4sQI=", hmac.GetSignature(message));
+ }
+ }
+}
diff --git a/src/DotNetOAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
new file mode 100644
index 0000000..6a58bfa
--- /dev/null
+++ b/src/DotNetOAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -0,0 +1,293 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthChannelTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOAuth.Test.OAuth.ChannelElements {
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Specialized;
+ using System.IO;
+ using System.Net;
+ using System.Text;
+ using System.Web;
+ using System.Xml;
+ using DotNetOAuth.Messaging;
+ using DotNetOAuth.Messaging.Bindings;
+ using DotNetOAuth.OAuth.ChannelElements;
+ using DotNetOAuth.Test.Mocks;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class OAuthChannelTests : TestBase {
+ private OAuthChannel channel;
+ private TestWebRequestHandler webRequestHandler;
+ private SigningBindingElementBase signingElement;
+ private INonceStore nonceStore;
+
+ [TestInitialize]
+ public override void SetUp() {
+ base.SetUp();
+
+ this.webRequestHandler = new TestWebRequestHandler();
+ this.signingElement = new RsaSha1SigningBindingElement();
+ this.nonceStore = new NonceMemoryStore(StandardExpirationBindingElement.DefaultMaximumMessageAge);
+ this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), new TestMessageTypeProvider(), this.webRequestHandler);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void CtorNullHandler() {
+ new OAuthChannel(new RsaSha1SigningBindingElement(), this.nonceStore, new InMemoryTokenManager(), new TestMessageTypeProvider(), null);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void CtorNullSigner() {
+ new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), new TestMessageTypeProvider(), this.webRequestHandler);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void CtorNullStore() {
+ new OAuthChannel(new RsaSha1SigningBindingElement(), null, new InMemoryTokenManager(), new TestMessageTypeProvider(), this.webRequestHandler);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void CtorNullTokenManager() {
+ new OAuthChannel(new RsaSha1SigningBindingElement(), this.nonceStore, null, new TestMessageTypeProvider(), this.webRequestHandler);
+ }
+
+ [TestMethod]
+ public void CtorSimpleConsumer() {
+ new OAuthChannel(new RsaSha1SigningBindingElement(), this.nonceStore, new InMemoryTokenManager(), true);
+ }
+
+ [TestMethod]
+ public void CtorSimpleServiceProvider() {
+ new OAuthChannel(new RsaSha1SigningBindingElement(), this.nonceStore, new InMemoryTokenManager(), false);
+ }
+
+ [TestMethod]
+ public void ReadFromRequestAuthorization() {
+ this.ParameterizedReceiveTest(HttpDeliveryMethods.AuthorizationHeaderRequest);
+ }
+
+ [TestMethod]
+ public void ReadFromRequestForm() {
+ this.ParameterizedReceiveTest(HttpDeliveryMethods.PostRequest);
+ }
+
+ [TestMethod]
+ public void ReadFromRequestQueryString() {
+ this.ParameterizedReceiveTest(HttpDeliveryMethods.GetRequest);
+ }
+
+ [TestMethod]
+ public void SendDirectMessageResponse() {
+ IProtocolMessage message = new TestMessage {
+ Age = 15,
+ Name = "Andrew",
+ Location = new Uri("http://hostb/pathB"),
+ };
+
+ Response response = this.channel.Send(message);
+ Assert.AreSame(message, response.OriginalMessage);
+ Assert.AreEqual(HttpStatusCode.OK, response.Status);
+ Assert.AreEqual(0, response.Headers.Count);
+
+ NameValueCollection body = HttpUtility.ParseQueryString(response.Body);
+ Assert.AreEqual("15", body["age"]);
+ Assert.AreEqual("Andrew", body["Name"]);
+ Assert.AreEqual("http://hostb/pathB", body["Location"]);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void ReadFromResponseNull() {
+ Channel_Accessor accessor = Channel_Accessor.AttachShadow(this.channel);
+ accessor.ReadFromResponse(null);
+ }
+
+ [TestMethod]
+ public void ReadFromResponse() {
+ var fields = new Dictionary<string, string> {
+ { "age", "15" },
+ { "Name", "Andrew" },
+ { "Location", "http://hostb/pathB" },
+ { "Timestamp", XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.Utc) },
+ };
+
+ MemoryStream ms = new MemoryStream();
+ StreamWriter writer = new StreamWriter(ms);
+ writer.Write(MessagingUtilities.CreateQueryString(fields));
+ writer.Flush();
+ ms.Seek(0, SeekOrigin.Begin);
+ Channel_Accessor channelAccessor = Channel_Accessor.AttachShadow(this.channel);
+ IProtocolMessage message = channelAccessor.ReadFromResponse(ms);
+ Assert.IsNotNull(message);
+ Assert.IsInstanceOfType(message, typeof(TestMessage));
+ TestMessage testMessage = (TestMessage)message;
+ Assert.AreEqual(15, testMessage.Age);
+ Assert.AreEqual("Andrew", testMessage.Name);
+ Assert.AreEqual("http://hostb/pathB", testMessage.Location.AbsoluteUri);
+ Assert.IsNull(testMessage.EmptyMember);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void RequestNull() {
+ this.channel.Request(null);
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void RequestNullRecipient() {
+ IDirectedProtocolMessage message = new TestDirectedMessage(MessageTransport.Direct);
+ this.channel.Request(message);
+ }
+
+ [TestMethod, ExpectedException(typeof(NotSupportedException))]
+ public void RequestBadPreferredScheme() {
+ TestDirectedMessage message = new TestDirectedMessage(MessageTransport.Direct);
+ message.Recipient = new Uri("http://localtest");
+ message.HttpMethods = HttpDeliveryMethods.None;
+ this.channel.Request(message);
+ }
+
+ [TestMethod]
+ public void RequestUsingAuthorizationHeader() {
+ this.ParameterizedRequestTest(HttpDeliveryMethods.AuthorizationHeaderRequest);
+ }
+
+ [TestMethod]
+ public void RequestUsingGet() {
+ this.ParameterizedRequestTest(HttpDeliveryMethods.GetRequest);
+ }
+
+ [TestMethod]
+ public void RequestUsingPost() {
+ this.ParameterizedRequestTest(HttpDeliveryMethods.PostRequest);
+ }
+
+ private static string CreateAuthorizationHeader(IDictionary<string, string> fields) {
+ if (fields == null) {
+ throw new ArgumentNullException("fields");
+ }
+
+ StringBuilder authorization = new StringBuilder();
+ authorization.Append("OAuth ");
+ foreach (var pair in fields) {
+ string key = Uri.EscapeDataString(pair.Key);
+ string value = Uri.EscapeDataString(pair.Value);
+ authorization.Append(key);
+ authorization.Append("=\"");
+ authorization.Append(value);
+ authorization.Append("\",");
+ }
+ authorization.Length--; // remove trailing comma
+
+ return authorization.ToString();
+ }
+
+ private static HttpRequestInfo CreateHttpRequestInfo(HttpDeliveryMethods scheme, IDictionary<string, string> fields) {
+ string query = MessagingUtilities.CreateQueryString(fields);
+ UriBuilder requestUri = new UriBuilder("http://localhost/path");
+ WebHeaderCollection headers = new WebHeaderCollection();
+ MemoryStream ms = new MemoryStream();
+ string method;
+ switch (scheme) {
+ case HttpDeliveryMethods.PostRequest:
+ method = "POST";
+ headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
+ StreamWriter sw = new StreamWriter(ms);
+ sw.Write(query);
+ sw.Flush();
+ ms.Position = 0;
+ break;
+ case HttpDeliveryMethods.GetRequest:
+ method = "GET";
+ requestUri.Query = query;
+ break;
+ case HttpDeliveryMethods.AuthorizationHeaderRequest:
+ method = "GET";
+ headers.Add(HttpRequestHeader.Authorization, CreateAuthorizationHeader(fields));
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("scheme", scheme, "Unexpected value");
+ }
+ HttpRequestInfo request = new HttpRequestInfo {
+ HttpMethod = method,
+ Url = requestUri.Uri,
+ Headers = headers,
+ InputStream = ms,
+ };
+
+ return request;
+ }
+
+ private static HttpRequestInfo ConvertToRequestInfo(HttpWebRequest request, Stream postEntity) {
+ HttpRequestInfo info = new HttpRequestInfo {
+ HttpMethod = request.Method,
+ Url = request.RequestUri,
+ Headers = request.Headers,
+ InputStream = postEntity,
+ };
+ return info;
+ }
+
+ private void ParameterizedRequestTest(HttpDeliveryMethods scheme) {
+ TestDirectedMessage request = new TestDirectedMessage(MessageTransport.Direct) {
+ Age = 15,
+ Name = "Andrew",
+ Location = new Uri("http://hostb/pathB"),
+ Recipient = new Uri("http://localtest"),
+ Timestamp = DateTime.UtcNow,
+ HttpMethods = scheme,
+ };
+
+ Response rawResponse = null;
+ this.webRequestHandler.Callback = (req) => {
+ Assert.IsNotNull(req);
+ HttpRequestInfo reqInfo = ConvertToRequestInfo(req, this.webRequestHandler.RequestEntityStream);
+ Assert.AreEqual(scheme == HttpDeliveryMethods.PostRequest ? "POST" : "GET", reqInfo.HttpMethod);
+ var incomingMessage = this.channel.ReadFromRequest(reqInfo) as TestMessage;
+ Assert.IsNotNull(incomingMessage);
+ Assert.AreEqual(request.Age, incomingMessage.Age);
+ Assert.AreEqual(request.Name, incomingMessage.Name);
+ Assert.AreEqual(request.Location, incomingMessage.Location);
+ Assert.AreEqual(request.Timestamp, incomingMessage.Timestamp);
+
+ var responseFields = new Dictionary<string, string> {
+ { "age", request.Age.ToString() },
+ { "Name", request.Name },
+ { "Location", request.Location.AbsoluteUri },
+ { "Timestamp", XmlConvert.ToString(request.Timestamp, XmlDateTimeSerializationMode.Utc) },
+ };
+ rawResponse = new Response {
+ Body = MessagingUtilities.CreateQueryString(responseFields),
+ };
+ return rawResponse;
+ };
+
+ IProtocolMessage response = this.channel.Request(request);
+ Assert.IsNotNull(response);
+ Assert.IsInstanceOfType(response, typeof(TestMessage));
+ TestMessage responseMessage = (TestMessage)response;
+ Assert.AreEqual(request.Age, responseMessage.Age);
+ Assert.AreEqual(request.Name, responseMessage.Name);
+ Assert.AreEqual(request.Location, responseMessage.Location);
+ }
+
+ private void ParameterizedReceiveTest(HttpDeliveryMethods scheme) {
+ var fields = new Dictionary<string, string> {
+ { "age", "15" },
+ { "Name", "Andrew" },
+ { "Location", "http://hostb/pathB" },
+ { "Timestamp", XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.Utc) },
+ };
+ IProtocolMessage requestMessage = this.channel.ReadFromRequest(CreateHttpRequestInfo(scheme, fields));
+ Assert.IsNotNull(requestMessage);
+ Assert.IsInstanceOfType(requestMessage, typeof(TestMessage));
+ TestMessage testMessage = (TestMessage)requestMessage;
+ Assert.AreEqual(15, testMessage.Age);
+ Assert.AreEqual("Andrew", testMessage.Name);
+ Assert.AreEqual("http://hostb/pathB", testMessage.Location.AbsoluteUri);
+ }
+ }
+}
diff --git a/src/DotNetOAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs b/src/DotNetOAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs
new file mode 100644
index 0000000..151f00d
--- /dev/null
+++ b/src/DotNetOAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs
@@ -0,0 +1,78 @@
+//-----------------------------------------------------------------------
+// <copyright file="PlaintextSigningBindingElementTest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOAuth.Test.OAuth.ChannelElements
+{
+ using DotNetOAuth.Messaging;
+ using DotNetOAuth.OAuth.ChannelElements;
+ using DotNetOAuth.OAuth.Messages;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class PlaintextSigningBindingElementTest {
+ [TestMethod]
+ public void HttpsSignatureGeneration() {
+ SigningBindingElementBase target = new PlaintextSigningBindingElement();
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://localtest", HttpDeliveryMethods.GetRequest);
+ ITamperResistantOAuthMessage message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerSecret = "cs";
+ message.TokenSecret = "ts";
+ Assert.IsTrue(target.PrepareMessageForSending(message));
+ Assert.AreEqual("PLAINTEXT", message.SignatureMethod);
+ Assert.AreEqual("cs&ts", message.Signature);
+ }
+
+ [TestMethod]
+ public void HttpsSignatureVerification() {
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://localtest", HttpDeliveryMethods.GetRequest);
+ ITamperProtectionChannelBindingElement target = new PlaintextSigningBindingElement();
+ ITamperResistantOAuthMessage message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerSecret = "cs";
+ message.TokenSecret = "ts";
+ message.SignatureMethod = "PLAINTEXT";
+ message.Signature = "cs&ts";
+ Assert.IsTrue(target.PrepareMessageForReceiving(message));
+ }
+
+ [TestMethod]
+ public void HttpsSignatureVerificationNotApplicable() {
+ SigningBindingElementBase target = new PlaintextSigningBindingElement();
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://localtest", HttpDeliveryMethods.GetRequest);
+ ITamperResistantOAuthMessage message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerSecret = "cs";
+ message.TokenSecret = "ts";
+ message.SignatureMethod = "ANOTHERALGORITHM";
+ message.Signature = "somethingelse";
+ Assert.IsFalse(target.PrepareMessageForReceiving(message), "PLAINTEXT binding element should opt-out where it doesn't understand.");
+ }
+
+ [TestMethod]
+ public void HttpSignatureGeneration() {
+ SigningBindingElementBase target = new PlaintextSigningBindingElement();
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("http://localtest", HttpDeliveryMethods.GetRequest);
+ ITamperResistantOAuthMessage message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerSecret = "cs";
+ message.TokenSecret = "ts";
+
+ // Since this is (non-encrypted) HTTP, so the plain text signer should not be used
+ Assert.IsFalse(target.PrepareMessageForSending(message));
+ Assert.IsNull(message.SignatureMethod);
+ Assert.IsNull(message.Signature);
+ }
+
+ [TestMethod]
+ public void HttpSignatureVerification() {
+ SigningBindingElementBase target = new PlaintextSigningBindingElement();
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("http://localtest", HttpDeliveryMethods.GetRequest);
+ ITamperResistantOAuthMessage message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerSecret = "cs";
+ message.TokenSecret = "ts";
+ message.SignatureMethod = "PLAINTEXT";
+ message.Signature = "cs%26ts";
+ Assert.IsFalse(target.PrepareMessageForReceiving(message), "PLAINTEXT signature binding element should refuse to participate in non-encrypted messages.");
+ }
+ }
+}
diff --git a/src/DotNetOAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
new file mode 100644
index 0000000..e764322
--- /dev/null
+++ b/src/DotNetOAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="SigningBindingElementBaseTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOAuth.Test.OAuth.ChannelElements {
+ using DotNetOAuth.Messaging;
+ using DotNetOAuth.Messaging.Reflection;
+ using DotNetOAuth.OAuth.ChannelElements;
+ using DotNetOAuth.OAuth.Messages;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class SigningBindingElementBaseTests : MessagingTestBase {
+ [TestMethod]
+ public void BaseSignatureStringTest() {
+ UnauthorizedTokenRequest message = CreateTestRequestTokenMessage();
+
+ Assert.AreEqual(
+ "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F",
+ SigningBindingElementBase_Accessor.ConstructSignatureBaseString(message));
+ }
+
+ internal static UnauthorizedTokenRequest CreateTestRequestTokenMessage() {
+ MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
+ UnauthorizedTokenRequest message = new UnauthorizedTokenRequest(endpoint);
+ message.ConsumerKey = "nerdbank.org";
+ ((ITamperResistantOAuthMessage)message).ConsumerSecret = "nerdbanksecret";
+ var signedMessage = (ITamperResistantOAuthMessage)message;
+ signedMessage.HttpMethod = "GET";
+ signedMessage.SignatureMethod = "HMAC-SHA1";
+ MessageDictionary dictionary = new MessageDictionary(message);
+ dictionary["oauth_timestamp"] = "1222665749";
+ dictionary["oauth_nonce"] = "fe4045a3f0efdd1e019fa8f8ae3f5c38";
+ dictionary["scope"] = "http://www.google.com/m8/feeds/";
+ return message;
+ }
+ }
+}