diff options
Diffstat (limited to 'src/DotNetOpenAuth.Web.Test')
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/DotNetOpenAuth.Web.Test.csproj | 87 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/OAuth2ClientTest.cs | 142 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/OAuthAuthenticationTickerHelperTest.cs | 152 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/OAuthClientTest.cs | 142 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/OAuthWebSecurityTest.cs | 486 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/Properties/AssemblyInfo.cs | 35 | ||||
-rw-r--r-- | src/DotNetOpenAuth.Web.Test/UriHelperTest.cs | 64 |
7 files changed, 1108 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.Web.Test/DotNetOpenAuth.Web.Test.csproj b/src/DotNetOpenAuth.Web.Test/DotNetOpenAuth.Web.Test.csproj new file mode 100644 index 0000000..d02c530 --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/DotNetOpenAuth.Web.Test.csproj @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " /> + <PropertyGroup> + <StyleCopEnabled>False</StyleCopEnabled> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>DotNetOpenAuth.Web.Test</RootNamespace> + <AssemblyName>DotNetOpenAuth.Web.Test</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" /> + <PropertyGroup> + <DelaySign>true</DelaySign> + </PropertyGroup> + <ItemGroup> + <Reference Include="Moq"> + <HintPath>..\..\lib\Moq.dll</HintPath> + </Reference> + <Reference Include="nunit.framework"> + <HintPath>..\..\lib\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="OAuth2ClientTest.cs" /> + <Compile Include="OAuthAuthenticationTickerHelperTest.cs" /> + <Compile Include="OAuthClientTest.cs" /> + <Compile Include="OAuthWebSecurityTest.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="UriHelperTest.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\DotNetOpenAuth.Messaging\DotNetOpenAuth.Messaging.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Messaging</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj"> + <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project> + <Name>DotNetOpenAuth.OAuth</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.WebPages\DotNetOpenAuth.WebPages.csproj"> + <Project>{AE031B0C-710B-4D5B-BDF5-F21DFC9092D8}</Project> + <Name>DotNetOpenAuth.WebPages</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.Web\DotNetOpenAuth.Web.csproj"> + <Project>{51835086-9611-4C53-819B-F2D5C9320873}</Project> + <Name>DotNetOpenAuth.Web</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="official-build-key.pfx" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " /> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.Web.Test/OAuth2ClientTest.cs b/src/DotNetOpenAuth.Web.Test/OAuth2ClientTest.cs new file mode 100644 index 0000000..b090346 --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/OAuth2ClientTest.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using DotNetOpenAuth.Web.Clients; +using Moq; +using System.Web; +using System.Collections.Specialized; + +namespace DotNetOpenAuth.Web.Test +{ + [TestFixture] + public class OAuth2ClientTest + { + [TestCase] + public void TestProviderName() + { + // Arrange + var client = new MockOAuth2Client(); + + // Act + string providerName = client.ProviderName; + + // Assert + Assert.AreEqual("mockprovider", providerName); + } + + [TestCase] + public void RequestAuthenticationIssueCorrectRedirect() + { + // Arrange + var client = new MockOAuth2Client(); + var context = new Mock<HttpContextBase>(MockBehavior.Strict); + context.Setup(c => c.Response.Redirect("http://live.com/?q=http://return.to.me/", true)).Verifiable(); + + // Act + client.RequestAuthentication(context.Object, new Uri("http://return.to.me")); + + // Assert + context.Verify(); + } + + [TestCase] + public void VerifyAuthenticationThrowsIfContextIsNull() + { + // Arrange + var client = new MockOAuth2Client(); + + // Act && Assert + Assert.Throws<ArgumentNullException>(() => client.VerifyAuthentication(null)); + } + + [TestCase] + public void VerifyAuthenticationFailsIfCodeIsNotPresent() + { + // Arrange + var client = new MockOAuth2Client(); + var context = new Mock<HttpContextBase>(MockBehavior.Strict); + var queryStrings = new NameValueCollection(); + context.Setup(c => c.Request.QueryString).Returns(queryStrings); + + // Act + AuthenticationResult result = client.VerifyAuthentication(context.Object); + + // Assert + Assert.IsFalse(result.IsSuccessful); + } + + [TestCase] + public void VerifyAuthenticationFailsIfAccessTokenIsNull() + { + // Arrange + var client = new MockOAuth2Client(); + var context = new Mock<HttpContextBase>(MockBehavior.Strict); + var queryStrings = new NameValueCollection(); + queryStrings.Add("code", "random"); + context.Setup(c => c.Request.QueryString).Returns(queryStrings); + + // Act + AuthenticationResult result = client.VerifyAuthentication(context.Object); + + // Assert + Assert.IsFalse(result.IsSuccessful); + } + + [TestCase] + public void VerifyAuthenticationSucceeds() + { + // Arrange + var client = new MockOAuth2Client(); + var context = new Mock<HttpContextBase>(MockBehavior.Strict); + var queryStrings = new NameValueCollection(); + queryStrings.Add("code", "secret"); + context.Setup(c => c.Request.QueryString).Returns(queryStrings); + + // Act + AuthenticationResult result = client.VerifyAuthentication(context.Object); + + // Assert + Assert.True(result.IsSuccessful); + Assert.AreEqual("mockprovider", result.Provider); + Assert.AreEqual("12345", result.ProviderUserId); + Assert.AreEqual("John Doe", result.UserName); + Assert.NotNull(result.ExtraData); + Assert.AreEqual("abcde", result.ExtraData["token"]); + } + + private class MockOAuth2Client : OAuth2Client + { + public MockOAuth2Client() : base("mockprovider") + { + } + + protected override Uri GetServiceLoginUrl(Uri returnUrl) + { + string url = "http://live.com/?q=" + returnUrl.ToString(); + return new Uri(url); + } + + protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) + { + return (authorizationCode == "secret") ? "abcde" : null; + } + + protected override IDictionary<string, string> GetUserData(string accessToken) + { + if (accessToken == "abcde") + { + return new Dictionary<string, string> + { + {"id", "12345"}, + {"token", accessToken}, + {"name", "John Doe"} + }; + } + + return null; + } + } + } +} diff --git a/src/DotNetOpenAuth.Web.Test/OAuthAuthenticationTickerHelperTest.cs b/src/DotNetOpenAuth.Web.Test/OAuthAuthenticationTickerHelperTest.cs new file mode 100644 index 0000000..2545bb3 --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/OAuthAuthenticationTickerHelperTest.cs @@ -0,0 +1,152 @@ +using System; +using System.Web; +using System.Web.Security; +using DotNetOpenAuth.Web; +using Moq; +using NUnit.Framework; + +namespace DotNetOpenAuth.Test.Web +{ + [TestFixture] + public class OAuthAuthenticationTickerHelperTest + { + [TestCase] + public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentSet() + { + SetAuthenticationTicketSetCookieOnHttpResponse(isPersistent: true); + } + + [TestCase] + public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentNotSet() + { + SetAuthenticationTicketSetCookieOnHttpResponse(isPersistent: false); + } + + [TestCase] + public void IsOAuthAuthenticationTicketReturnsTrueIfCookieIsPresent() + { + // Arrange + var ticket = new FormsAuthenticationTicket( + 2, + "username", + DateTime.Now, + DateTime.Now.Add(FormsAuthentication.Timeout), + false, + "OAuth", + FormsAuthentication.FormsCookiePath); + + var cookie = new HttpCookie(name: FormsAuthentication.FormsCookieName, + value: FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection {cookie}; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OAuthAuthenticationTicketHelper.IsOAuthAuthenticationTicket(context.Object); + + // Assert + Assert.IsTrue(result); + } + + [TestCase] + public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsNotPresent() + { + // Arrange + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(new HttpCookieCollection()); + + // Act + bool result = OAuthAuthenticationTicketHelper.IsOAuthAuthenticationTicket(context.Object); + + // Assert + Assert.IsFalse(result); + } + + [TestCase] + public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsPresentButDoesNotHaveOAuthData() + { + // Arrange + var ticket = new FormsAuthenticationTicket( + 2, + "username", + DateTime.Now, + DateTime.Now.Add(FormsAuthentication.Timeout), + false, + null, + FormsAuthentication.FormsCookiePath); + + var cookie = new HttpCookie(name: FormsAuthentication.FormsCookieName, + value: FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection { cookie }; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OAuthAuthenticationTicketHelper.IsOAuthAuthenticationTicket(context.Object); + + // Assert + Assert.IsFalse(result); + } + + [TestCase] + public void IsOAuthAuthenticationTicketReturnsFalseIfCookieIsPresentButDoesNotHaveCorrectName() + { + // Arrange + var response = new Mock<HttpResponseBase>(); + + var ticket = new FormsAuthenticationTicket( + 2, + "username", + DateTime.Now, + DateTime.Now.Add(FormsAuthentication.Timeout), + false, + "OAuth", + FormsAuthentication.FormsCookiePath); + + var cookie = new HttpCookie(name: "random cookie name", + value: FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection { cookie }; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OAuthAuthenticationTicketHelper.IsOAuthAuthenticationTicket(context.Object); + + // Assert + Assert.IsFalse(result); + } + + private void SetAuthenticationTicketSetCookieOnHttpResponse(bool isPersistent) + { + // Arrange + var cookies = new HttpCookieCollection(); + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.IsSecureConnection).Returns(true); + context.Setup(c => c.Response.Cookies).Returns(cookies); + + // Act + OAuthAuthenticationTicketHelper.SetAuthenticationTicket(context.Object, "user", isPersistent); + + // Assert + Assert.AreEqual(1, cookies.Count); + HttpCookie addedCookie = cookies[0]; + + Assert.AreEqual(FormsAuthentication.FormsCookieName, addedCookie.Name); + Assert.IsTrue(addedCookie.HttpOnly); + Assert.AreEqual("/", addedCookie.Path); + Assert.IsFalse(addedCookie.Secure); + Assert.IsNotNullOrEmpty(addedCookie.Value); + + FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(addedCookie.Value); + Assert.NotNull(ticket); + Assert.AreEqual(2, ticket.Version); + Assert.AreEqual("user", ticket.Name); + Assert.AreEqual("OAuth", ticket.UserData); + Assert.AreEqual(isPersistent, ticket.IsPersistent); + } + } +} diff --git a/src/DotNetOpenAuth.Web.Test/OAuthClientTest.cs b/src/DotNetOpenAuth.Web.Test/OAuthClientTest.cs new file mode 100644 index 0000000..8e8cf1e --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/OAuthClientTest.cs @@ -0,0 +1,142 @@ +using System; +using System.Web; +using DotNetOpenAuth.Messaging; +using DotNetOpenAuth.OAuth.Messages; +using DotNetOpenAuth.Web.Clients; +using Moq; +using NUnit.Framework; + +namespace DotNetOpenAuth.Web.Test +{ + [TestFixture] + public class OAuthClientTest + { + [TestCase] + public void TestProviderNamePropertyIsCorrect() + { + // Arrange + var client = new MockOAuthClient(); + + // Act + var provider = client.ProviderName; + + // Assert + Assert.AreEqual("mockoauth", provider); + } + + [TestCase] + public void RequestAuthenticationInvokeMethodOnWebWorker() + { + // Arrange + var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict); + webWorker.Setup( + w => w.RequestAuthentication( + It.Is<Uri>(u => u.ToString().Equals("http://live.com/my/path.cshtml?q=one")))) + .Verifiable(); + + var client = new MockOAuthClient(webWorker.Object); + var returnUri = new Uri("http://live.com/my/path.cshtml?q=one"); + var context = new Mock<HttpContextBase>(); + + // Act + client.RequestAuthentication(context.Object, returnUri); + + // Assert + webWorker.Verify(); + } + + [TestCase] + public void VerifyAuthenticationFailsIfResponseTokenIsNull() + { + // Arrange + var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict); + webWorker.Setup(w => w.ProcessUserAuthorization()).Returns((AuthorizedTokenResponse)null); + + var client = new MockOAuthClient(webWorker.Object); + var context = new Mock<HttpContextBase>(); + + // Act + client.VerifyAuthentication(context.Object); + + // Assert + webWorker.Verify(); + } + + [TestCase] + public void VerifyAuthenticationFailsIfAccessTokenIsInvalid() + { + // Arrange + var endpoint = new MessageReceivingEndpoint("http://live.com/path/?a=b", HttpDeliveryMethods.GetRequest); + var request = new AuthorizedTokenRequest(endpoint, new Version("1.0")); + var response = new AuthorizedTokenResponse(request) + { + AccessToken = "invalid token" + }; + + var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict); + webWorker.Setup(w => w.ProcessUserAuthorization()).Returns(response).Verifiable(); + + var client = new MockOAuthClient(webWorker.Object); + var context = new Mock<HttpContextBase>(); + + // Act + AuthenticationResult result = client.VerifyAuthentication(context.Object); + + // Assert + webWorker.Verify(); + + Assert.False(result.IsSuccessful); + } + + [TestCase] + public void VerifyAuthenticationSucceeds() + { + // Arrange + var endpoint = new MessageReceivingEndpoint("http://live.com/path/?a=b", HttpDeliveryMethods.GetRequest); + var request = new AuthorizedTokenRequest(endpoint, new Version("1.0")); + var response = new AuthorizedTokenResponse(request) + { + AccessToken = "ok" + }; + + var webWorker = new Mock<IOAuthWebWorker>(MockBehavior.Strict); + webWorker.Setup(w => w.ProcessUserAuthorization()).Returns(response).Verifiable(); + + var client = new MockOAuthClient(webWorker.Object); + var context = new Mock<HttpContextBase>(); + + // Act + AuthenticationResult result = client.VerifyAuthentication(context.Object); + + // Assert + webWorker.Verify(); + + Assert.True(result.IsSuccessful); + Assert.AreEqual("mockoauth", result.Provider); + Assert.AreEqual("12345", result.ProviderUserId); + Assert.AreEqual("super", result.UserName); + } + + private class MockOAuthClient : OAuthClient + { + public MockOAuthClient() + : this(new Mock<IOAuthWebWorker>().Object) + { + } + + public MockOAuthClient(IOAuthWebWorker worker) : base("mockoauth", worker) + { + } + + protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response) + { + if (response.AccessToken == "ok") + { + return new AuthenticationResult(true, "mockoauth", "12345", "super", response.ExtraData); + } + + return AuthenticationResult.Failed; + } + } + } +} diff --git a/src/DotNetOpenAuth.Web.Test/OAuthWebSecurityTest.cs b/src/DotNetOpenAuth.Web.Test/OAuthWebSecurityTest.cs new file mode 100644 index 0000000..2465f0f --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/OAuthWebSecurityTest.cs @@ -0,0 +1,486 @@ +using System; +using System.Collections.Specialized; +using System.Web; +using System.Web.Security; +using DotNetOpenAuth.Web.Clients; +using Moq; +using NUnit.Framework; + +namespace DotNetOpenAuth.Web.Test +{ + [TestFixture] + public class OAuthWebSecurityTest + { + [TestCase] + public void RegisterDataProviderThrowsOnNullValue() + { + Assert.Throws(typeof(ArgumentNullException), () => OAuthWebSecurity.RegisterDataProvider(null)); + } + + [TestCase] + public void IsOAuthDataProviderIsFalseIfNotYetRegistered() + { + Assert.IsFalse(OAuthWebSecurity.IsOAuthDataProviderRegistered); + } + + [TestCase] + public void IsOAuthDataProviderIsTrueIfRegistered() + { + // Arrange + OAuthWebSecurity.RegisterDataProvider(new Mock<IOAuthDataProvider>().Object); + + // Act & Assert + Assert.IsTrue(OAuthWebSecurity.IsOAuthDataProviderRegistered); + } + + [TestCase] + public void RegisterDataProviderThrowsIfRegisterMoreThanOnce() + { + // Arrange + OAuthWebSecurity.RegisterDataProvider(new Mock<IOAuthDataProvider>().Object); + + // Act & Assert + Assert.Throws( + typeof(InvalidOperationException), + () => OAuthWebSecurity.RegisterDataProvider(new Mock<IOAuthDataProvider>().Object)); + } + + [TestCase] + public void RegisterClientThrowsOnNullValue() + { + Assert.Throws(typeof(ArgumentNullException), () => OAuthWebSecurity.RegisterClient(null)); + } + + [TestCase] + public void RegisterClientThrowsIfProviderNameIsEmpty() + { + // Arrange + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns((string)null); + + // Act & Assert + Assert.Throws(typeof(ArgumentException), () => OAuthWebSecurity.RegisterClient(client.Object), "Invalid provider name."); + + client.Setup(c => c.ProviderName).Returns(""); + + // Act & Assert + Assert.Throws(typeof(ArgumentException), () => OAuthWebSecurity.RegisterClient(client.Object), "Invalid provider name."); + } + + [TestCase] + public void RegisterClientThrowsRegisterMoreThanOneClientWithTheSameName() + { + // Arrange + var client1 = new Mock<IAuthenticationClient>(); + client1.Setup(c => c.ProviderName).Returns("provider"); + + var client2 = new Mock<IAuthenticationClient>(); + client2.Setup(c => c.ProviderName).Returns("provider"); + + OAuthWebSecurity.RegisterClient(client1.Object); + + // Act & Assert + Assert.Throws( + typeof(ArgumentException), + () => OAuthWebSecurity.RegisterClient(client2.Object), + "Another service provider with the same name has already been registered."); + } + + [TestCase] + public void RegisterOAuthClient() + { + // Arrange + var clients = new BuiltInOAuthClient[] + { + BuiltInOAuthClient.Facebook, + BuiltInOAuthClient.Twitter, + BuiltInOAuthClient.LinkedIn, + BuiltInOAuthClient.WindowsLive + }; + var clientNames = new string[] + { + "Facebook", + "Twitter", + "LinkedIn", + "WindowsLive" + }; + + for (int i = 0; i < clients.Length; i++) + { + // Act + OAuthWebSecurity.RegisterOAuthClient(clients[i], "key", "secret"); + + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns(clientNames[i]); + + // Assert + Assert.Throws( + typeof(ArgumentException), + () => OAuthWebSecurity.RegisterClient(client.Object), + "Another service provider with the same name has already been registered."); + } + } + + [TestCase] + public void RegisterOpenIDClient() + { + // Arrange + var clients = new BuiltInOpenIDClient[] + { + BuiltInOpenIDClient.Google, + BuiltInOpenIDClient.Yahoo + }; + var clientNames = new string[] + { + "Google", + "Yahoo" + }; + + for (int i = 0; i < clients.Length; i++) + { + // Act + OAuthWebSecurity.RegisterOpenIDClient(clients[i]); + + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns(clientNames[i]); + + // Assert + Assert.Throws( + typeof(ArgumentException), + () => OAuthWebSecurity.RegisterClient(client.Object), + "Another service provider with the same name has already been registered."); + } + } + + [TestCase] + public void RequestAuthenticationRedirectsToProviderWithNullReturnUrl() + { + // Arrange + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.ServerVariables).Returns( + new NameValueCollection()); + context.Setup(c => c.Request.Url).Returns(new Uri("http://live.com/login.aspx")); + context.Setup(c => c.Request.RawUrl).Returns("/login.aspx"); + + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("windowslive"); + client.Setup(c => c.RequestAuthentication( + context.Object, + It.Is<Uri>(u => u.AbsoluteUri.Equals("http://live.com/login.aspx?__provider__=windowslive", StringComparison.OrdinalIgnoreCase)))) + .Verifiable(); + + OAuthWebSecurity.RegisterClient(client.Object); + + // Act + OAuthWebSecurity.RequestAuthenticationCore(context.Object, "windowslive", null); + + // Assert + client.Verify(); + } + + [TestCase] + public void RequestAuthenticationRedirectsToProviderWithReturnUrl() + { + // Arrange + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.ServerVariables).Returns( + new NameValueCollection()); + context.Setup(c => c.Request.Url).Returns(new Uri("http://live.com/login.aspx")); + context.Setup(c => c.Request.RawUrl).Returns("/login.aspx"); + + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("yahoo"); + client.Setup(c => c.RequestAuthentication( + context.Object, + It.Is<Uri>(u => u.AbsoluteUri.Equals("http://yahoo.com/?__provider__=yahoo", StringComparison.OrdinalIgnoreCase)))) + .Verifiable(); + + OAuthWebSecurity.RegisterClient(client.Object); + + // Act + OAuthWebSecurity.RequestAuthenticationCore(context.Object, "yahoo", "http://yahoo.com"); + + // Assert + client.Verify(); + } + + [TestCase] + public void VerifyAuthenticationSucceed() + { + // Arrange + var queryStrings = new NameValueCollection(); + queryStrings.Add("__provider__", "facebook"); + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.QueryString).Returns(queryStrings); + + var client = new Mock<IAuthenticationClient>(MockBehavior.Strict); + client.Setup(c => c.ProviderName).Returns("facebook"); + client.Setup(c => c.VerifyAuthentication(context.Object)).Returns(new AuthenticationResult(true, "facebook", "123", + "super", null)); + + var anotherClient = new Mock<IAuthenticationClient>(MockBehavior.Strict); + anotherClient.Setup(c => c.ProviderName).Returns("twitter"); + anotherClient.Setup(c => c.VerifyAuthentication(context.Object)).Returns(AuthenticationResult.Failed); + + OAuthWebSecurity.RegisterClient(client.Object); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + AuthenticationResult result = OAuthWebSecurity.VerifyAuthenticationCore(context.Object); + + // Assert + Assert.True(result.IsSuccessful); + Assert.AreEqual("facebook", result.Provider); + Assert.AreEqual("123", result.ProviderUserId); + Assert.AreEqual("super", result.UserName); + Assert.IsNull(result.Error); + Assert.IsNull(result.ExtraData); + } + + [TestCase] + public void VerifyAuthenticationFail() + { + // Arrange + var queryStrings = new NameValueCollection(); + queryStrings.Add("__provider__", "twitter"); + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.QueryString).Returns(queryStrings); + + var client = new Mock<IAuthenticationClient>(MockBehavior.Strict); + client.Setup(c => c.ProviderName).Returns("facebook"); + client.Setup(c => c.VerifyAuthentication(context.Object)).Returns(new AuthenticationResult(true, "facebook", "123", + "super", null)); + + var anotherClient = new Mock<IAuthenticationClient>(MockBehavior.Strict); + anotherClient.Setup(c => c.ProviderName).Returns("twitter"); + anotherClient.Setup(c => c.VerifyAuthentication(context.Object)).Returns(AuthenticationResult.Failed); + + OAuthWebSecurity.RegisterClient(client.Object); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + AuthenticationResult result = OAuthWebSecurity.VerifyAuthenticationCore(context.Object); + + // Assert + Assert.False(result.IsSuccessful); + Assert.AreEqual("twitter", result.Provider); + } + + [TestCase] + public void VerifyAuthenticationFailIfNoProviderInQueryString() + { + // Arrange + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.QueryString).Returns(new NameValueCollection()); + + var client = new Mock<IAuthenticationClient>(MockBehavior.Strict); + client.Setup(c => c.ProviderName).Returns("facebook"); + + var anotherClient = new Mock<IAuthenticationClient>(MockBehavior.Strict); + anotherClient.Setup(c => c.ProviderName).Returns("twitter"); + + OAuthWebSecurity.RegisterClient(client.Object); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + AuthenticationResult result = OAuthWebSecurity.VerifyAuthenticationCore(context.Object); + + // Assert + Assert.False(result.IsSuccessful); + Assert.IsNull(result.Provider); + } + + [TestCase] + public void LoginSetAuthenticationTicketIfSuccessful() + { + // Arrange + var cookies = new HttpCookieCollection(); + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.IsSecureConnection).Returns(true); + context.Setup(c => c.Response.Cookies).Returns(cookies); + + var dataProvider = new Mock<IOAuthDataProvider>(MockBehavior.Strict); + dataProvider.Setup(p => p.GetUserNameFromOAuth("twitter", "12345")).Returns("hola"); + OAuthWebSecurity.RegisterDataProvider(dataProvider.Object); + + // Act + bool successful = OAuthWebSecurity.LoginCore(context.Object, "twitter", "12345", createPersistentCookie: false); + + // Assert + Assert.IsTrue(successful); + + Assert.AreEqual(1, cookies.Count); + HttpCookie addedCookie = cookies[0]; + + Assert.AreEqual(FormsAuthentication.FormsCookieName, addedCookie.Name); + Assert.IsTrue(addedCookie.HttpOnly); + Assert.AreEqual("/", addedCookie.Path); + Assert.IsFalse(addedCookie.Secure); + Assert.IsNotNullOrEmpty(addedCookie.Value); + + FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(addedCookie.Value); + Assert.NotNull(ticket); + Assert.AreEqual(2, ticket.Version); + Assert.AreEqual("hola", ticket.Name); + Assert.AreEqual("OAuth", ticket.UserData); + Assert.IsFalse(ticket.IsPersistent); + } + + [TestCase] + public void LoginFailIfUserIsNotFound() + { + // Arrange + var context = new Mock<HttpContextBase>(); + + var dataProvider = new Mock<IOAuthDataProvider>(); + OAuthWebSecurity.RegisterDataProvider(dataProvider.Object); + + // Act + bool successful = OAuthWebSecurity.LoginCore(context.Object, "twitter", "12345", createPersistentCookie: false); + + // Assert + Assert.IsFalse(successful); + } + + [TestCase] + public void CreateOrUpdateAccountCallsOAuthDataProviderMethod() + { + // Arrange + var dataProvider = new Mock<IOAuthDataProvider>(MockBehavior.Strict); + OAuthWebSecurity.RegisterDataProvider(dataProvider.Object); + dataProvider.Setup(p => p.CreateOrUpdateOAuthAccount("twitter", "12345", "super")).Verifiable(); + + // Act + OAuthWebSecurity.CreateOrUpdateAccount("twitter", "12345", "super"); + + // Assert + dataProvider.Verify(); + } + + [TestCase] + public void GetAccountsFromUserNameCallsOAuthDataProviderMethod() + { + // Arrange + var accounts = new OAuthAccount[] + { + new OAuthAccount("twitter", "123"), + new OAuthAccount("facebook", "abc"), + new OAuthAccount("live", "xyz") + }; + + var dataProvider = new Mock<IOAuthDataProvider>(MockBehavior.Strict); + dataProvider.Setup(p => p.GetOAuthAccountsFromUserName("dotnetjunky")).Returns(accounts).Verifiable(); + + OAuthWebSecurity.RegisterDataProvider(dataProvider.Object); + + // Act + var retrievedAccounts = OAuthWebSecurity.GetAccountsFromUserName("dotnetjunky"); + + // Assert + CollectionAssert.AreEqual(retrievedAccounts, accounts); + } + + [TestCase] + public void DeleteAccountCallsOAuthDataProviderMethod() + { + // Arrange + var dataProvider = new Mock<IOAuthDataProvider>(MockBehavior.Strict); + OAuthWebSecurity.RegisterDataProvider(dataProvider.Object); + dataProvider.Setup(p => p.DeleteOAuthAccount("linkedin", "423432")).Returns(true).Verifiable(); + + // Act + OAuthWebSecurity.DeleteAccount("linkedin", "423432"); + + // Assert + dataProvider.Verify(); + } + + [TestCase] + public void GetOAuthClientReturnsTheCorrectClient() + { + // Arrange + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("facebook"); + OAuthWebSecurity.RegisterClient(client.Object); + + var anotherClient = new Mock<IAuthenticationClient>(); + anotherClient.Setup(c => c.ProviderName).Returns("hulu"); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + var expectedClient = OAuthWebSecurity.GetOAuthClient("facebook"); + + // Assert + Assert.AreSame(expectedClient, client.Object); + } + + [TestCase] + public void GetOAuthClientThrowsIfClientIsNotFound() + { + // Arrange + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("facebook"); + OAuthWebSecurity.RegisterClient(client.Object); + + var anotherClient = new Mock<IAuthenticationClient>(); + anotherClient.Setup(c => c.ProviderName).Returns("hulu"); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act & Assert + Assert.Throws<ArgumentException>( + () => OAuthWebSecurity.GetOAuthClient("live"), + "A service provider could not be found by the specified name."); + } + + [TestCase] + public void TryGetOAuthClientSucceeds() + { + // Arrange + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("facebook"); + OAuthWebSecurity.RegisterClient(client.Object); + + var anotherClient = new Mock<IAuthenticationClient>(); + anotherClient.Setup(c => c.ProviderName).Returns("hulu"); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + IAuthenticationClient expectedClient; + bool result = OAuthWebSecurity.TryGetOAuthClient("facebook", out expectedClient); + + // Assert + Assert.AreSame(expectedClient, client.Object); + Assert.IsTrue(result); + } + + [TestCase] + public void TryGetOAuthClientFail() + { + // Arrange + var client = new Mock<IAuthenticationClient>(); + client.Setup(c => c.ProviderName).Returns("facebook"); + OAuthWebSecurity.RegisterClient(client.Object); + + var anotherClient = new Mock<IAuthenticationClient>(); + anotherClient.Setup(c => c.ProviderName).Returns("hulu"); + OAuthWebSecurity.RegisterClient(anotherClient.Object); + + // Act + IAuthenticationClient expectedClient; + bool result = OAuthWebSecurity.TryGetOAuthClient("live", out expectedClient); + + // Assert + Assert.IsNull(expectedClient); + Assert.IsFalse(result); + } + + [TearDown] + public void Cleanup() + { + OAuthWebSecurity.ClearDataProvider(); + OAuthWebSecurity.ClearProviders(); + } + } +} diff --git a/src/DotNetOpenAuth.Web.Test/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.Web.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2ea59e1 --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DotNetOpenAuth.Web.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft IT")] +[assembly: AssemblyProduct("DotNetOpenAuth.Web.Test")] +[assembly: AssemblyCopyright("Copyright © Microsoft IT 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6c32d8f7-1394-40ef-9ec0-b8953adc0a4f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/DotNetOpenAuth.Web.Test/UriHelperTest.cs b/src/DotNetOpenAuth.Web.Test/UriHelperTest.cs new file mode 100644 index 0000000..557efae --- /dev/null +++ b/src/DotNetOpenAuth.Web.Test/UriHelperTest.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using DotNetOpenAuth.Web.Clients; + +namespace DotNetOpenAuth.Web.Test +{ + [TestFixture] + public class UriHelperTest + { + [TestCase] + public void TestAttachQueryStringParameterMethod() + { + // Arrange + string[] input = new string[] + { + "http://x.com", + "https://xxx.com/one?s=123", + "https://yyy.com/?s=6&u=a", + "https://zzz.com/default.aspx?name=sd" + }; + + string[] expectedOutput = new string[] + { + "http://x.com/?s=awesome", + "https://xxx.com/one?s=awesome", + "https://yyy.com/?s=awesome&u=a", + "https://zzz.com/default.aspx?name=sd&s=awesome" + }; + + for (int i = 0; i < input.Length; i++) + { + // Act + var inputUrl = new Uri(input[i]); + var outputUri = UriHelper.AttachQueryStringParameter(inputUrl, "s", "awesome"); + + // Assert + Assert.AreEqual(expectedOutput[i], outputUri.ToString()); + } + } + + [TestCase] + public void TestAppendQueryArguments() + { + // Arrange + var builder = new UriBuilder("http://www.microsoft.com"); + + // Act + builder.AppendQueryArguments( + new Dictionary<string, string> {{"one", "xxx"}, {"two", "yyy"}}); + + // Assert + if (builder.Port == 80) + { + // set port = -1 so that the display string doesn't contain port number + builder.Port = -1; + } + string s = builder.ToString(); + Assert.AreEqual("http://www.microsoft.com/?one=xxx&two=yyy", s); + } + } +} |