diff options
Diffstat (limited to 'src')
238 files changed, 6141 insertions, 1449 deletions
diff --git a/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.AspNet.Test.csproj b/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.AspNet.Test.csproj new file mode 100644 index 0000000..268b7cc --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/DotNetOpenAuth.AspNet.Test.csproj @@ -0,0 +1,78 @@ +<?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> + <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.AspNet.Test</RootNamespace> + <AssemblyName>DotNetOpenAuth.AspNet.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="Properties\AssemblyInfo.cs" /> + <Compile Include="UriHelperTest.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Core</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj"> + <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project> + <Name>DotNetOpenAuth.OAuth</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.AspNet\DotNetOpenAuth.AspNet.csproj"> + <Project>{51835086-9611-4C53-819B-F2D5C9320873}</Project> + <Name>DotNetOpenAuth.AspNet</Name> + </ProjectReference> + </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.AspNet.Test/OAuth2ClientTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs new file mode 100644 index 0000000..89a483c --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/OAuth2ClientTest.cs @@ -0,0 +1,132 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuth2ClientTest.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Test { + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Web; + using DotNetOpenAuth.AspNet.Clients; + using Moq; + using NUnit.Framework; + + [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["accesstoken"]); + } + + 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" }, + { "name", "John Doe" }, + }; + } + + return null; + } + } + } +} diff --git a/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs new file mode 100644 index 0000000..676a550 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/OAuthAuthenticationTickerHelperTest.cs @@ -0,0 +1,146 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthenticationTickerHelperTest.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Web { + using System; + using System.Web; + using System.Web.Security; + using DotNetOpenAuth.AspNet; + using Moq; + using NUnit.Framework; + + [TestFixture] + public class OAuthAuthenticationTickerHelperTest { + [TestCase] + public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentSet() { + this.SetAuthenticationTicketSetCookieOnHttpResponse(isPersistent: true); + } + + [TestCase] + public void SetAuthenticationTicketSetCookieOnHttpResponseWithPersistentNotSet() { + this.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(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection { cookie }; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(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 = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(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(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection { cookie }; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(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("random cookie name", FormsAuthentication.Encrypt(ticket)); + var cookies = new HttpCookieCollection { cookie }; + + var context = new Mock<HttpContextBase>(); + context.Setup(c => c.Request.Cookies).Returns(cookies); + + // Act + bool result = OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(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 + OpenAuthAuthenticationTicketHelper.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.AspNet.Test/OAuthClientTest.cs b/src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs new file mode 100644 index 0000000..3b72b9e --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/OAuthClientTest.cs @@ -0,0 +1,145 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthClientTest.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Test { + using System; + using System.Web; + using DotNetOpenAuth.AspNet; + using DotNetOpenAuth.AspNet.Clients; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth.Messages; + using Moq; + using NUnit.Framework; + + [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); + Assert.IsNotNull(result.ExtraData); + Assert.IsTrue(result.ExtraData.ContainsKey("accesstoken")); + Assert.AreEqual("ok", result.ExtraData["accesstoken"]); + } + + private class MockOAuthClient : OAuthClient { + /// <summary> + /// Initializes a new instance of the <see cref="MockOAuthClient"/> class. + /// </summary> + public MockOAuthClient() + : this(new Mock<IOAuthWebWorker>().Object) { + } + + /// <summary> + /// Initializes a new instance of the <see cref="MockOAuthClient"/> class. + /// </summary> + /// <param name="worker">The worker.</param> + 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.AspNet.Test/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d8a6a0b --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------- +// <copyright file="AssemblyInfo.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +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.AspNet.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("DotNetOpenAuth.AspNet.Test")] +[assembly: AssemblyCopyright("Copyright © Microsoft 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")] diff --git a/src/DotNetOpenAuth.AspNet.Test/Settings.StyleCop b/src/DotNetOpenAuth.AspNet.Test/Settings.StyleCop new file mode 100644 index 0000000..63f402c --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/Settings.StyleCop @@ -0,0 +1,48 @@ +<StyleCopSettings Version="105"> + <Analyzers> + <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules"> + <Rules> + <Rule Name="ElementsMustBeDocumented"> + <RuleSettings> + <BooleanProperty Name="Enabled">False</BooleanProperty> + </RuleSettings> + </Rule> + <Rule Name="EnumerationItemsMustBeDocumented"> + <RuleSettings> + <BooleanProperty Name="Enabled">False</BooleanProperty> + </RuleSettings> + </Rule> + </Rules> + <AnalyzerSettings /> + </Analyzer> + <Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules"> + <Rules> + <Rule Name="SingleLineCommentMustBePrecededByBlankLine"> + <RuleSettings> + <BooleanProperty Name="Enabled">False</BooleanProperty> + </RuleSettings> + </Rule> + </Rules> + <AnalyzerSettings /> + </Analyzer> + <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules"> + <AnalyzerSettings> + <CollectionProperty Name="Hungarian"> + <Value>op</Value> + <Value>rp</Value> + <Value>v</Value> + </CollectionProperty> + </AnalyzerSettings> + </Analyzer> + <Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules"> + <Rules> + <Rule Name="FieldsMustBePrivate"> + <RuleSettings> + <BooleanProperty Name="Enabled">False</BooleanProperty> + </RuleSettings> + </Rule> + </Rules> + <AnalyzerSettings /> + </Analyzer> + </Analyzers> +</StyleCopSettings>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs b/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs new file mode 100644 index 0000000..db60e17 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet.Test/UriHelperTest.cs @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------- +// <copyright file="UriHelperTest.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Test { + using System; + using DotNetOpenAuth.AspNet.Clients; + using NUnit.Framework; + + [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()); + } + } + } +} diff --git a/src/DotNetOpenAuth.AspNet/AuthenticationResult.cs b/src/DotNetOpenAuth.AspNet/AuthenticationResult.cs new file mode 100644 index 0000000..d5fb2d1 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/AuthenticationResult.cs @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------- +// <copyright file="AuthenticationResult.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Represents the result of OAuth or OpenID authentication. + /// </summary> + public class AuthenticationResult { + /// <summary> + /// Returns an instance which indicates failed authentication. + /// </summary> + [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", + Justification = "This type is immutable.")] + public static readonly AuthenticationResult Failed = new AuthenticationResult(isSuccessful: false); + + /// <summary> + /// Initializes a new instance of the <see cref="AuthenticationResult"/> class. + /// </summary> + /// <param name="isSuccessful"> + /// if set to <c>true</c> [is successful]. + /// </param> + public AuthenticationResult(bool isSuccessful) + : this(isSuccessful, provider: null, providerUserId: null, userName: null, extraData: null) { } + + /// <summary> + /// Initializes a new instance of the <see cref="AuthenticationResult"/> class. + /// </summary> + /// <param name="exception"> + /// The exception. + /// </param> + public AuthenticationResult(Exception exception) + : this(isSuccessful: false) { + if (exception == null) { + throw new ArgumentNullException("exception"); + } + + this.Error = exception; + } + + /// <summary> + /// Initializes a new instance of the <see cref="AuthenticationResult"/> class. + /// </summary> + /// <param name="isSuccessful"> + /// if set to <c>true</c> [is successful]. + /// </param> + /// <param name="provider"> + /// The provider. + /// </param> + /// <param name="providerUserId"> + /// The provider user id. + /// </param> + /// <param name="userName"> + /// Name of the user. + /// </param> + /// <param name="extraData"> + /// The extra data. + /// </param> + public AuthenticationResult( + bool isSuccessful, string provider, string providerUserId, string userName, IDictionary<string, string> extraData) { + this.IsSuccessful = isSuccessful; + this.Provider = provider; + this.ProviderUserId = providerUserId; + this.UserName = userName; + if (extraData != null) { + // wrap extraData in a read-only dictionary + this.ExtraData = new ReadOnlyDictionary<string, string>(extraData); + } + } + + /// <summary> + /// Gets the error that may have occured during the authentication process + /// </summary> + public Exception Error { get; private set; } + + /// <summary> + /// Gets the optional extra data that may be returned from the provider + /// </summary> + public IDictionary<string, string> ExtraData { get; private set; } + + /// <summary> + /// Gets a value indicating whether the authentication step is successful. + /// </summary> + /// <value> <c>true</c> if authentication is successful; otherwise, <c>false</c> . </value> + public bool IsSuccessful { get; private set; } + + /// <summary> + /// Gets the provider's name. + /// </summary> + public string Provider { get; private set; } + + /// <summary> + /// Gets the user id that is returned from the provider. It is unique only within the Provider's namespace. + /// </summary> + public string ProviderUserId { get; private set; } + + /// <summary> + /// Gets an (insecure, non-unique) alias for the user that the user should recognize as himself/herself. + /// </summary> + /// <value>This may take the form of an email address, a URL, or any other value that the user may recognize.</value> + /// <remarks> + /// This alias may come from the Provider or may be derived by the relying party if the Provider does not supply one. + /// It is not guaranteed to be unique and certainly does not merit any trust in any suggested authenticity. + /// </remarks> + public string UserName { get; private set; } + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs b/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs new file mode 100644 index 0000000..f441c07 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/DictionaryExtensions.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------- +// <copyright file="DictionaryExtensions.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Xml.Linq; + + /// <summary> + /// The dictionary extensions. + /// </summary> + internal static class DictionaryExtensions { + /// <summary> + /// Adds the value from an XDocument with the specified element name if it's not empty. + /// </summary> + /// <param name="dictionary"> + /// The dictionary. + /// </param> + /// <param name="document"> + /// The document. + /// </param> + /// <param name="elementName"> + /// Name of the element. + /// </param> + public static void AddDataIfNotEmpty( + this Dictionary<string, string> dictionary, XDocument document, string elementName) { + var element = document.Root.Element(elementName); + if (element != null) { + dictionary.AddItemIfNotEmpty(elementName, element.Value); + } + } + + /// <summary> + /// Adds a key/value pair to the specified dictionary if the value is not null or empty. + /// </summary> + /// <param name="dictionary"> + /// The dictionary. + /// </param> + /// <param name="key"> + /// The key. + /// </param> + /// <param name="value"> + /// The value. + /// </param> + public static void AddItemIfNotEmpty(this IDictionary<string, string> dictionary, string key, string value) { + if (key == null) { + throw new ArgumentNullException("key"); + } + + if (!string.IsNullOrEmpty(value)) { + dictionary[key] = value; + } + } + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs new file mode 100644 index 0000000..7eda8e4 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/DotNetOpenAuthWebConsumer.cs @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------- +// <copyright file="DotNetOpenAuthWebConsumer.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Net; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// The dot net open auth web consumer. + /// </summary> + public class DotNetOpenAuthWebConsumer : IOAuthWebWorker, IDisposable { + #region Constants and Fields + + /// <summary> + /// The _web consumer. + /// </summary> + private readonly WebConsumer webConsumer; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="DotNetOpenAuthWebConsumer"/> class. + /// </summary> + /// <param name="serviceDescription"> + /// The service description. + /// </param> + /// <param name="tokenManager"> + /// The token manager. + /// </param> + public DotNetOpenAuthWebConsumer(ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager) { + Requires.NotNull(serviceDescription, "serviceDescription"); + Requires.NotNull(tokenManager, "tokenManager"); + + this.webConsumer = new WebConsumer(serviceDescription, tokenManager); + } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// The prepare authorized request. + /// </summary> + /// <param name="profileEndpoint"> + /// The profile endpoint. + /// </param> + /// <param name="accessToken"> + /// The access token. + /// </param> + /// <returns>An HTTP request.</returns> + public HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint profileEndpoint, string accessToken) { + return this.webConsumer.PrepareAuthorizedRequest(profileEndpoint, accessToken); + } + + /// <summary> + /// The process user authorization. + /// </summary> + /// <returns>The response message.</returns> + public AuthorizedTokenResponse ProcessUserAuthorization() { + return this.webConsumer.ProcessUserAuthorization(); + } + + /// <summary> + /// The request authentication. + /// </summary> + /// <param name="callback"> + /// The callback. + /// </param> + public void RequestAuthentication(Uri callback) { + var redirectParameters = new Dictionary<string, string> { { "force_login", "false" } }; + UserAuthorizationRequest request = this.webConsumer.PrepareRequestUserAuthorization( + callback, null, redirectParameters); + this.webConsumer.Channel.PrepareResponse(request).Send(); + } + + #endregion + + #region IDisposable members + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + /// <filterpriority>2</filterpriority> + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + /// <summary> + /// Releases unmanaged and - optionally - managed resources + /// </summary> + /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool disposing) { + if (disposing) { + this.webConsumer.Dispose(); + } + } + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs new file mode 100644 index 0000000..a054a1c --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/IOAuthWebWorker.cs @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------- +// <copyright file="IOAuthWebWorker.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Net; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// The io auth web worker. + /// </summary> + public interface IOAuthWebWorker { + #region Public Methods and Operators + + /// <summary> + /// The prepare authorized request. + /// </summary> + /// <param name="profileEndpoint"> + /// The profile endpoint. + /// </param> + /// <param name="accessToken"> + /// The access token. + /// </param> + /// <returns>An HTTP request.</returns> + HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint profileEndpoint, string accessToken); + + /// <summary> + /// The process user authorization. + /// </summary> + /// <returns>The response message.</returns> + AuthorizedTokenResponse ProcessUserAuthorization(); + + /// <summary> + /// The request authentication. + /// </summary> + /// <param name="callback"> + /// The callback. + /// </param> + void RequestAuthentication(Uri callback); + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs new file mode 100644 index 0000000..b45a65b --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/InMemoryOAuthTokenManager.cs @@ -0,0 +1,157 @@ +//----------------------------------------------------------------------- +// <copyright file="InMemoryOAuthTokenManager.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// An implementation of IOAuthTokenManager which stores keys in memory. + /// </summary> + public sealed class InMemoryOAuthTokenManager : IConsumerTokenManager { + #region Constants and Fields + + /// <summary> + /// The _tokens and secrets. + /// </summary> + private readonly Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>(); + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="InMemoryOAuthTokenManager"/> class. + /// </summary> + /// <param name="consumerKey"> + /// The consumer key. + /// </param> + /// <param name="consumerSecret"> + /// The consumer secret. + /// </param> + public InMemoryOAuthTokenManager(string consumerKey, string consumerSecret) { + Requires.NotNull(consumerKey, "consumerKey"); + Requires.NotNull(consumerSecret, "consumerSecret"); + + this.ConsumerKey = consumerKey; + this.ConsumerSecret = consumerSecret; + } + + #endregion + + #region Public Properties + + /// <summary> + /// Gets the consumer key. + /// </summary> + public string ConsumerKey { get; private set; } + + /// <summary> + /// Gets the consumer secret. + /// </summary> + public string ConsumerSecret { get; private set; } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Deletes a request token and its associated secret and stores a new access token and secret. + /// </summary> + /// <param name="consumerKey"> + /// The Consumer that is exchanging its request token for an access token. + /// </param> + /// <param name="requestToken"> + /// The Consumer's request token that should be deleted/expired. + /// </param> + /// <param name="accessToken"> + /// The new access token that is being issued to the Consumer. + /// </param> + /// <param name="accessTokenSecret"> + /// The secret associated with the newly issued access token. + /// </param> + /// <remarks> + /// <para> + /// Any scope of granted privileges associated with the request token from the + /// original call to + /// <see cref="StoreNewRequestToken"/> + /// should be carried over + /// to the new Access Token. + /// </para> + /// <para> + /// To associate a user account with the new access token, + /// <see cref="System.Web.HttpContext.User">HttpContext.Current.User</see> + /// may be + /// useful in an ASP.NET web application within the implementation of this method. + /// Alternatively you may store the access token here without associating with a user account, + /// and wait until + /// <see cref="WebConsumer.ProcessUserAuthorization()"/> + /// or + /// <see cref="DesktopConsumer.ProcessUserAuthorization(string, string)"/> + /// return the access + /// token to associate the access token with a user account at that point. + /// </para> + /// </remarks> + public void ExpireRequestTokenAndStoreNewAccessToken( + string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { + this.tokensAndSecrets.Remove(requestToken); + this.tokensAndSecrets[accessToken] = accessTokenSecret; + } + + /// <summary> + /// Gets the Token Secret given a request or access token. + /// </summary> + /// <param name="token"> + /// The request or access token. + /// </param> + /// <returns> + /// The secret associated with the given token. + /// </returns> + /// <exception cref="ArgumentException"> + /// Thrown if the secret cannot be found for the given token. + /// </exception> + public string GetTokenSecret(string token) { + return this.tokensAndSecrets[token]; + } + + /// <summary> + /// Classifies a token as a request token or an access token. + /// </summary> + /// <param name="token"> + /// The token to classify. + /// </param> + /// <returns> + /// Request or Access token, or invalid if the token is not recognized. + /// </returns> + public TokenType GetTokenType(string token) { + throw new NotImplementedException(); + } + + /// <summary> + /// Stores a newly generated unauthorized request token, secret, and optional application-specific parameters for later recall. + /// </summary> + /// <param name="request"> + /// The request message that resulted in the generation of a new unauthorized request token. + /// </param> + /// <param name="response"> + /// The response message that includes the unauthorized request token. + /// </param> + /// <exception cref="ArgumentException"> + /// Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection. + /// </exception> + /// <remarks> + /// Request tokens stored by this method SHOULD NOT associate any user account with this token. It usually opens up security holes in your application to do so. Instead, you associate a user account with access tokens (not request tokens) in the <see cref="ExpireRequestTokenAndStoreNewAccessToken"/> method. + /// </remarks> + public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) { + this.tokensAndSecrets[response.Token] = response.TokenSecret; + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs new file mode 100644 index 0000000..631636b --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------- +// <copyright file="LinkedInClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Net; + using System.Xml.Linq; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// Represents LinkedIn authentication client. + /// </summary> + public sealed class LinkedInClient : OAuthClient { + #region Constants and Fields + + /// <summary> + /// Describes the OAuth service provider endpoints for LinkedIn. + /// </summary> + public static readonly ServiceProviderDescription LinkedInServiceDescription = new ServiceProviderDescription { + RequestTokenEndpoint = + new MessageReceivingEndpoint( + "https://api.linkedin.com/uas/oauth/requestToken", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + UserAuthorizationEndpoint = + new MessageReceivingEndpoint( + "https://www.linkedin.com/uas/oauth/authenticate", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + AccessTokenEndpoint = + new MessageReceivingEndpoint( + "https://api.linkedin.com/uas/oauth/accessToken", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, + }; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="LinkedInClient"/> class. + /// </summary> + /// <param name="consumerKey"> + /// The LinkedIn app's consumer key. + /// </param> + /// <param name="consumerSecret"> + /// The LinkedIn app's consumer secret. + /// </param> + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", + Justification = "We can't dispose the object because we still need it through the app lifetime.")] + public LinkedInClient(string consumerKey, string consumerSecret) + : base("linkedIn", LinkedInServiceDescription, consumerKey, consumerSecret) { } + + #endregion + + #region Methods + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="response"> + /// The response token returned from service provider + /// </param> + /// <returns> + /// Authentication result. + /// </returns> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", + Justification = "We don't care if the request fails.")] + protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response) { + // See here for Field Selectors API http://developer.linkedin.com/docs/DOC-1014 + const string ProfileRequestUrl = "http://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,industry,summary)"; + + string accessToken = response.AccessToken; + + var profileEndpoint = new MessageReceivingEndpoint(ProfileRequestUrl, HttpDeliveryMethods.GetRequest); + HttpWebRequest request = this.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken); + + try { + using (WebResponse profileResponse = request.GetResponse()) { + using (Stream responseStream = profileResponse.GetResponseStream()) { + XDocument document = XDocument.Load(responseStream); + string userId = document.Root.Element("id").Value; + + string firstName = document.Root.Element("first-name").Value; + string lastName = document.Root.Element("last-name").Value; + string userName = firstName + " " + lastName; + + var extraData = new Dictionary<string, string>(); + extraData.Add("accesstoken", accessToken); + extraData.Add("name", userName); + extraData.AddDataIfNotEmpty(document, "headline"); + extraData.AddDataIfNotEmpty(document, "summary"); + extraData.AddDataIfNotEmpty(document, "industry"); + + return new AuthenticationResult( + isSuccessful: true, provider: this.ProviderName, providerUserId: userId, userName: userName, extraData: extraData); + } + } + } catch (Exception exception) { + return new AuthenticationResult(exception); + } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs new file mode 100644 index 0000000..89cefad --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs @@ -0,0 +1,167 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// Represents base class for OAuth 1.0 clients + /// </summary> + public abstract class OAuthClient : IAuthenticationClient { + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthClient"/> class. + /// </summary> + /// <param name="providerName"> + /// Name of the provider. + /// </param> + /// <param name="serviceDescription"> + /// The service description. + /// </param> + /// <param name="consumerKey"> + /// The consumer key. + /// </param> + /// <param name="consumerSecret"> + /// The consumer secret. + /// </param> + protected OAuthClient( + string providerName, ServiceProviderDescription serviceDescription, string consumerKey, string consumerSecret) + : this(providerName, serviceDescription, new InMemoryOAuthTokenManager(consumerKey, consumerSecret)) { } + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthClient"/> class. + /// </summary> + /// <param name="providerName"> + /// Name of the provider. + /// </param> + /// <param name="serviceDescription"> + /// The service Description. + /// </param> + /// <param name="tokenManager"> + /// The token Manager. + /// </param> + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "I don't know how to ensure this rule is followed given this API")] + protected OAuthClient( + string providerName, ServiceProviderDescription serviceDescription, IConsumerTokenManager tokenManager) + : this(providerName, new DotNetOpenAuthWebConsumer(serviceDescription, tokenManager)) { } + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthClient"/> class. + /// </summary> + /// <param name="providerName"> + /// The provider name. + /// </param> + /// <param name="webWorker"> + /// The web worker. + /// </param> + protected OAuthClient(string providerName, IOAuthWebWorker webWorker) { + Requires.NotNull(providerName, "providerName"); + Requires.NotNull(webWorker, "webWorker"); + + this.ProviderName = providerName; + this.WebWorker = webWorker; + } + + #endregion + + #region Public Properties + + /// <summary> + /// Gets the name of the provider which provides authentication service. + /// </summary> + public string ProviderName { get; private set; } + + #endregion + + #region Properties + + /// <summary> + /// Gets the OAuthWebConsumer instance which handles constructing requests to the OAuth providers. + /// </summary> + protected IOAuthWebWorker WebWorker { get; private set; } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <param name="returnUrl"> + /// The return url after users have completed authenticating against external website. + /// </param> + public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) { + Requires.NotNull(returnUrl, "returnUrl"); + Requires.NotNull(context, "context"); + + Uri callback = returnUrl.StripQueryArgumentsWithPrefix("oauth_"); + this.WebWorker.RequestAuthentication(callback); + } + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <returns> + /// An instance of <see cref="AuthenticationResult"/> containing authentication result. + /// </returns> + public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) { + AuthorizedTokenResponse response = this.WebWorker.ProcessUserAuthorization(); + if (response == null) { + return AuthenticationResult.Failed; + } + + AuthenticationResult result = this.VerifyAuthenticationCore(response); + if (result.IsSuccessful && result.ExtraData != null) { + // add the access token to the user data dictionary just in case page developers want to use it + var wrapExtraData = result.ExtraData.IsReadOnly + ? new Dictionary<string, string>(result.ExtraData) + : result.ExtraData; + wrapExtraData["accesstoken"] = response.AccessToken; + + AuthenticationResult wrapResult = new AuthenticationResult( + result.IsSuccessful, + result.Provider, + result.ProviderUserId, + result.UserName, + wrapExtraData); + + result = wrapResult; + } + + return result; + } + + #endregion + + #region Methods + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="response"> + /// The response token returned from service provider + /// </param> + /// <returns> + /// Authentication result + /// </returns> + protected abstract AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response); + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs new file mode 100644 index 0000000..ceaffd4 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------- +// <copyright file="TwitterClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Net; + using System.Xml.Linq; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// Represents a Twitter client + /// </summary> + public class TwitterClient : OAuthClient { + #region Constants and Fields + + /// <summary> + /// The description of Twitter's OAuth protocol URIs for use with their "Sign in with Twitter" feature. + /// </summary> + public static readonly ServiceProviderDescription TwitterServiceDescription = new ServiceProviderDescription { + RequestTokenEndpoint = + new MessageReceivingEndpoint( + "http://twitter.com/oauth/request_token", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + UserAuthorizationEndpoint = + new MessageReceivingEndpoint( + "http://twitter.com/oauth/authenticate", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + AccessTokenEndpoint = + new MessageReceivingEndpoint( + "http://twitter.com/oauth/access_token", + HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, + }; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="TwitterClient"/> class with the specified consumer key and consumer secret. + /// </summary> + /// <param name="consumerKey"> + /// The consumer key. + /// </param> + /// <param name="consumerSecret"> + /// The consumer secret. + /// </param> + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", + Justification = "We can't dispose the object because we still need it through the app lifetime.")] + public TwitterClient(string consumerKey, string consumerSecret) + : base("twitter", TwitterServiceDescription, consumerKey, consumerSecret) { } + + #endregion + + #region Methods + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="response"> + /// The response token returned from service provider + /// </param> + /// <returns> + /// Authentication result + /// </returns> + [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", + Justification = "We don't care if the request for additional data fails.")] + protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response) { + string accessToken = response.AccessToken; + string userId = response.ExtraData["user_id"]; + string userName = response.ExtraData["screen_name"]; + + var profileRequestUrl = new Uri("http://api.twitter.com/1/users/show.xml?user_id=" + + MessagingUtilities.EscapeUriDataStringRfc3986(userId)); + var profileEndpoint = new MessageReceivingEndpoint(profileRequestUrl, HttpDeliveryMethods.GetRequest); + HttpWebRequest request = this.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken); + + var extraData = new Dictionary<string, string>(); + extraData.Add("accesstoken", accessToken); + try { + using (WebResponse profileResponse = request.GetResponse()) { + using (Stream responseStream = profileResponse.GetResponseStream()) { + XDocument document = XDocument.Load(responseStream); + extraData.AddDataIfNotEmpty(document, "name"); + extraData.AddDataIfNotEmpty(document, "location"); + extraData.AddDataIfNotEmpty(document, "description"); + extraData.AddDataIfNotEmpty(document, "url"); + } + } + } catch (Exception) { + // At this point, the authentication is already successful. + // Here we are just trying to get additional data if we can. + // If it fails, no problem. + } + + return new AuthenticationResult( + isSuccessful: true, provider: this.ProviderName, providerUserId: userId, userName: userName, extraData: extraData); + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs new file mode 100644 index 0000000..f4ad20b --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookClient.cs @@ -0,0 +1,148 @@ +//----------------------------------------------------------------------- +// <copyright file="FacebookClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Net; + using System.Web; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// The facebook client. + /// </summary> + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Facebook", Justification = "Brand name")] + public sealed class FacebookClient : OAuth2Client { + #region Constants and Fields + + /// <summary> + /// The authorization endpoint. + /// </summary> + private const string AuthorizationEndpoint = "https://www.facebook.com/dialog/oauth"; + + /// <summary> + /// The token endpoint. + /// </summary> + private const string TokenEndpoint = "https://graph.facebook.com/oauth/access_token"; + + /// <summary> + /// The _app id. + /// </summary> + private readonly string appId; + + /// <summary> + /// The _app secret. + /// </summary> + private readonly string appSecret; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="FacebookClient"/> class. + /// </summary> + /// <param name="appId"> + /// The app id. + /// </param> + /// <param name="appSecret"> + /// The app secret. + /// </param> + public FacebookClient(string appId, string appSecret) + : base("facebook") { + Requires.NotNullOrEmpty(appId, "appId"); + Requires.NotNullOrEmpty(appSecret, "appSecret"); + + this.appId = appId; + this.appSecret = appSecret; + } + + #endregion + + #region Methods + + /// <summary> + /// The get service login url. + /// </summary> + /// <param name="returnUrl"> + /// The return url. + /// </param> + /// <returns>An absolute URI.</returns> + protected override Uri GetServiceLoginUrl(Uri returnUrl) { + // Note: Facebook doesn't like us to url-encode the redirect_uri value + var builder = new UriBuilder(AuthorizationEndpoint); + builder.AppendQueryArgs( + new Dictionary<string, string> { { "client_id", this.appId }, { "redirect_uri", returnUrl.AbsoluteUri }, }); + return builder.Uri; + } + + /// <summary> + /// The get user data. + /// </summary> + /// <param name="accessToken"> + /// The access token. + /// </param> + /// <returns>A dictionary of profile data.</returns> + protected override IDictionary<string, string> GetUserData(string accessToken) { + FacebookGraphData graphData; + var request = + WebRequest.Create( + "https://graph.facebook.com/me?access_token=" + MessagingUtilities.EscapeUriDataStringRfc3986(accessToken)); + using (var response = request.GetResponse()) { + using (var responseStream = response.GetResponseStream()) { + graphData = JsonHelper.Deserialize<FacebookGraphData>(responseStream); + } + } + + // this dictionary must contains + var userData = new Dictionary<string, string>(); + userData.AddItemIfNotEmpty("id", graphData.Id); + userData.AddItemIfNotEmpty("username", graphData.Email); + userData.AddItemIfNotEmpty("name", graphData.Name); + userData.AddItemIfNotEmpty("link", graphData.Link == null ? null : graphData.Link.AbsoluteUri); + userData.AddItemIfNotEmpty("gender", graphData.Gender); + userData.AddItemIfNotEmpty("birthday", graphData.Birthday); + return userData; + } + + /// <summary> + /// Obtains an access token given an authorization code and callback URL. + /// </summary> + /// <param name="returnUrl"> + /// The return url. + /// </param> + /// <param name="authorizationCode"> + /// The authorization code. + /// </param> + /// <returns> + /// The access token. + /// </returns> + protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) { + // Note: Facebook doesn't like us to url-encode the redirect_uri value + var builder = new UriBuilder(TokenEndpoint); + builder.AppendQueryArgs( + new Dictionary<string, string> { + { "client_id", this.appId }, + { "redirect_uri", returnUrl.AbsoluteUri }, + { "client_secret", this.appSecret }, + { "code", authorizationCode }, + }); + + using (WebClient client = new WebClient()) { + string data = client.DownloadString(builder.Uri); + if (string.IsNullOrEmpty(data)) { + return null; + } + + var parsedQueryString = HttpUtility.ParseQueryString(data); + return parsedQueryString["access_token"]; + } + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookGraphData.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookGraphData.cs new file mode 100644 index 0000000..9ad3eff --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/FacebookGraphData.cs @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------- +// <copyright file="FacebookGraphData.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.ComponentModel; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.Serialization; + + /// <summary> + /// Contains data of a Facebook user. + /// </summary> + /// <remarks> + /// Technically, this class doesn't need to be public, but because we want to make it serializable in medium trust, it has to be public. + /// </remarks> + [DataContract] + [EditorBrowsable(EditorBrowsableState.Never)] + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Facebook", Justification = "Brand name")] + public class FacebookGraphData { + #region Public Properties + + /// <summary> + /// Gets or sets the birthday. + /// </summary> + /// <value> The birthday. </value> + [DataMember(Name = "birthday")] + public string Birthday { get; set; } + + /// <summary> + /// Gets or sets the email. + /// </summary> + /// <value> The email. </value> + [DataMember(Name = "email")] + public string Email { get; set; } + + /// <summary> + /// Gets or sets the gender. + /// </summary> + /// <value> The gender. </value> + [DataMember(Name = "gender")] + public string Gender { get; set; } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <value> The id. </value> + [DataMember(Name = "id")] + public string Id { get; set; } + + /// <summary> + /// Gets or sets the link. + /// </summary> + /// <value> The link. </value> + [DataMember(Name = "link")] + public Uri Link { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value> The name. </value> + [DataMember(Name = "name")] + public string Name { get; set; } + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/JsonHelper.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/JsonHelper.cs new file mode 100644 index 0000000..a7ff79e --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/JsonHelper.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------- +// <copyright file="JsonHelper.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.IO; + using System.Runtime.Serialization.Json; + + /// <summary> + /// The json helper. + /// </summary> + internal static class JsonHelper { + #region Public Methods and Operators + + /// <summary> + /// The deserialize. + /// </summary> + /// <param name="stream"> + /// The stream. + /// </param> + /// <typeparam name="T">The type of the value to deserialize.</typeparam> + /// <returns> + /// The deserialized value. + /// </returns> + public static T Deserialize<T>(Stream stream) where T : class { + Requires.NotNull(stream, "stream"); + + var serializer = new DataContractJsonSerializer(typeof(T)); + return (T)serializer.ReadObject(stream); + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2AccessTokenData.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2AccessTokenData.cs new file mode 100644 index 0000000..5da24dd --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2AccessTokenData.cs @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuth2AccessTokenData.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System.Runtime.Serialization; + + /// <summary> + /// Captures the result of an access token request, including an optional refresh token. + /// </summary> + [DataContract] + public class OAuth2AccessTokenData { + #region Public Properties + + /// <summary> + /// Gets or sets the access token. + /// </summary> + /// <value> The access token. </value> + [DataMember(Name = "access_token")] + public string AccessToken { get; set; } + + /// <summary> + /// Gets or sets the refresh token. + /// </summary> + /// <value> The refresh token. </value> + [DataMember(Name = "refresh_token")] + public string RefreshToken { get; set; } + + /// <summary> + /// Gets or sets the scope. + /// </summary> + /// <value> The scope. </value> + [DataMember(Name = "scope")] + public string Scope { get; set; } + + /// <summary> + /// Gets or sets the type of the token. + /// </summary> + /// <value> The type of the token. </value> + [DataMember(Name = "token_type")] + public string TokenType { get; set; } + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs new file mode 100644 index 0000000..016d92e --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/OAuth2Client.cs @@ -0,0 +1,166 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuth2Client.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Web; + + /// <summary> + /// Represents the base class for OAuth 2.0 clients + /// </summary> + public abstract class OAuth2Client : IAuthenticationClient { + #region Constants and Fields + + /// <summary> + /// The provider name. + /// </summary> + private readonly string providerName; + + /// <summary> + /// The return url. + /// </summary> + private Uri returnUrl; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="OAuth2Client"/> class with the specified provider name. + /// </summary> + /// <param name="providerName"> + /// Name of the provider. + /// </param> + protected OAuth2Client(string providerName) { + Requires.NotNull(providerName, "providerName"); + this.providerName = providerName; + } + + #endregion + + #region Public Properties + + /// <summary> + /// Gets the name of the provider which provides authentication service. + /// </summary> + public string ProviderName { + get { + return this.providerName; + } + } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <param name="returnUrl"> + /// The return url after users have completed authenticating against external website. + /// </param> + public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) { + Requires.NotNull(context, "context"); + Requires.NotNull(returnUrl, "returnUrl"); + + this.returnUrl = returnUrl; + + string redirectUrl = this.GetServiceLoginUrl(returnUrl).AbsoluteUri; + context.Response.Redirect(redirectUrl, endResponse: true); + } + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <returns> + /// An instance of <see cref="AuthenticationResult"/> containing authentication result. + /// </returns> + public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) { + Requires.NotNull(context, "context"); + + string code = context.Request.QueryString["code"]; + if (string.IsNullOrEmpty(code)) { + return AuthenticationResult.Failed; + } + + string accessToken = this.QueryAccessToken(this.returnUrl, code); + if (accessToken == null) { + return AuthenticationResult.Failed; + } + + IDictionary<string, string> userData = this.GetUserData(accessToken); + if (userData == null) { + return AuthenticationResult.Failed; + } + + string id = userData["id"]; + string name; + + // Some oAuth providers do not return value for the 'username' attribute. + // In that case, try the 'name' attribute. If it's still unavailable, fall back to 'id' + if (!userData.TryGetValue("username", out name) && !userData.TryGetValue("name", out name)) { + name = id; + } + + // add the access token to the user data dictionary just in case page developers want to use it + userData["accesstoken"] = accessToken; + + return new AuthenticationResult( + isSuccessful: true, provider: this.ProviderName, providerUserId: id, userName: name, extraData: userData); + } + + #endregion + + #region Methods + + /// <summary> + /// Gets the full url pointing to the login page for this client. The url should include the specified return url so that when the login completes, user is redirected back to that url. + /// </summary> + /// <param name="returnUrl"> + /// The return URL. + /// </param> + /// <returns> + /// An absolute URL. + /// </returns> + [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", + Justification = "Login is used more consistently in ASP.Net")] + protected abstract Uri GetServiceLoginUrl(Uri returnUrl); + + /// <summary> + /// Given the access token, gets the logged-in user's data. The returned dictionary must include two keys 'id', and 'username'. + /// </summary> + /// <param name="accessToken"> + /// The access token of the current user. + /// </param> + /// <returns> + /// A dictionary contains key-value pairs of user data + /// </returns> + protected abstract IDictionary<string, string> GetUserData(string accessToken); + + /// <summary> + /// Queries the access token from the specified authorization code. + /// </summary> + /// <param name="returnUrl"> + /// The return URL. + /// </param> + /// <param name="authorizationCode"> + /// The authorization code. + /// </param> + /// <returns> + /// The access token + /// </returns> + protected abstract string QueryAccessToken(Uri returnUrl, string authorizationCode); + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveClient.cs new file mode 100644 index 0000000..5e396a1 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveClient.cs @@ -0,0 +1,166 @@ +//----------------------------------------------------------------------- +// <copyright file="WindowsLiveClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.IO; + using System.Net; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// The windows live client. + /// </summary> + public sealed class WindowsLiveClient : OAuth2Client { + #region Constants and Fields + + /// <summary> + /// The authorization endpoint. + /// </summary> + private const string AuthorizationEndpoint = "https://oauth.live.com/authorize"; + + /// <summary> + /// The token endpoint. + /// </summary> + private const string TokenEndpoint = "https://oauth.live.com/token"; + + /// <summary> + /// The _app id. + /// </summary> + private readonly string appId; + + /// <summary> + /// The _app secret. + /// </summary> + private readonly string appSecret; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="WindowsLiveClient"/> class. + /// </summary> + /// <param name="appId"> + /// The app id. + /// </param> + /// <param name="appSecret"> + /// The app secret. + /// </param> + public WindowsLiveClient(string appId, string appSecret) + : base("windowslive") { + Requires.NotNullOrEmpty(appId, "appId"); + Requires.NotNullOrEmpty(appSecret, "appSecret"); + + this.appId = appId; + this.appSecret = appSecret; + } + + #endregion + + #region Methods + + /// <summary> + /// Gets the full url pointing to the login page for this client. The url should include the specified return url so that when the login completes, user is redirected back to that url. + /// </summary> + /// <param name="returnUrl">The return URL.</param> + /// <returns> + /// An absolute URL. + /// </returns> + protected override Uri GetServiceLoginUrl(Uri returnUrl) { + var builder = new UriBuilder(AuthorizationEndpoint); + builder.AppendQueryArgs( + new Dictionary<string, string> { + { "client_id", this.appId }, + { "scope", "wl.basic" }, + { "response_type", "code" }, + { "redirect_uri", returnUrl.AbsoluteUri }, + }); + + return builder.Uri; + } + + /// <summary> + /// Given the access token, gets the logged-in user's data. The returned dictionary must include two keys 'id', and 'username'. + /// </summary> + /// <param name="accessToken"> + /// The access token of the current user. + /// </param> + /// <returns> + /// A dictionary contains key-value pairs of user data + /// </returns> + protected override IDictionary<string, string> GetUserData(string accessToken) { + WindowsLiveUserData graph; + var request = + WebRequest.Create( + "https://apis.live.net/v5.0/me?access_token=" + MessagingUtilities.EscapeUriDataStringRfc3986(accessToken)); + using (var response = request.GetResponse()) { + using (var responseStream = response.GetResponseStream()) { + graph = JsonHelper.Deserialize<WindowsLiveUserData>(responseStream); + } + } + + var userData = new Dictionary<string, string>(); + userData.AddItemIfNotEmpty("id", graph.Id); + userData.AddItemIfNotEmpty("username", graph.Name); + userData.AddItemIfNotEmpty("name", graph.Name); + userData.AddItemIfNotEmpty("link", graph.Link == null ? null : graph.Link.AbsoluteUri); + userData.AddItemIfNotEmpty("gender", graph.Gender); + userData.AddItemIfNotEmpty("firstname", graph.FirstName); + userData.AddItemIfNotEmpty("lastname", graph.LastName); + return userData; + } + + /// <summary> + /// Queries the access token from the specified authorization code. + /// </summary> + /// <param name="returnUrl"> + /// The return URL. + /// </param> + /// <param name="authorizationCode"> + /// The authorization code. + /// </param> + /// <returns> + /// The query access token. + /// </returns> + protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) { + var entity = + MessagingUtilities.CreateQueryString( + new Dictionary<string, string> { + { "client_id", this.appId }, + { "redirect_uri", returnUrl.AbsoluteUri }, + { "client_secret", this.appSecret }, + { "code", authorizationCode }, + { "grant_type", "authorization_code" }, + }); + + WebRequest tokenRequest = WebRequest.Create(TokenEndpoint); + tokenRequest.ContentType = "application/x-www-form-urlencoded"; + tokenRequest.ContentLength = entity.Length; + tokenRequest.Method = "POST"; + + using (Stream requestStream = tokenRequest.GetRequestStream()) { + var writer = new StreamWriter(requestStream); + writer.Write(entity); + writer.Flush(); + } + + HttpWebResponse tokenResponse = (HttpWebResponse)tokenRequest.GetResponse(); + if (tokenResponse.StatusCode == HttpStatusCode.OK) { + using (Stream responseStream = tokenResponse.GetResponseStream()) { + var tokenData = JsonHelper.Deserialize<OAuth2AccessTokenData>(responseStream); + if (tokenData != null) { + return tokenData.AccessToken; + } + } + } + + return null; + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveUserData.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveUserData.cs new file mode 100644 index 0000000..52192c3 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth2/WindowsLiveUserData.cs @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------- +// <copyright file="WindowsLiveUserData.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.ComponentModel; + using System.Runtime.Serialization; + + /// <summary> + /// Contains data of a Windows Live user. + /// </summary> + /// <remarks> + /// Technically, this class doesn't need to be public, but because we want to make it serializable in medium trust, it has to be public. + /// </remarks> + [DataContract] + [EditorBrowsable(EditorBrowsableState.Never)] + public class WindowsLiveUserData { + #region Public Properties + + /// <summary> + /// Gets or sets the first name. + /// </summary> + /// <value> The first name. </value> + [DataMember(Name = "first_name")] + public string FirstName { get; set; } + + /// <summary> + /// Gets or sets the gender. + /// </summary> + /// <value> The gender. </value> + [DataMember(Name = "gender")] + public string Gender { get; set; } + + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <value> The id. </value> + [DataMember(Name = "id")] + public string Id { get; set; } + + /// <summary> + /// Gets or sets the last name. + /// </summary> + /// <value> The last name. </value> + [DataMember(Name = "last_name")] + public string LastName { get; set; } + + /// <summary> + /// Gets or sets the link. + /// </summary> + /// <value> The link. </value> + [DataMember(Name = "link")] + public Uri Link { get; set; } + + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value> The name. </value> + [DataMember(Name = "name")] + public string Name { get; set; } + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs new file mode 100644 index 0000000..aedcb80 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/GoogleOpenIdClient.cs @@ -0,0 +1,70 @@ +//----------------------------------------------------------------------- +// <copyright file="GoogleOpenIdClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System.Collections.Generic; + using DotNetOpenAuth.OpenId.Extensions.AttributeExchange; + using DotNetOpenAuth.OpenId.RelyingParty; + + /// <summary> + /// Represents Google OpenID client. + /// </summary> + public sealed class GoogleOpenIdClient : OpenIdClient { + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="GoogleOpenIdClient"/> class. + /// </summary> + public GoogleOpenIdClient() + : base("google", WellKnownProviders.Google) { } + + #endregion + + #region Methods + + /// <summary> + /// Gets the extra data obtained from the response message when authentication is successful. + /// </summary> + /// <param name="response"> + /// The response message. + /// </param> + /// <returns>A dictionary of profile data; or null if no data is available.</returns> + protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response) { + FetchResponse fetchResponse = response.GetExtension<FetchResponse>(); + if (fetchResponse != null) { + var extraData = new Dictionary<string, string>(); + extraData.AddItemIfNotEmpty("email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email)); + extraData.AddItemIfNotEmpty( + "country", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.Country)); + extraData.AddItemIfNotEmpty("firstName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.First)); + extraData.AddItemIfNotEmpty("lastName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.Last)); + + return extraData; + } + + return null; + } + + /// <summary> + /// Called just before the authentication request is sent to service provider. + /// </summary> + /// <param name="request"> + /// The request. + /// </param> + protected override void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request) { + // Attribute Exchange extensions + var fetchRequest = new FetchRequest(); + fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.Email); + fetchRequest.Attributes.AddOptional(WellKnownAttributes.Contact.HomeAddress.Country); + fetchRequest.Attributes.AddOptional(WellKnownAttributes.Name.First); + fetchRequest.Attributes.AddOptional(WellKnownAttributes.Name.Last); + + request.AddExtension(fetchRequest); + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs new file mode 100644 index 0000000..6ced1a6 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/OpenIDClient.cs @@ -0,0 +1,156 @@ +//----------------------------------------------------------------------- +// <copyright file="OpenIdClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.RelyingParty; + + /// <summary> + /// Base classes for OpenID clients. + /// </summary> + public class OpenIdClient : IAuthenticationClient { + #region Constants and Fields + + /// <summary> + /// The _openid relaying party. + /// </summary> + private static readonly OpenIdRelyingParty RelyingParty = + new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore()); + + /// <summary> + /// The _provider identifier. + /// </summary> + private readonly Identifier providerIdentifier; + + /// <summary> + /// The _provider name. + /// </summary> + private readonly string providerName; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="OpenIdClient"/> class. + /// </summary> + /// <param name="providerName"> + /// Name of the provider. + /// </param> + /// <param name="providerIdentifier"> + /// The provider identifier, which is the usually the login url of the specified provider. + /// </param> + public OpenIdClient(string providerName, Identifier providerIdentifier) { + Requires.NotNullOrEmpty(providerName, "providerName"); + Requires.NotNull(providerIdentifier, "providerIdentifier"); + + this.providerName = providerName; + this.providerIdentifier = providerIdentifier; + } + + #endregion + + #region Public Properties + + /// <summary> + /// Gets the name of the provider which provides authentication service. + /// </summary> + public string ProviderName { + get { + return this.providerName; + } + } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url. + /// </summary> + /// <param name="context"> + /// The context of the current request. + /// </param> + /// <param name="returnUrl"> + /// The return url after users have completed authenticating against external website. + /// </param> + [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", + Justification = "We don't have a Uri object handy.")] + public virtual void RequestAuthentication(HttpContextBase context, Uri returnUrl) { + Requires.NotNull(returnUrl, "returnUrl"); + + var realm = new Realm(returnUrl.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped)); + IAuthenticationRequest request = RelyingParty.CreateRequest(this.providerIdentifier, realm, returnUrl); + + // give subclasses a chance to modify request message, e.g. add extension attributes, etc. + this.OnBeforeSendingAuthenticationRequest(request); + + request.RedirectToProvider(); + } + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="context"> + /// The context of the current request. + /// </param> + /// <returns> + /// An instance of <see cref="AuthenticationResult"/> containing authentication result. + /// </returns> + public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context) { + IAuthenticationResponse response = RelyingParty.GetResponse(); + if (response == null) { + throw new InvalidOperationException(WebResources.OpenIDFailedToGetResponse); + } + + if (response.Status == AuthenticationStatus.Authenticated) { + string id = response.ClaimedIdentifier; + string username; + + Dictionary<string, string> extraData = this.GetExtraData(response) ?? new Dictionary<string, string>(); + + // try to look up username from the 'username' or 'email' property. If not found, fall back to 'friendly id' + if (!extraData.TryGetValue("username", out username) && !extraData.TryGetValue("email", out username)) { + username = response.FriendlyIdentifierForDisplay; + } + + return new AuthenticationResult(true, this.ProviderName, id, username, extraData); + } + + return AuthenticationResult.Failed; + } + + #endregion + + #region Methods + + /// <summary> + /// Gets the extra data obtained from the response message when authentication is successful. + /// </summary> + /// <param name="response"> + /// The response message. + /// </param> + /// <returns>Always null.</returns> + protected virtual Dictionary<string, string> GetExtraData(IAuthenticationResponse response) { + return null; + } + + /// <summary> + /// Called just before the authentication request is sent to service provider. + /// </summary> + /// <param name="request"> + /// The request. + /// </param> + protected virtual void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request) { } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs new file mode 100644 index 0000000..bd420fc --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Clients/OpenID/YahooOpenIdClient.cs @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------- +// <copyright file="YahooOpenIdClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet.Clients { + using System.Collections.Generic; + using DotNetOpenAuth.OpenId.Extensions.AttributeExchange; + using DotNetOpenAuth.OpenId.RelyingParty; + + /// <summary> + /// The yahoo open id client. + /// </summary> + public sealed class YahooOpenIdClient : OpenIdClient { + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="YahooOpenIdClient"/> class. + /// </summary> + public YahooOpenIdClient() + : base("yahoo", WellKnownProviders.Yahoo) { } + + #endregion + + #region Methods + + /// <summary> + /// Gets the extra data obtained from the response message when authentication is successful. + /// </summary> + /// <param name="response"> + /// The response message. + /// </param> + /// <returns>A dictionary of profile data; or null if no data is available.</returns> + protected override Dictionary<string, string> GetExtraData(IAuthenticationResponse response) { + FetchResponse fetchResponse = response.GetExtension<FetchResponse>(); + if (fetchResponse != null) { + var extraData = new Dictionary<string, string>(); + extraData.AddItemIfNotEmpty("email", fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email)); + extraData.AddItemIfNotEmpty("fullName", fetchResponse.GetAttributeValue(WellKnownAttributes.Name.FullName)); + + return extraData; + } + + return null; + } + + /// <summary> + /// Called just before the authentication request is sent to service provider. + /// </summary> + /// <param name="request"> + /// The request. + /// </param> + protected override void OnBeforeSendingAuthenticationRequest(IAuthenticationRequest request) { + // Attribute Exchange extensions + var fetchRequest = new FetchRequest(); + fetchRequest.Attributes.AddRequired(WellKnownAttributes.Contact.Email); + fetchRequest.Attributes.AddOptional(WellKnownAttributes.Name.FullName); + + request.AddExtension(fetchRequest); + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj b/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj new file mode 100644 index 0000000..f28f96f --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/DotNetOpenAuth.AspNet.csproj @@ -0,0 +1,104 @@ +<?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> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{51835086-9611-4C53-819B-F2D5C9320873}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>DotNetOpenAuth.AspNet</RootNamespace> + <AssemblyName>DotNetOpenAuth.AspNet</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <CodeAnalysisRuleSet>ExtendedDesignGuidelineRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\bin\v4.0\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\bin\v4.0\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + </PropertyGroup> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" /> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.Product.props" /> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Runtime.Serialization" /> + <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="AuthenticationResult.cs" /> + <Compile Include="Clients\DictionaryExtensions.cs" /> + <Compile Include="IAuthenticationClient.cs" /> + <Compile Include="Clients\OAuth2\FacebookClient.cs" /> + <Compile Include="Clients\OAuth2\FacebookGraphData.cs" /> + <Compile Include="Clients\OAuth2\JsonHelper.cs" /> + <Compile Include="Clients\OAuth2\OAuth2AccessTokenData.cs" /> + <Compile Include="Clients\OAuth2\OAuth2Client.cs" /> + <Compile Include="Clients\OAuth2\WindowsLiveClient.cs" /> + <Compile Include="Clients\OAuth2\WindowsLiveUserData.cs" /> + <Compile Include="Clients\OAuth\DotNetOpenAuthWebConsumer.cs" /> + <Compile Include="Clients\OAuth\InMemoryOAuthTokenManager.cs" /> + <Compile Include="Clients\OAuth\IOAuthWebWorker.cs" /> + <Compile Include="Clients\OAuth\LinkedInClient.cs" /> + <Compile Include="Clients\OAuth\OAuthClient.cs" /> + <Compile Include="Clients\OAuth\TwitterClient.cs" /> + <Compile Include="Clients\OpenID\GoogleOpenIdClient.cs" /> + <Compile Include="Clients\OpenID\OpenIdClient.cs" /> + <Compile Include="Clients\OpenID\YahooOpenIdClient.cs" /> + <Compile Include="UriHelper.cs" /> + <Compile Include="IOpenAuthDataProvider.cs" /> + <Compile Include="OpenAuthAuthenticationTicketHelper.cs" /> + <Compile Include="OpenAuthSecurityManager.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="WebResources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>WebResources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="WebResources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>WebResources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj"> + <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> + <Name>DotNetOpenAuth.Core</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth.Consumer\DotNetOpenAuth.OAuth.Consumer.csproj"> + <Project>{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}</Project> + <Name>DotNetOpenAuth.OAuth.Consumer</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj"> + <Project>{A288FCC8-6FCF-46DA-A45E-5F9281556361}</Project> + <Name>DotNetOpenAuth.OAuth</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OpenId.RelyingParty\DotNetOpenAuth.OpenId.RelyingParty.csproj"> + <Project>{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}</Project> + <Name>DotNetOpenAuth.OpenId.RelyingParty</Name> + </ProjectReference> + <ProjectReference Include="..\DotNetOpenAuth.OpenId\DotNetOpenAuth.OpenId.csproj"> + <Project>{3896A32A-E876-4C23-B9B8-78E17D134CD3}</Project> + <Name>DotNetOpenAuth.OpenId</Name> + </ProjectReference> + </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.AspNet/IAuthenticationClient.cs b/src/DotNetOpenAuth.AspNet/IAuthenticationClient.cs new file mode 100644 index 0000000..4d9acde --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/IAuthenticationClient.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------- +// <copyright file="IAuthenticationClient.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + using System; + using System.Web; + + /// <summary> + /// Represents a client which can authenticate users via an external website/provider. + /// </summary> + public interface IAuthenticationClient { + /// <summary> + /// Gets the name of the provider which provides authentication service. + /// </summary> + string ProviderName { get; } + + /// <summary> + /// Attempts to authenticate users by forwarding them to an external website, and upon succcess or failure, redirect users back to the specified url. + /// </summary> + /// <param name="context"> + /// The context of the current request. + /// </param> + /// <param name="returnUrl"> + /// The return url after users have completed authenticating against external website. + /// </param> + void RequestAuthentication(HttpContextBase context, Uri returnUrl); + + /// <summary> + /// Check if authentication succeeded after user is redirected back from the service provider. + /// </summary> + /// <param name="context"> + /// The context of the current request. + /// </param> + /// <returns> + /// An instance of <see cref="AuthenticationResult"/> containing authentication result. + /// </returns> + AuthenticationResult VerifyAuthentication(HttpContextBase context); + } +} diff --git a/src/DotNetOpenAuth.AspNet/IOpenAuthDataProvider.cs b/src/DotNetOpenAuth.AspNet/IOpenAuthDataProvider.cs new file mode 100644 index 0000000..12d929d --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/IOpenAuthDataProvider.cs @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------- +// <copyright file="IOpenAuthDataProvider.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + /// <summary> + /// Common methods available on identity issuers. + /// </summary> + public interface IOpenAuthDataProvider { + #region Public Methods and Operators + + /// <summary> + /// Get a user name from an identity provider and their own assigned user ID. + /// </summary> + /// <param name="openAuthProvider"> + /// The identity provider. + /// </param> + /// <param name="openAuthId"> + /// The issuer's ID for the user. + /// </param> + /// <returns> + /// The username of the user. + /// </returns> + string GetUserNameFromOpenAuth(string openAuthProvider, string openAuthId); + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/OpenAuthAuthenticationTicketHelper.cs b/src/DotNetOpenAuth.AspNet/OpenAuthAuthenticationTicketHelper.cs new file mode 100644 index 0000000..3fc3a21 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/OpenAuthAuthenticationTicketHelper.cs @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------- +// <copyright file="OpenAuthAuthenticationTicketHelper.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + using System; + using System.Diagnostics; + using System.Web; + using System.Web.Security; + + /// <summary> + /// Helper methods for setting and retrieving a custom forms authentication ticket for delegation protocols. + /// </summary> + internal static class OpenAuthAuthenticationTicketHelper { + #region Constants and Fields + + /// <summary> + /// The open auth cookie token. + /// </summary> + private const string OpenAuthCookieToken = "OAuth"; + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Checks whether the specified HTTP request comes from an authenticated user. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <returns>True if the reuest is authenticated; false otherwise.</returns> + public static bool IsValidAuthenticationTicket(HttpContextBase context) { + HttpCookie cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName]; + if (cookie == null) { + return false; + } + + string encryptedCookieData = cookie.Value; + if (string.IsNullOrEmpty(encryptedCookieData)) { + return false; + } + + try { + FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(encryptedCookieData); + return authTicket != null && !authTicket.Expired && authTicket.UserData == OpenAuthCookieToken; + } catch (ArgumentException) { + return false; + } + } + + /// <summary> + /// Adds an authentication cookie to the user agent in the next HTTP response. + /// </summary> + /// <param name="context"> + /// The context. + /// </param> + /// <param name="userName"> + /// The user name. + /// </param> + /// <param name="createPersistentCookie"> + /// A value indicating whether the cookie should persist across sessions. + /// </param> + public static void SetAuthenticationTicket(HttpContextBase context, string userName, bool createPersistentCookie) { + if (!context.Request.IsSecureConnection && FormsAuthentication.RequireSSL) { + throw new HttpException(WebResources.ConnectionNotSecure); + } + + HttpCookie cookie = GetAuthCookie(userName, createPersistentCookie); + context.Response.Cookies.Add(cookie); + } + + #endregion + + #region Methods + + /// <summary> + /// Creates an HTTP authentication cookie. + /// </summary> + /// <param name="userName"> + /// The user name. + /// </param> + /// <param name="createPersistentCookie"> + /// A value indicating whether the cookie should last across sessions. + /// </param> + /// <returns>An authentication cookie.</returns> + private static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie) { + Requires.NotNullOrEmpty(userName, "userName"); + + var ticket = new FormsAuthenticationTicket( + /* version */ + 2, + userName, + DateTime.Now, + DateTime.Now.Add(FormsAuthentication.Timeout), + createPersistentCookie, + OpenAuthCookieToken, + FormsAuthentication.FormsCookiePath); + + string encryptedTicket = FormsAuthentication.Encrypt(ticket); + if (encryptedTicket == null || encryptedTicket.Length < 1) { + throw new HttpException(WebResources.FailedToEncryptTicket); + } + + var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) { + HttpOnly = true, + Path = FormsAuthentication.FormsCookiePath, + Secure = FormsAuthentication.RequireSSL + }; + + if (FormsAuthentication.CookieDomain != null) { + cookie.Domain = FormsAuthentication.CookieDomain; + } + + if (ticket.IsPersistent) { + cookie.Expires = ticket.Expiration; + } + + return cookie; + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs new file mode 100644 index 0000000..463f056 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs @@ -0,0 +1,173 @@ +//----------------------------------------------------------------------- +// <copyright file="OpenAuthSecurityManager.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + using System; + using System.Diagnostics.CodeAnalysis; + using System.Web; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// Manage authenticating with an external OAuth or OpenID provider + /// </summary> + public class OpenAuthSecurityManager { + #region Constants and Fields + + /// <summary> + /// The provider query string name. + /// </summary> + private const string ProviderQueryStringName = "__provider__"; + + /// <summary> + /// The _authentication provider. + /// </summary> + private readonly IAuthenticationClient authenticationProvider; + + /// <summary> + /// The _data provider. + /// </summary> + private readonly IOpenAuthDataProvider dataProvider; + + /// <summary> + /// The _request context. + /// </summary> + private readonly HttpContextBase requestContext; + + #endregion + + #region Constructors and Destructors + + /// <summary> + /// Initializes a new instance of the <see cref="OpenAuthSecurityManager"/> class. + /// </summary> + /// <param name="requestContext"> + /// The request context. + /// </param> + public OpenAuthSecurityManager(HttpContextBase requestContext) + : this(requestContext, provider: null, dataProvider: null) { } + + /// <summary> + /// Initializes a new instance of the <see cref="OpenAuthSecurityManager"/> class. + /// </summary> + /// <param name="requestContext"> + /// The request context. + /// </param> + /// <param name="provider"> + /// The provider. + /// </param> + /// <param name="dataProvider"> + /// The data provider. + /// </param> + public OpenAuthSecurityManager( + HttpContextBase requestContext, IAuthenticationClient provider, IOpenAuthDataProvider dataProvider) { + if (requestContext == null) { + throw new ArgumentNullException("requestContext"); + } + + this.requestContext = requestContext; + this.dataProvider = dataProvider; + this.authenticationProvider = provider; + } + + #endregion + + #region Public Properties + + /// <summary> + /// Gets a value indicating whether IsAuthenticatedWithOpenAuth. + /// </summary> + public bool IsAuthenticatedWithOpenAuth { + get { + return this.requestContext.Request.IsAuthenticated + && OpenAuthAuthenticationTicketHelper.IsValidAuthenticationTicket(this.requestContext); + } + } + + #endregion + + #region Public Methods and Operators + + /// <summary> + /// Gets the provider that is responding to an authentication request. + /// </summary> + /// <param name="context"> + /// The HTTP request context. + /// </param> + /// <returns> + /// The provider name, if one is available. + /// </returns> + public static string GetProviderName(HttpContextBase context) { + return context.Request.QueryString[ProviderQueryStringName]; + } + + /// <summary> + /// Checks if the specified provider user id represents a valid account. If it does, log user in. + /// </summary> + /// <param name="providerUserId"> + /// The provider user id. + /// </param> + /// <param name="createPersistentCookie"> + /// if set to <c>true</c> create persistent cookie. + /// </param> + /// <returns> + /// <c>true</c> if the login is successful. + /// </returns> + [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "Login", + Justification = "Login is used more consistently in ASP.Net")] + public bool Login(string providerUserId, bool createPersistentCookie) { + string userName = this.dataProvider.GetUserNameFromOpenAuth( + this.authenticationProvider.ProviderName, providerUserId); + if (string.IsNullOrEmpty(userName)) { + return false; + } + + OpenAuthAuthenticationTicketHelper.SetAuthenticationTicket(this.requestContext, userName, createPersistentCookie); + return true; + } + + /// <summary> + /// Requests the specified provider to start the authentication by directing users to an external website + /// </summary> + /// <param name="returnUrl"> + /// The return url after user is authenticated. + /// </param> + public void RequestAuthentication(string returnUrl) { + // convert returnUrl to an absolute path + Uri uri; + if (!string.IsNullOrEmpty(returnUrl)) { + uri = UriHelper.ConvertToAbsoluteUri(returnUrl, this.requestContext); + } else { + uri = this.requestContext.Request.GetPublicFacingUrl(); + } + + // attach the provider parameter so that we know which provider initiated + // the login when user is redirected back to this page + uri = uri.AttachQueryStringParameter(ProviderQueryStringName, this.authenticationProvider.ProviderName); + this.authenticationProvider.RequestAuthentication(this.requestContext, uri); + } + + /// <summary> + /// Checks if user is successfully authenticated when user is redirected back to this user. + /// </summary> + /// <returns>The result of the authentication.</returns> + public AuthenticationResult VerifyAuthentication() { + AuthenticationResult result = this.authenticationProvider.VerifyAuthentication(this.requestContext); + if (!result.IsSuccessful) { + // if the result is a Failed result, creates a new Failed response which has providerName info. + result = new AuthenticationResult( + isSuccessful: false, + provider: this.authenticationProvider.ProviderName, + providerUserId: null, + userName: null, + extraData: null); + } + + return result; + } + + #endregion + } +} diff --git a/src/DotNetOpenAuth.AspNet/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.AspNet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..15b7d9e --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------- +// <copyright file="AssemblyInfo.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +using System; +using System.Reflection; +using System.Resources; +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.AspNet")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("DotNetOpenAuth.AspNet")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en-US")] +[assembly: CLSCompliant(true)] + +// 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("c89b7e57-2735-4407-bcb9-dfe9bb9493a2")] + +#if StrongNameSigned + +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +#else +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test")] +#endif diff --git a/src/DotNetOpenAuth.AspNet/UriHelper.cs b/src/DotNetOpenAuth.AspNet/UriHelper.cs new file mode 100644 index 0000000..602f00c --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/UriHelper.cs @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------- +// <copyright file="UriHelper.cs" company="Microsoft"> +// Copyright (c) Microsoft. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.AspNet { + using System; + using System.Text.RegularExpressions; + using System.Web; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// The uri helper. + /// </summary> + internal static class UriHelper { + /// <summary> + /// The attach query string parameter. + /// </summary> + /// <param name="url"> + /// The url. + /// </param> + /// <param name="parameterName"> + /// The parameter name. + /// </param> + /// <param name="parameterValue"> + /// The parameter value. + /// </param> + /// <returns>An absolute URI.</returns> + public static Uri AttachQueryStringParameter(this Uri url, string parameterName, string parameterValue) { + UriBuilder builder = new UriBuilder(url); + string query = builder.Query; + if (query.Length > 1) { + // remove the '?' character in front of the query string + query = query.Substring(1); + } + + string parameterPrefix = parameterName + "="; + + string encodedParameterValue = Uri.EscapeDataString(parameterValue); + + string newQuery = Regex.Replace(query, parameterPrefix + "[^\\&]*", parameterPrefix + encodedParameterValue); + if (newQuery == query) { + if (newQuery.Length > 0) { + newQuery += "&"; + } + + newQuery = newQuery + parameterPrefix + encodedParameterValue; + } + + builder.Query = newQuery; + + return builder.Uri; + } + + /// <summary> + /// Converts an app-relative url, e.g. ~/Content/Return.cshtml, to a full-blown url, e.g. http://mysite.com/Content/Return.cshtml + /// </summary> + /// <param name="returnUrl"> + /// The return URL. + /// </param> + /// <param name="context"> + /// The context. + /// </param> + /// <returns>An absolute URI.</returns> + public static Uri ConvertToAbsoluteUri(string returnUrl, HttpContextBase context) { + if (Uri.IsWellFormedUriString(returnUrl, UriKind.Absolute)) { + return new Uri(returnUrl, UriKind.Absolute); + } + + if (!VirtualPathUtility.IsAbsolute(returnUrl)) { + returnUrl = VirtualPathUtility.ToAbsolute(returnUrl); + } + + Uri publicUrl = context.Request.GetPublicFacingUrl(); + return new Uri(publicUrl, returnUrl); + } + } +} diff --git a/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs b/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs new file mode 100644 index 0000000..23a51be --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/WebResources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.261 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace DotNetOpenAuth.AspNet { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class WebResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal WebResources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.AspNet.WebResources", typeof(WebResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to A setting in web.config requires a secure connection for this request but the current connection is not secured.. + /// </summary> + internal static string ConnectionNotSecure { + get { + return ResourceManager.GetString("ConnectionNotSecure", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Unable to encrypt the authentication ticket.. + /// </summary> + internal static string FailedToEncryptTicket { + get { + return ResourceManager.GetString("FailedToEncryptTicket", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to An OAuth data provider has already been registered for this application.. + /// </summary> + internal static string OAuthDataProviderRegistered { + get { + return ResourceManager.GetString("OAuthDataProviderRegistered", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Failed to obtain the authentication response from service provider.. + /// </summary> + internal static string OpenIDFailedToGetResponse { + get { + return ResourceManager.GetString("OpenIDFailedToGetResponse", resourceCulture); + } + } + } +} diff --git a/src/DotNetOpenAuth.AspNet/WebResources.resx b/src/DotNetOpenAuth.AspNet/WebResources.resx new file mode 100644 index 0000000..321c097 --- /dev/null +++ b/src/DotNetOpenAuth.AspNet/WebResources.resx @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="ConnectionNotSecure" xml:space="preserve"> + <value>A setting in web.config requires a secure connection for this request but the current connection is not secured.</value> + </data> + <data name="FailedToEncryptTicket" xml:space="preserve"> + <value>Unable to encrypt the authentication ticket.</value> + </data> + <data name="OAuthDataProviderRegistered" xml:space="preserve"> + <value>An OAuth data provider has already been registered for this application.</value> + </data> + <data name="OpenIDFailedToGetResponse" xml:space="preserve"> + <value>Failed to obtain the authentication response from service provider.</value> + </data> +</root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln index ddf80bd..76f9103 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln @@ -29,11 +29,29 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{D49E2011-0E1C-4AB5-9887-BD1D42266503}" ProjectSection(SolutionItems) = preProject + ..\..\nuget\DotNetOpenAuth.AspNet.nuspec = ..\..\nuget\DotNetOpenAuth.AspNet.nuspec ..\..\nuget\DotNetOpenAuth.Core.nuspec = ..\..\nuget\DotNetOpenAuth.Core.nuspec + ..\..\nuget\DotNetOpenAuth.Core.UI.nuspec = ..\..\nuget\DotNetOpenAuth.Core.UI.nuspec + ..\..\nuget\DotNetOpenAuth.InfoCard.nuspec = ..\..\nuget\DotNetOpenAuth.InfoCard.nuspec + ..\..\nuget\DotNetOpenAuth.InfoCard.UI.nuspec = ..\..\nuget\DotNetOpenAuth.InfoCard.UI.nuspec + ..\..\nuget\DotNetOpenAuth.nuspec = ..\..\nuget\DotNetOpenAuth.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth.Common.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth.Common.nuspec ..\..\nuget\DotNetOpenAuth.OAuth.Consumer.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth.Consumer.nuspec ..\..\nuget\DotNetOpenAuth.OAuth.Core.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth.Core.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth.ServiceProvider.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth.ServiceProvider.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth2.AuthorizationServer.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth2.AuthorizationServer.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth2.Client.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth2.Client.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth2.Client.UI.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth2.Client.UI.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth2.Core.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth2.Core.nuspec + ..\..\nuget\DotNetOpenAuth.OAuth2.ResourceServer.nuspec = ..\..\nuget\DotNetOpenAuth.OAuth2.ResourceServer.nuspec ..\..\nuget\DotNetOpenAuth.OpenId.Core.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.Core.nuspec + ..\..\nuget\DotNetOpenAuth.OpenId.Core.UI.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.Core.UI.nuspec + ..\..\nuget\DotNetOpenAuth.OpenId.Provider.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.Provider.nuspec + ..\..\nuget\DotNetOpenAuth.OpenId.Provider.UI.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.Provider.UI.nuspec ..\..\nuget\DotNetOpenAuth.OpenId.RelyingParty.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.RelyingParty.nuspec + ..\..\nuget\DotNetOpenAuth.OpenId.RelyingParty.UI.nuspec = ..\..\nuget\DotNetOpenAuth.OpenId.RelyingParty.UI.nuspec + ..\..\nuget\DotNetOpenAuth.OpenIdInfoCard.UI.nuspec = ..\..\nuget\DotNetOpenAuth.OpenIdInfoCard.UI.nuspec + ..\..\nuget\DotNetOpenAuth.OpenIdOAuth.nuspec = ..\..\nuget\DotNetOpenAuth.OpenIdOAuth.nuspec ..\..\nuget\DotNetOpenAuth.Ultimate.nuspec = ..\..\nuget\DotNetOpenAuth.Ultimate.nuspec ..\..\nuget\nuget.proj = ..\..\nuget\nuget.proj EndProjectSection diff --git a/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs index 50bc89f..05976ea 100644 --- a/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs +++ b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs @@ -29,6 +29,30 @@ namespace DotNetOpenAuth.BuildTasks { public string SimpleVersion { get; private set; } /// <summary> + /// Gets or sets the major.minor version string. + /// </summary> + /// <value> + /// The x.y string (no build number or revision number). + /// </value> + [Output] + public string MajorMinorVersion { get; set; } + + /// <summary> + /// Gets or sets the prerelease version, or empty if this is a final release. + /// </summary> + /// <value> + /// The prerelease version. + /// </value> + [Output] + public string PrereleaseVersion { get; set; } + + /// <summary> + /// Gets or sets the version string to use for NuGet packages containing OAuth 2 components. + /// </summary> + [Output] + public string OAuth2PackagesVersion { get; set; } + + /// <summary> /// Gets the Git revision control commit id for HEAD (the current source code version). /// </summary> [Output] @@ -53,8 +77,13 @@ namespace DotNetOpenAuth.BuildTasks { public override bool Execute() { try { - Version typedVersion = ReadVersionFromFile(); + Version typedVersion; + string prerelease, oauth2PackagesVersion; + this.ReadVersionFromFile(out typedVersion, out prerelease, out oauth2PackagesVersion); + this.PrereleaseVersion = prerelease; + this.OAuth2PackagesVersion = oauth2PackagesVersion; this.SimpleVersion = typedVersion.ToString(); + this.MajorMinorVersion = new Version(typedVersion.Major, typedVersion.Minor).ToString(); this.BuildNumber = this.CalculateJDate(DateTime.Now); var fullVersion = new Version(typedVersion.Major, typedVersion.Minor, typedVersion.Build, this.BuildNumber); @@ -127,10 +156,21 @@ namespace DotNetOpenAuth.BuildTasks { return commitId.Trim(); } - private Version ReadVersionFromFile() { + private void ReadVersionFromFile(out Version typedVersion, out string prereleaseVersion, out string oauth2PackagesVersion) { string[] lines = File.ReadAllLines(VersionFile); string versionLine = lines[0]; - return new Version(versionLine); + prereleaseVersion = lines.Length >= 2 ? lines[1] : null; + oauth2PackagesVersion = lines.Length >= 3 ? lines[2] : null; + if (!String.IsNullOrEmpty(prereleaseVersion)) { + if (!prereleaseVersion.StartsWith("-")) { + // SemVer requires that prerelease suffixes begin with a hyphen, so add one if it's missing. + prereleaseVersion = "-" + prereleaseVersion; + } + + this.VerifyValidPrereleaseVersion(prereleaseVersion); + } + + typedVersion = new Version(versionLine); } private int CalculateJDate(DateTime date) { @@ -140,5 +180,17 @@ namespace DotNetOpenAuth.BuildTasks { int jdate = yearLastDigit * 1000 + dayOfYear; return jdate; } + + private void VerifyValidPrereleaseVersion(string prerelease) { + if (prerelease[0] != '-') { + throw new ArgumentOutOfRangeException("The prerelease string must begin with a hyphen."); + } + + for (int i = 1; i < prerelease.Length; i++) { + if (!char.IsLetterOrDigit(prerelease[i])) { + throw new ArgumentOutOfRangeException("The prerelease string must be alphanumeric."); + } + } + } } } diff --git a/src/DotNetOpenAuth.Core/Assumes.cs b/src/DotNetOpenAuth.Core/Assumes.cs index b61fbd4..f29f09f 100644 --- a/src/DotNetOpenAuth.Core/Assumes.cs +++ b/src/DotNetOpenAuth.Core/Assumes.cs @@ -12,6 +12,7 @@ namespace DotNetOpenAuth { using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; + using System.Runtime.Serialization; using System.Text; /// <summary> @@ -39,7 +40,7 @@ namespace DotNetOpenAuth { [Pure, DebuggerStepThrough] internal static void True(bool condition, string unformattedMessage, params object[] args) { if (!condition) { - Fail(String.Format(CultureInfo.CurrentCulture, unformattedMessage, args)); + Fail(string.Format(CultureInfo.CurrentCulture, unformattedMessage, args)); } } @@ -84,8 +85,8 @@ namespace DotNetOpenAuth { /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception> /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception> protected InternalErrorException( - System.Runtime.Serialization.SerializationInfo info, - System.Runtime.Serialization.StreamingContext context) + SerializationInfo info, + StreamingContext context) : base(info, context) { } } diff --git a/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj b/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj index 9b8a613..c46e6b8 100644 --- a/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj +++ b/src/DotNetOpenAuth.Core/DotNetOpenAuth.Core.csproj @@ -28,10 +28,11 @@ <Compile Include="Messaging\CachedDirectWebResponse.cs" /> <Compile Include="Messaging\ChannelContract.cs" /> <Compile Include="Messaging\DataBagFormatterBase.cs" /> + <Compile Include="Messaging\HttpRequestHeaders.cs" /> <Compile Include="Messaging\IHttpIndirectResponse.cs" /> <Compile Include="Messaging\IMessageOriginalPayload.cs" /> <Compile Include="Messaging\DirectWebRequestOptions.cs" /> - <Compile Include="Messaging\EnumerableCache.cs" /> + <Compile Include="Messaging\EnumerableCacheExtensions.cs" /> <Compile Include="Messaging\HostErrorException.cs" /> <Compile Include="Messaging\IHttpDirectResponse.cs" /> <Compile Include="Messaging\IExtensionMessage.cs" /> @@ -127,6 +128,7 @@ <Compile Include="Loggers\NoOpLogger.cs" /> <Compile Include="Loggers\TraceLogger.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Messaging\ReadOnlyDictionary.cs" /> <Compile Include="Reporting.cs" /> <Compile Include="Requires.cs" /> <Compile Include="Strings.Designer.cs"> diff --git a/src/DotNetOpenAuth.Core/Loggers/ILog.cs b/src/DotNetOpenAuth.Core/Loggers/ILog.cs index 8094296..e801b2a 100644 --- a/src/DotNetOpenAuth.Core/Loggers/ILog.cs +++ b/src/DotNetOpenAuth.Core/Loggers/ILog.cs @@ -122,8 +122,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="args">An Object array containing zero or more objects to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -143,8 +143,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg0">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -165,8 +165,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg1">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -188,8 +188,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg2">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -253,8 +253,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="args">An Object array containing zero or more objects to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -274,8 +274,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg0">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -296,8 +296,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg1">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -319,8 +319,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg2">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -384,8 +384,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="args">An Object array containing zero or more objects to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -405,8 +405,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg0">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -427,8 +427,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg1">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -450,8 +450,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg2">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -515,8 +515,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="args">An Object array containing zero or more objects to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -536,8 +536,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg0">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -558,8 +558,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg1">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -581,8 +581,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg2">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -646,8 +646,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="args">An Object array containing zero or more objects to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -667,8 +667,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg0">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -689,8 +689,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg1">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> @@ -712,8 +712,8 @@ namespace DotNetOpenAuth.Loggers /// <param name="arg2">An Object to format</param> /// <remarks> /// <para> - /// The message is formatted using the <c>String.Format</c> method. See - /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior + /// The message is formatted using the <c>string.Format</c> method. See + /// <see cref="string.Format(string, object[])"/> for details of the syntax of the format string and the behavior /// of the formatting. /// </para> /// <para> diff --git a/src/DotNetOpenAuth.Core/Messaging/Channel.cs b/src/DotNetOpenAuth.Core/Messaging/Channel.cs index 26a8179..16e39d3 100644 --- a/src/DotNetOpenAuth.Core/Messaging/Channel.cs +++ b/src/DotNetOpenAuth.Core/Messaging/Channel.cs @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Messaging { /// <summary> /// The HTML that should be returned to the user agent as part of a 301 Redirect. /// </summary> - /// <value>A string that should be used as the first argument to String.Format, where the {0} should be replaced with the URL to redirect to.</value> + /// <value>A string that should be used as the first argument to string.Format, where the {0} should be replaced with the URL to redirect to.</value> private const string RedirectResponseBodyFormat = @"<html><head><title>Object moved</title></head><body> <h2>Object moved to <a href=""{0}"">here</a>.</h2> </body></html>"; @@ -409,7 +409,7 @@ namespace DotNetOpenAuth.Messaging { /// <returns>True if the expected message was recognized and deserialized. False otherwise.</returns> /// <exception cref="InvalidOperationException">Thrown when <see cref="HttpContext.Current"/> is null.</exception> /// <exception cref="ProtocolException">Thrown when a request message of an unexpected type is received.</exception> - public bool TryReadFromRequest<TRequest>(HttpRequestInfo httpRequest, out TRequest request) + public bool TryReadFromRequest<TRequest>(HttpRequestBase httpRequest, out TRequest request) where TRequest : class, IProtocolMessage { Requires.NotNull(httpRequest, "httpRequest"); Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<TRequest>(out request) != null)); @@ -450,7 +450,7 @@ namespace DotNetOpenAuth.Messaging { /// <returns>The deserialized message. Never null.</returns> /// <exception cref="ProtocolException">Thrown if the expected message was not recognized in the response.</exception> [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This returns and verifies the appropriate message type.")] - public TRequest ReadFromRequest<TRequest>(HttpRequestInfo httpRequest) + public TRequest ReadFromRequest<TRequest>(HttpRequestBase httpRequest) where TRequest : class, IProtocolMessage { Requires.NotNull(httpRequest, "httpRequest"); TRequest request; @@ -466,11 +466,11 @@ namespace DotNetOpenAuth.Messaging { /// </summary> /// <param name="httpRequest">The request to search for an embedded message.</param> /// <returns>The deserialized message, if one is found. Null otherwise.</returns> - public IDirectedProtocolMessage ReadFromRequest(HttpRequestInfo httpRequest) { + public IDirectedProtocolMessage ReadFromRequest(HttpRequestBase httpRequest) { Requires.NotNull(httpRequest, "httpRequest"); - if (Logger.Channel.IsInfoEnabled && httpRequest.UrlBeforeRewriting != null) { - Logger.Channel.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.UrlBeforeRewriting.AbsoluteUri); + if (Logger.Channel.IsInfoEnabled && httpRequest.GetPublicFacingUrl() != null) { + Logger.Channel.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.GetPublicFacingUrl().AbsoluteUri); } IDirectedProtocolMessage requestMessage = this.ReadFromRequestCore(httpRequest); if (requestMessage != null) { @@ -599,6 +599,16 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Gets the HTTP context for the current HTTP request. + /// </summary> + /// <returns>An HttpContextBase instance.</returns> + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Allocates memory")] + protected internal virtual HttpContextBase GetHttpContext() { + Requires.ValidState(HttpContext.Current != null, MessagingStrings.HttpContextRequired); + return new HttpContextWrapper(HttpContext.Current); + } + + /// <summary> /// Gets the current HTTP request being processed. /// </summary> /// <returns>The HttpRequestInfo for the current request.</returns> @@ -607,16 +617,13 @@ namespace DotNetOpenAuth.Messaging { /// </remarks> /// <exception cref="InvalidOperationException">Thrown if <see cref="HttpContext.Current">HttpContext.Current</see> == <c>null</c>.</exception> [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Costly call should not be a property.")] - protected internal virtual HttpRequestInfo GetRequestFromContext() { + protected internal virtual HttpRequestBase GetRequestFromContext() { Requires.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired); - Contract.Ensures(Contract.Result<HttpRequestInfo>() != null); - Contract.Ensures(Contract.Result<HttpRequestInfo>().Url != null); - Contract.Ensures(Contract.Result<HttpRequestInfo>().RawUrl != null); - Contract.Ensures(Contract.Result<HttpRequestInfo>().UrlBeforeRewriting != null); + Contract.Ensures(Contract.Result<HttpRequestBase>() != null); Contract.Assume(HttpContext.Current.Request.Url != null); Contract.Assume(HttpContext.Current.Request.RawUrl != null); - return new HttpRequestInfo(HttpContext.Current.Request); + return new HttpRequestWrapper(HttpContext.Current.Request); } /// <summary> @@ -638,6 +645,22 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Applies message prescribed HTTP response headers to an outgoing web response. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="response">The HTTP response.</param> + protected static void ApplyMessageTemplate(IMessage message, OutgoingWebResponse response) { + Requires.NotNull(message, "message"); + var httpMessage = message as IHttpDirectResponse; + if (httpMessage != null) { + response.Status = httpMessage.HttpStatusCode; + foreach (string headerName in httpMessage.Headers) { + response.Headers.Add(headerName, httpMessage.Headers[headerName]); + } + } + } + + /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> @@ -731,16 +754,16 @@ namespace DotNetOpenAuth.Messaging { /// </summary> /// <param name="request">The request to search for an embedded message.</param> /// <returns>The deserialized message, if one is found. Null otherwise.</returns> - protected virtual IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { + protected virtual IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { Requires.NotNull(request, "request"); - Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.UrlBeforeRewriting.AbsoluteUri); + Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.GetPublicFacingUrl().AbsoluteUri); // Search Form data first, and if nothing is there search the QueryString - Contract.Assume(request.Form != null && request.QueryStringBeforeRewriting != null); + Contract.Assume(request.Form != null && request.GetQueryStringBeforeRewriting() != null); var fields = request.Form.ToDictionary(); if (fields.Count == 0 && request.HttpMethod != "POST") { // OpenID 2.0 section 4.1.2 - fields = request.QueryStringBeforeRewriting.ToDictionary(); + fields = request.GetQueryStringBeforeRewriting().ToDictionary(); } MessageReceivingEndpoint recipient; @@ -1038,22 +1061,6 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> - /// Applies message prescribed HTTP response headers to an outgoing web response. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="response">The HTTP response.</param> - protected void ApplyMessageTemplate(IMessage message, OutgoingWebResponse response) { - Requires.NotNull(message, "message"); - var httpMessage = message as IHttpDirectResponse; - if (httpMessage != null) { - response.Status = httpMessage.HttpStatusCode; - foreach (string headerName in httpMessage.Headers) { - response.Headers.Add(headerName, httpMessage.Headers[headerName]); - } - } - } - - /// <summary> /// Prepares to send a request to the Service Provider as the query string in a GET request. /// </summary> /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param> diff --git a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs index 43df1f5..9d4b93e 100644 --- a/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs +++ b/src/DotNetOpenAuth.Core/Messaging/DataBagFormatterBase.cs @@ -110,7 +110,7 @@ namespace DotNetOpenAuth.Messaging { /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param> protected DataBagFormatterBase(ICryptoKeyStore cryptoKeyStore = null, string bucket = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? minimumAge = null, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) : this(signed, encrypted, compressed, maximumAge, decodeOnceOnly) { - Requires.True(!String.IsNullOrEmpty(bucket) || cryptoKeyStore == null, null); + Requires.True(!string.IsNullOrEmpty(bucket) || cryptoKeyStore == null, null); Requires.True(cryptoKeyStore != null || (!signed && !encrypted), null); this.cryptoKeyStore = cryptoKeyStore; @@ -190,15 +190,22 @@ namespace DotNetOpenAuth.Messaging { /// <summary> /// Deserializes a <see cref="DataBag"/>, including decompression, decryption, signature and nonce validation where applicable. /// </summary> - /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param> + /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be null.</param> /// <param name="value">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param> - /// <returns>The deserialized value. Never null.</returns> + /// <param name="messagePartName">The name of the parameter whose value is to be deserialized. Used for error message generation.</param> + /// <returns> + /// The deserialized value. Never null. + /// </returns> [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")] - public T Deserialize(IProtocolMessage containingMessage, string value) { + public T Deserialize(IProtocolMessage containingMessage, string value, string messagePartName) { + Requires.NotNull(containingMessage, "containingMessage"); + Requires.NotNullOrEmpty(value, "value"); + Requires.NotNullOrEmpty(messagePartName, "messagePartName"); + string symmetricSecretHandle = null; if (this.encrypted && this.cryptoKeyStore != null) { string valueWithoutHandle; - MessagingUtilities.ExtractKeyHandleAndPayload(containingMessage, "<TODO>", value, out symmetricSecretHandle, out valueWithoutHandle); + MessagingUtilities.ExtractKeyHandleAndPayload(containingMessage, messagePartName, value, out symmetricSecretHandle, out valueWithoutHandle); value = valueWithoutHandle; } diff --git a/src/DotNetOpenAuth.Core/Messaging/EmptyDictionary.cs b/src/DotNetOpenAuth.Core/Messaging/EmptyDictionary.cs index a686d45..f21be78 100644 --- a/src/DotNetOpenAuth.Core/Messaging/EmptyDictionary.cs +++ b/src/DotNetOpenAuth.Core/Messaging/EmptyDictionary.cs @@ -75,6 +75,7 @@ namespace DotNetOpenAuth.Messaging { /// Gets or sets the value with the specified key. /// </summary> /// <param name="key">The key being read or written.</param> + /// <returns>Nothing. It always throws.</returns> public TValue this[TKey key] { get { throw new KeyNotFoundException(); } set { throw new NotSupportedException(); } diff --git a/src/DotNetOpenAuth.Core/Messaging/EmptyList.cs b/src/DotNetOpenAuth.Core/Messaging/EmptyList.cs index 6790e19..5d64118 100644 --- a/src/DotNetOpenAuth.Core/Messaging/EmptyList.cs +++ b/src/DotNetOpenAuth.Core/Messaging/EmptyList.cs @@ -53,6 +53,7 @@ namespace DotNetOpenAuth.Messaging { /// Gets or sets the <typeparamref name="T"/> at the specified index. /// </summary> /// <param name="index">The index of the element in the list to change.</param> + /// <returns>Nothing. It always throws.</returns> public T this[int index] { get { throw new ArgumentOutOfRangeException("index"); diff --git a/src/DotNetOpenAuth.Core/Messaging/EnumerableCache.cs b/src/DotNetOpenAuth.Core/Messaging/EnumerableCacheExtensions.cs index afbdf30..5e9cf93 100644 --- a/src/DotNetOpenAuth.Core/Messaging/EnumerableCache.cs +++ b/src/DotNetOpenAuth.Core/Messaging/EnumerableCacheExtensions.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="EnumerableCache.cs" company="Outercurve Foundation"> +// <copyright file="EnumerableCacheExtensions.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // This code is released under the Microsoft Public License (Ms-PL). // </copyright> diff --git a/src/DotNetOpenAuth.Core/Messaging/HttpRequestHeaders.cs b/src/DotNetOpenAuth.Core/Messaging/HttpRequestHeaders.cs new file mode 100644 index 0000000..9579a81 --- /dev/null +++ b/src/DotNetOpenAuth.Core/Messaging/HttpRequestHeaders.cs @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------- +// <copyright file="HttpRequestHeaders.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; + + /// <summary> + /// Well known HTTP headers. + /// </summary> + internal static class HttpRequestHeaders { + /// <summary> + /// The Authorization header, which specifies the credentials that the client presents in order to authenticate itself to the server. + /// </summary> + internal const string Authorization = "Authorization"; + + /// <summary> + /// The Content-Type header, which specifies the MIME type of the accompanying body data. + /// </summary> + internal const string ContentType = "Content-Type"; + } +} diff --git a/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs index 49ecb36..ed948ce 100644 --- a/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs +++ b/src/DotNetOpenAuth.Core/Messaging/HttpRequestInfo.cs @@ -25,101 +25,51 @@ namespace DotNetOpenAuth.Messaging { /// ASP.NET does not let us fully initialize that class, so we have to write one /// of our one. /// </remarks> - public class HttpRequestInfo { + public class HttpRequestInfo : HttpRequestBase { /// <summary> - /// The key/value pairs found in the entity of a POST request. + /// The HTTP verb in the request. /// </summary> - private NameValueCollection form; + private readonly string httpMethod; /// <summary> - /// The key/value pairs found in the querystring of the incoming request. + /// The full request URL. /// </summary> - private NameValueCollection queryString; + private readonly Uri requestUri; /// <summary> - /// Backing field for the <see cref="QueryStringBeforeRewriting"/> property. + /// The HTTP headers. /// </summary> - private NameValueCollection queryStringBeforeRewriting; + private readonly NameValueCollection headers; /// <summary> - /// Backing field for the <see cref="Message"/> property. + /// The variables defined in the query part of the URL. /// </summary> - private IDirectedProtocolMessage message; + private readonly NameValueCollection queryString; /// <summary> - /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. + /// The POSTed form variables. /// </summary> - /// <param name="request">The ASP.NET structure to copy from.</param> - public HttpRequestInfo(HttpRequest request) { - Requires.NotNull(request, "request"); - Contract.Ensures(this.HttpMethod == request.HttpMethod); - Contract.Ensures(this.Url == request.Url); - Contract.Ensures(this.RawUrl == request.RawUrl); - Contract.Ensures(this.UrlBeforeRewriting != null); - Contract.Ensures(this.Headers != null); - Contract.Ensures(this.InputStream == request.InputStream); - Contract.Ensures(this.form == request.Form); - Contract.Ensures(this.queryString == request.QueryString); - - this.HttpMethod = request.HttpMethod; - this.Url = request.Url; - this.UrlBeforeRewriting = GetPublicFacingUrl(request); - this.RawUrl = request.RawUrl; - this.Headers = GetHeaderCollection(request.Headers); - this.InputStream = request.InputStream; - - // These values would normally be calculated, but we'll reuse them from - // HttpRequest since they're already calculated, and there's a chance (<g>) - // that ASP.NET does a better job of being comprehensive about gathering - // these as well. - this.form = request.Form; - this.queryString = request.QueryString; - - Reporting.RecordRequestStatistics(this); - } + private readonly NameValueCollection form; /// <summary> - /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. + /// The server variables collection. /// </summary> - /// <param name="httpMethod">The HTTP method (i.e. GET or POST) of the incoming request.</param> - /// <param name="requestUrl">The URL being requested.</param> - /// <param name="rawUrl">The raw URL that appears immediately following the HTTP verb in the request, - /// before any URL rewriting takes place.</param> - /// <param name="headers">Headers in the HTTP request.</param> - /// <param name="inputStream">The entity stream, if any. (POST requests typically have these). Use <c>null</c> for GET requests.</param> - public HttpRequestInfo(string httpMethod, Uri requestUrl, string rawUrl, WebHeaderCollection headers, Stream inputStream) { - Requires.NotNullOrEmpty(httpMethod, "httpMethod"); - Requires.NotNull(requestUrl, "requestUrl"); - Requires.NotNull(rawUrl, "rawUrl"); - Requires.NotNull(headers, "headers"); - - this.HttpMethod = httpMethod; - this.Url = requestUrl; - this.UrlBeforeRewriting = requestUrl; - this.RawUrl = rawUrl; - this.Headers = headers; - this.InputStream = inputStream; - - Reporting.RecordRequestStatistics(this); - } + private readonly NameValueCollection serverVariables; /// <summary> /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. /// </summary> - /// <param name="listenerRequest">Details on the incoming HTTP request.</param> - public HttpRequestInfo(HttpListenerRequest listenerRequest) { - Requires.NotNull(listenerRequest, "listenerRequest"); - - this.HttpMethod = listenerRequest.HttpMethod; - this.Url = listenerRequest.Url; - this.UrlBeforeRewriting = listenerRequest.Url; - this.RawUrl = listenerRequest.RawUrl; - this.Headers = new WebHeaderCollection(); - foreach (string key in listenerRequest.Headers) { - this.Headers[key] = listenerRequest.Headers[key]; - } + /// <param name="request">The request.</param> + /// <param name="requestUri">The request URI.</param> + internal HttpRequestInfo(HttpRequestMessageProperty request, Uri requestUri) { + Requires.NotNull(request, "request"); + Requires.NotNull(requestUri, "requestUri"); - this.InputStream = listenerRequest.InputStream; + this.httpMethod = request.Method; + this.headers = request.Headers; + this.requestUri = requestUri; + this.form = new NameValueCollection(); + this.serverVariables = new NameValueCollection(); Reporting.RecordRequestStatistics(this); } @@ -127,297 +77,179 @@ namespace DotNetOpenAuth.Messaging { /// <summary> /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. /// </summary> - /// <param name="request">The WCF incoming request structure to get the HTTP information from.</param> - /// <param name="requestUri">The URI of the service endpoint.</param> - public HttpRequestInfo(HttpRequestMessageProperty request, Uri requestUri) { - Requires.NotNull(request, "request"); + /// <param name="httpMethod">The HTTP method.</param> + /// <param name="requestUri">The request URI.</param> + /// <param name="form">The form variables.</param> + /// <param name="headers">The HTTP headers.</param> + internal HttpRequestInfo(string httpMethod, Uri requestUri, NameValueCollection form = null, NameValueCollection headers = null) { + Requires.NotNullOrEmpty(httpMethod, "httpMethod"); Requires.NotNull(requestUri, "requestUri"); - this.HttpMethod = request.Method; - this.Headers = request.Headers; - this.Url = requestUri; - this.UrlBeforeRewriting = requestUri; - this.RawUrl = MakeUpRawUrlFromUrl(requestUri); - - Reporting.RecordRequestStatistics(this); + this.httpMethod = httpMethod; + this.requestUri = requestUri; + this.form = form ?? new NameValueCollection(); + this.queryString = HttpUtility.ParseQueryString(requestUri.Query); + this.headers = headers ?? new NameValueCollection(); + this.serverVariables = new NameValueCollection(); } /// <summary> /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. /// </summary> - internal HttpRequestInfo() { - Contract.Ensures(this.HttpMethod == "GET"); - Contract.Ensures(this.Headers != null); + /// <param name="listenerRequest">Details on the incoming HTTP request.</param> + internal HttpRequestInfo(HttpListenerRequest listenerRequest) { + Requires.NotNull(listenerRequest, "listenerRequest"); - this.HttpMethod = "GET"; - this.Headers = new WebHeaderCollection(); + this.httpMethod = listenerRequest.HttpMethod; + this.requestUri = listenerRequest.Url; + this.queryString = listenerRequest.QueryString; + this.headers = listenerRequest.Headers; + this.form = ParseFormData(listenerRequest.HttpMethod, listenerRequest.Headers, listenerRequest.InputStream); + this.serverVariables = new NameValueCollection(); + + Reporting.RecordRequestStatistics(this); } /// <summary> /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. /// </summary> - /// <param name="request">The HttpWebRequest (that was never used) to copy from.</param> - internal HttpRequestInfo(WebRequest request) { - Requires.NotNull(request, "request"); + /// <param name="httpMethod">The HTTP method.</param> + /// <param name="requestUri">The request URI.</param> + /// <param name="headers">The headers.</param> + /// <param name="inputStream">The input stream.</param> + internal HttpRequestInfo(string httpMethod, Uri requestUri, NameValueCollection headers, Stream inputStream) { + Requires.NotNullOrEmpty(httpMethod, "httpMethod"); + Requires.NotNull(requestUri, "requestUri"); - this.HttpMethod = request.Method; - this.Url = request.RequestUri; - this.UrlBeforeRewriting = request.RequestUri; - this.RawUrl = MakeUpRawUrlFromUrl(request.RequestUri); - this.Headers = GetHeaderCollection(request.Headers); - this.InputStream = null; + this.httpMethod = httpMethod; + this.requestUri = requestUri; + this.headers = headers; + this.queryString = HttpUtility.ParseQueryString(requestUri.Query); + this.form = ParseFormData(httpMethod, headers, inputStream); + this.serverVariables = new NameValueCollection(); Reporting.RecordRequestStatistics(this); } /// <summary> - /// Initializes a new instance of the <see cref="HttpRequestInfo"/> class. + /// Gets the HTTP method. /// </summary> - /// <param name="message">The message being passed in through a mock transport. May be null.</param> - /// <param name="httpMethod">The HTTP method that the incoming request came in on, whether or not <paramref name="message"/> is null.</param> - internal HttpRequestInfo(IDirectedProtocolMessage message, HttpDeliveryMethods httpMethod) { - this.message = message; - this.HttpMethod = MessagingUtilities.GetHttpVerb(httpMethod); + public override string HttpMethod { + get { return this.httpMethod; } } /// <summary> - /// Gets or sets the message that is being sent over a mock transport (for testing). + /// Gets the headers. /// </summary> - internal virtual IDirectedProtocolMessage Message { - get { return this.message; } - set { this.message = value; } + public override NameValueCollection Headers { + get { return this.headers; } } /// <summary> - /// Gets or sets the verb in the request (i.e. GET, POST, etc.) - /// </summary> - internal string HttpMethod { get; set; } - - /// <summary> - /// Gets or sets the entire URL of the request, after any URL rewriting. - /// </summary> - internal Uri Url { get; set; } - - /// <summary> - /// Gets or sets the raw URL that appears immediately following the HTTP verb in the request, - /// before any URL rewriting takes place. + /// Gets the URL. /// </summary> - internal string RawUrl { get; set; } - - /// <summary> - /// Gets or sets the full public URL used by the remote client to initiate this request, - /// before any URL rewriting and before any changes made by web farm load distributors. - /// </summary> - internal Uri UrlBeforeRewriting { get; set; } - - /// <summary> - /// Gets the query part of the URL (The ? and everything after it), after URL rewriting. - /// </summary> - internal string Query { - get { return this.Url != null ? this.Url.Query : null; } + public override Uri Url { + get { return this.requestUri; } } /// <summary> - /// Gets or sets the collection of headers that came in with the request. - /// </summary> - internal WebHeaderCollection Headers { get; set; } - - /// <summary> - /// Gets or sets the entity, or body of the request, if any. + /// Gets the raw URL. /// </summary> - internal Stream InputStream { get; set; } - - /// <summary> - /// Gets the key/value pairs found in the entity of a POST request. - /// </summary> - internal NameValueCollection Form { - get { - Contract.Ensures(Contract.Result<NameValueCollection>() != null); - if (this.form == null) { - ContentType contentType = string.IsNullOrEmpty(this.Headers[HttpRequestHeader.ContentType]) ? null : new ContentType(this.Headers[HttpRequestHeader.ContentType]); - if (this.HttpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) { - StreamReader reader = new StreamReader(this.InputStream); - long originalPosition = 0; - if (this.InputStream.CanSeek) { - originalPosition = this.InputStream.Position; - } - this.form = HttpUtility.ParseQueryString(reader.ReadToEnd()); - if (this.InputStream.CanSeek) { - this.InputStream.Seek(originalPosition, SeekOrigin.Begin); - } - } else { - this.form = new NameValueCollection(); - } - } - - return this.form; - } + public override string RawUrl { + get { return this.requestUri.AbsolutePath + this.requestUri.Query; } } /// <summary> - /// Gets the key/value pairs found in the querystring of the incoming request. + /// Gets the form. /// </summary> - internal NameValueCollection QueryString { - get { - if (this.queryString == null) { - this.queryString = this.Query != null ? HttpUtility.ParseQueryString(this.Query) : new NameValueCollection(); - } - - return this.queryString; - } + public override NameValueCollection Form { + get { return this.form; } } /// <summary> - /// Gets the query data from the original request (before any URL rewriting has occurred.) + /// Gets the query string. /// </summary> - /// <returns>A <see cref="NameValueCollection"/> containing all the parameters in the query string.</returns> - internal NameValueCollection QueryStringBeforeRewriting { - get { - if (this.queryStringBeforeRewriting == null) { - // This request URL may have been rewritten by the host site. - // For openid protocol purposes, we really need to look at - // the original query parameters before any rewriting took place. - if (!this.IsUrlRewritten) { - // No rewriting has taken place. - this.queryStringBeforeRewriting = this.QueryString; - } else { - // Rewriting detected! Recover the original request URI. - ErrorUtilities.VerifyInternal(this.UrlBeforeRewriting != null, "UrlBeforeRewriting is null, so the query string cannot be determined."); - this.queryStringBeforeRewriting = HttpUtility.ParseQueryString(this.UrlBeforeRewriting.Query); - } - } - - return this.queryStringBeforeRewriting; - } + public override NameValueCollection QueryString { + get { return this.queryString; } } /// <summary> - /// Gets a value indicating whether the request's URL was rewritten by ASP.NET - /// or some other module. + /// Gets the server variables. /// </summary> - /// <value> - /// <c>true</c> if this request's URL was rewritten; otherwise, <c>false</c>. - /// </value> - internal bool IsUrlRewritten { - get { return this.Url != this.UrlBeforeRewriting; } + public override NameValueCollection ServerVariables { + get { return this.serverVariables; } } /// <summary> - /// Gets the public facing URL for the given incoming HTTP request. + /// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request. /// </summary> /// <param name="request">The request.</param> - /// <param name="serverVariables">The server variables to consider part of the request.</param> - /// <returns> - /// The URI that the outside world used to create this request. - /// </returns> - /// <remarks> - /// Although the <paramref name="serverVariables"/> value can be obtained from - /// <see cref="HttpRequest.ServerVariables"/>, it's useful to be able to pass them - /// in so we can simulate injected values from our unit tests since the actual property - /// is a read-only kind of <see cref="NameValueCollection"/>. - /// </remarks> - internal static Uri GetPublicFacingUrl(HttpRequest request, NameValueCollection serverVariables) { - Requires.NotNull(request, "request"); - Requires.NotNull(serverVariables, "serverVariables"); - - // Due to URL rewriting, cloud computing (i.e. Azure) - // and web farms, etc., we have to be VERY careful about what - // we consider the incoming URL. We want to see the URL as it would - // appear on the public-facing side of the hosting web site. - // HttpRequest.Url gives us the internal URL in a cloud environment, - // So we use a variable that (at least from what I can tell) gives us - // the public URL: - if (serverVariables["HTTP_HOST"] != null) { - ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols."); - string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme; - Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + serverVariables["HTTP_HOST"]); - UriBuilder publicRequestUri = new UriBuilder(request.Url); - publicRequestUri.Scheme = scheme; - publicRequestUri.Host = hostAndPort.Host; - publicRequestUri.Port = hostAndPort.Port; // CC missing Uri.Port contract that's on UriBuilder.Port - return publicRequestUri.Uri; - } else { - // Failover to the method that works for non-web farm enviroments. - // We use Request.Url for the full path to the server, and modify it - // with Request.RawUrl to capture both the cookieless session "directory" if it exists - // and the original path in case URL rewriting is going on. We don't want to be - // fooled by URL rewriting because we're comparing the actual URL with what's in - // the return_to parameter in some cases. - // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless - // session, but not the URL rewriting problem. - return new Uri(request.Url, request.RawUrl); - } + /// <param name="requestUri">The request URI.</param> + /// <returns>An instance of <see cref="HttpRequestBase"/>.</returns> + public static HttpRequestBase Create(HttpRequestMessageProperty request, Uri requestUri) { + return new HttpRequestInfo(request, requestUri); } /// <summary> - /// Gets the query or form data from the original request (before any URL rewriting has occurred.) + /// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request. /// </summary> - /// <returns>A set of name=value pairs.</returns> - [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call")] - internal NameValueCollection GetQueryOrFormFromContext() { - NameValueCollection query; - if (this.HttpMethod == "GET") { - query = this.QueryStringBeforeRewriting; - } else { - query = this.Form; - } - return query; + /// <param name="listenerRequest">The listener request.</param> + /// <returns>An instance of <see cref="HttpRequestBase"/>.</returns> + public static HttpRequestBase Create(HttpListenerRequest listenerRequest) { + return new HttpRequestInfo(listenerRequest); } /// <summary> - /// Gets the public facing URL for the given incoming HTTP request. + /// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request. /// </summary> - /// <param name="request">The request.</param> - /// <returns>The URI that the outside world used to create this request.</returns> - private static Uri GetPublicFacingUrl(HttpRequest request) { - Requires.NotNull(request, "request"); - return GetPublicFacingUrl(request, request.ServerVariables); + /// <param name="httpMethod">The HTTP method.</param> + /// <param name="requestUri">The request URI.</param> + /// <param name="form">The form variables.</param> + /// <param name="headers">The HTTP headers.</param> + /// <returns>An instance of <see cref="HttpRequestBase"/>.</returns> + public static HttpRequestBase Create(string httpMethod, Uri requestUri, NameValueCollection form = null, NameValueCollection headers = null) { + return new HttpRequestInfo(httpMethod, requestUri, form, headers); } /// <summary> - /// Makes up a reasonable guess at the raw URL from the possibly rewritten URL. + /// Creates an <see cref="HttpRequestBase"/> instance that describes the specified HTTP request. /// </summary> - /// <param name="url">A full URL.</param> - /// <returns>A raw URL that might have come in on the HTTP verb.</returns> - private static string MakeUpRawUrlFromUrl(Uri url) { - Requires.NotNull(url, "url"); - return url.AbsolutePath + url.Query + url.Fragment; + /// <param name="httpMethod">The HTTP method.</param> + /// <param name="requestUri">The request URI.</param> + /// <param name="headers">The headers.</param> + /// <param name="inputStream">The input stream.</param> + /// <returns>An instance of <see cref="HttpRequestBase"/>.</returns> + public static HttpRequestBase Create(string httpMethod, Uri requestUri, NameValueCollection headers, Stream inputStream) { + return new HttpRequestInfo(httpMethod, requestUri, headers, inputStream); } /// <summary> - /// Converts a NameValueCollection to a WebHeaderCollection. + /// Reads name=value pairs from the POSTed form entity when the HTTP headers indicate that that is the payload of the entity. /// </summary> - /// <param name="pairs">The collection a HTTP headers.</param> - /// <returns>A new collection of the given headers.</returns> - private static WebHeaderCollection GetHeaderCollection(NameValueCollection pairs) { - Requires.NotNull(pairs, "pairs"); - - WebHeaderCollection headers = new WebHeaderCollection(); - foreach (string key in pairs) { - try { - headers.Add(key, pairs[key]); - } catch (ArgumentException ex) { - Logger.Messaging.WarnFormat( - "{0} thrown when trying to add web header \"{1}: {2}\". {3}", - ex.GetType().Name, - key, - pairs[key], - ex.Message); + /// <param name="httpMethod">The HTTP method.</param> + /// <param name="headers">The headers.</param> + /// <param name="inputStream">The input stream.</param> + /// <returns>The non-null collection of form variables.</returns> + private static NameValueCollection ParseFormData(string httpMethod, NameValueCollection headers, Stream inputStream) { + Requires.NotNullOrEmpty(httpMethod, "httpMethod"); + Requires.NotNull(headers, "headers"); + + ContentType contentType = string.IsNullOrEmpty(headers[HttpRequestHeaders.ContentType]) ? null : new ContentType(headers[HttpRequestHeaders.ContentType]); + if (inputStream != null && httpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) { + var reader = new StreamReader(inputStream); + long originalPosition = 0; + if (inputStream.CanSeek) { + originalPosition = inputStream.Position; + } + string postEntity = reader.ReadToEnd(); + if (inputStream.CanSeek) { + inputStream.Seek(originalPosition, SeekOrigin.Begin); } - } - return headers; - } + return HttpUtility.ParseQueryString(postEntity); + } -#if CONTRACTS_FULL - /// <summary> - /// Verifies conditions that should be true for any valid state of this object. - /// </summary> - [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Called by code contracts.")] - [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")] - [ContractInvariantMethod] - private void ObjectInvariant() { + return new NameValueCollection(); } -#endif } } diff --git a/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs b/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs index f911264..9086ee9 100644 --- a/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs +++ b/src/DotNetOpenAuth.Core/Messaging/IDataBagFormatter.cs @@ -24,10 +24,13 @@ namespace DotNetOpenAuth.Messaging { /// <summary> /// Deserializes a <see cref="DataBag"/>. /// </summary> - /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param> + /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be null.</param> /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param> - /// <returns>The deserialized value. Never null.</returns> - T Deserialize(IProtocolMessage containingMessage, string data); + /// <param name="messagePartName">The name of the parameter whose value is to be deserialized. Used for error message generation.</param> + /// <returns> + /// The deserialized value. Never null. + /// </returns> + T Deserialize(IProtocolMessage containingMessage, string data, string messagePartName); } /// <summary> @@ -51,7 +54,7 @@ namespace DotNetOpenAuth.Messaging { /// <returns>A non-null, non-empty value.</returns> string IDataBagFormatter<T>.Serialize(T message) { Requires.NotNull(message, "message"); - Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); throw new System.NotImplementedException(); } @@ -61,10 +64,14 @@ namespace DotNetOpenAuth.Messaging { /// </summary> /// <param name="containingMessage">The message that contains the <see cref="DataBag"/> serialized value. Must not be nulll.</param> /// <param name="data">The serialized form of the <see cref="DataBag"/> to deserialize. Must not be null or empty.</param> - /// <returns>The deserialized value. Never null.</returns> - T IDataBagFormatter<T>.Deserialize(IProtocolMessage containingMessage, string data) { + /// <param name="messagePartName">Name of the message part whose value is to be deserialized. Used for exception messages.</param> + /// <returns> + /// The deserialized value. Never null. + /// </returns> + T IDataBagFormatter<T>.Deserialize(IProtocolMessage containingMessage, string data, string messagePartName) { Requires.NotNull(containingMessage, "containingMessage"); Requires.NotNullOrEmpty(data, "data"); + Requires.NotNullOrEmpty(messagePartName, "messagePartName"); Contract.Ensures(Contract.Result<T>() != null); throw new System.NotImplementedException(); diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs index 1305620..b26deeb 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs @@ -153,9 +153,7 @@ namespace DotNetOpenAuth.Messaging { [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call should not be a property.")] public static Uri GetRequestUrlFromContext() { Requires.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired); - HttpContext context = HttpContext.Current; - - return HttpRequestInfo.GetPublicFacingUrl(context.Request, context.Request.ServerVariables); + return new HttpRequestWrapper(HttpContext.Current.Request).GetPublicFacingUrl(); } /// <summary> @@ -448,7 +446,7 @@ namespace DotNetOpenAuth.Messaging { internal static string CombineKeyHandleAndPayload(string handle, string payload) { Requires.NotNullOrEmpty(handle, "handle"); Requires.NotNullOrEmpty(payload, "payload"); - Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); return handle + "!" + payload; } @@ -1248,7 +1246,7 @@ namespace DotNetOpenAuth.Messaging { Requires.NotNull(args, "args"); Contract.Ensures(Contract.Result<string>() != null); - if (args.Count() == 0) { + if (!args.Any()) { return string.Empty; } StringBuilder sb = new StringBuilder(args.Count() * 10); @@ -1352,8 +1350,8 @@ namespace DotNetOpenAuth.Messaging { /// <param name="request">The request to get recipient information from.</param> /// <returns>The recipient.</returns> /// <exception cref="ArgumentException">Thrown if the HTTP request is something we can't handle.</exception> - internal static MessageReceivingEndpoint GetRecipient(this HttpRequestInfo request) { - return new MessageReceivingEndpoint(request.UrlBeforeRewriting, GetHttpDeliveryMethod(request.HttpMethod)); + internal static MessageReceivingEndpoint GetRecipient(this HttpRequestBase request) { + return new MessageReceivingEndpoint(request.GetPublicFacingUrl(), GetHttpDeliveryMethod(request.HttpMethod)); } /// <summary> @@ -1484,6 +1482,22 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Converts a dictionary to a <see cref="NameValueCollection"/> + /// </summary> + /// <param name="data">The existing dictionary.</param> + /// <returns>The new collection.</returns> + internal static NameValueCollection ToNameValueCollection(this IDictionary<string, string> data) { + Requires.NotNull(data, "data"); + + var nvc = new NameValueCollection(); + foreach (var entry in data) { + nvc.Add(entry.Key, entry.Value); + } + + return nvc; + } + + /// <summary> /// Sorts the elements of a sequence in ascending order by using a specified comparer. /// </summary> /// <typeparam name="TSource">The type of the elements of source.</typeparam> @@ -1663,6 +1677,111 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Gets the query data from the original request (before any URL rewriting has occurred.) + /// </summary> + /// <param name="request">The request.</param> + /// <returns> + /// A <see cref="NameValueCollection"/> containing all the parameters in the query string. + /// </returns> + internal static NameValueCollection GetQueryStringBeforeRewriting(this HttpRequestBase request) { + // This request URL may have been rewritten by the host site. + // For openid protocol purposes, we really need to look at + // the original query parameters before any rewriting took place. + Uri beforeRewriting = GetPublicFacingUrl(request); + if (beforeRewriting == request.Url) { + // No rewriting has taken place. + return request.QueryString; + } else { + // Rewriting detected! Recover the original request URI. + ErrorUtilities.VerifyInternal(beforeRewriting != null, "UrlBeforeRewriting is null, so the query string cannot be determined."); + return HttpUtility.ParseQueryString(beforeRewriting.Query); + } + } + + /// <summary> + /// Gets a value indicating whether the request's URL was rewritten by ASP.NET + /// or some other module. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>A value indicating whether there is evidence that the URL of the request has been changed to some internal server (farm) representation.</returns> + /// <value> + /// <c>true</c> if this request's URL was rewritten; otherwise, <c>false</c>. + /// </value> + internal static bool GetIsUrlRewritten(this HttpRequestBase request) { + return request.Url != GetPublicFacingUrl(request); + } + + /// <summary> + /// Gets the public facing URL for the given incoming HTTP request. + /// </summary> + /// <param name="request">The request.</param> + /// <param name="serverVariables">The server variables to consider part of the request.</param> + /// <returns> + /// The URI that the outside world used to create this request. + /// </returns> + /// <remarks> + /// Although the <paramref name="serverVariables"/> value can be obtained from + /// <see cref="HttpRequest.ServerVariables"/>, it's useful to be able to pass them + /// in so we can simulate injected values from our unit tests since the actual property + /// is a read-only kind of <see cref="NameValueCollection"/>. + /// </remarks> + internal static Uri GetPublicFacingUrl(this HttpRequestBase request, NameValueCollection serverVariables) { + Requires.NotNull(request, "request"); + Requires.NotNull(serverVariables, "serverVariables"); + + // Due to URL rewriting, cloud computing (i.e. Azure) + // and web farms, etc., we have to be VERY careful about what + // we consider the incoming URL. We want to see the URL as it would + // appear on the public-facing side of the hosting web site. + // HttpRequest.Url gives us the internal URL in a cloud environment, + // So we use a variable that (at least from what I can tell) gives us + // the public URL: + if (serverVariables["HTTP_HOST"] != null) { + ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols."); + string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme; + Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + serverVariables["HTTP_HOST"]); + UriBuilder publicRequestUri = new UriBuilder(request.Url); + publicRequestUri.Scheme = scheme; + publicRequestUri.Host = hostAndPort.Host; + publicRequestUri.Port = hostAndPort.Port; // CC missing Uri.Port contract that's on UriBuilder.Port + return publicRequestUri.Uri; + } else { + // Failover to the method that works for non-web farm enviroments. + // We use Request.Url for the full path to the server, and modify it + // with Request.RawUrl to capture both the cookieless session "directory" if it exists + // and the original path in case URL rewriting is going on. We don't want to be + // fooled by URL rewriting because we're comparing the actual URL with what's in + // the return_to parameter in some cases. + // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless + // session, but not the URL rewriting problem. + return new Uri(request.Url, request.RawUrl); + } + } + + /// <summary> + /// Gets the public facing URL for the given incoming HTTP request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>The URI that the outside world used to create this request.</returns> + internal static Uri GetPublicFacingUrl(this HttpRequestBase request) { + Requires.NotNull(request, "request"); + return GetPublicFacingUrl(request, request.ServerVariables); + } + + /// <summary> + /// Gets the query or form data from the original request (before any URL rewriting has occurred.) + /// </summary> + /// <param name="request">The request.</param> + /// <returns> + /// A set of name=value pairs. + /// </returns> + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call")] + internal static NameValueCollection GetQueryOrForm(this HttpRequestBase request) { + Requires.NotNull(request, "request"); + return request.HttpMethod == "GET" ? GetQueryStringBeforeRewriting(request) : request.Form; + } + + /// <summary> /// Creates a symmetric algorithm for use in encryption/decryption. /// </summary> /// <param name="key">The symmetric key to use for encryption/decryption.</param> diff --git a/src/DotNetOpenAuth.Core/Messaging/OutgoingWebResponseActionResult.cs b/src/DotNetOpenAuth.Core/Messaging/OutgoingWebResponseActionResult.cs index 9569e34..a5fe782 100644 --- a/src/DotNetOpenAuth.Core/Messaging/OutgoingWebResponseActionResult.cs +++ b/src/DotNetOpenAuth.Core/Messaging/OutgoingWebResponseActionResult.cs @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Messaging { /// </summary> /// <param name="context">The context in which to set the response.</param> public override void ExecuteResult(ControllerContext context) { - this.response.Respond(); + this.response.Respond(context.HttpContext); } } } diff --git a/src/DotNetOpenAuth.Core/Messaging/ReadOnlyDictionary.cs b/src/DotNetOpenAuth.Core/Messaging/ReadOnlyDictionary.cs new file mode 100644 index 0000000..0ba1ff5 --- /dev/null +++ b/src/DotNetOpenAuth.Core/Messaging/ReadOnlyDictionary.cs @@ -0,0 +1,224 @@ +//----------------------------------------------------------------------- +// <copyright file="ReadOnlyDictionary.cs" company="Microsoft Corporation"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Messaging { + using System; + using System.Collections.Generic; + + /// <summary> + /// Represents a read-only dictionary. + /// </summary> + /// <typeparam name="K">The type of the key.</typeparam> + /// <typeparam name="V">The type of the value.</typeparam> + internal class ReadOnlyDictionary<K, V> : IDictionary<K, V> { + /// <summary> + /// Contains base dictionary. + /// </summary> + private readonly IDictionary<K, V> baseDictionary; + + /// <summary> + /// Initializes a new instance of the <see cref="ReadOnlyDictionary<K, V>"/> class. + /// </summary> + /// <param name="baseDictionary">The base dictionary.</param> + public ReadOnlyDictionary(IDictionary<K, V> baseDictionary) { + this.baseDictionary = baseDictionary; + } + + /// <summary> + /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </summary> + /// <returns> + /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </returns> + public ICollection<K> Keys { + get { return this.baseDictionary.Keys; } + } + + /// <summary> + /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </summary> + /// <returns> + /// An <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </returns> + public ICollection<V> Values { + get { return this.baseDictionary.Values; } + } + + /// <summary> + /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </summary> + /// <returns> + /// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </returns> + public int Count { + get { return this.baseDictionary.Count; } + } + + /// <summary> + /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. + /// </summary> + /// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false. + /// </returns> + public bool IsReadOnly { + get { return true; } + } + + /// <summary> + /// Gets or sets the element with the specified key. + /// </summary> + /// <param name="key">The key being read or written.</param> + /// <returns> + /// The element with the specified key. + /// </returns> + /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. + /// </exception> + /// <exception cref="T:System.Collections.Generic.KeyNotFoundException"> + /// The property is retrieved and <paramref name="key"/> is not found. + /// </exception> + /// <exception cref="T:System.NotSupportedException"> + /// The property is set and the <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only. + /// </exception> + public V this[K key] { + get { return this.baseDictionary[key]; } + set { throw new NotSupportedException(); } + } + + /// <summary> + /// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </summary> + /// <param name="key">The object to use as the key of the element to add.</param> + /// <param name="value">The object to use as the value of the element to add.</param> + /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. + /// </exception> + /// <exception cref="T:System.ArgumentException"> + /// An element with the same key already exists in the <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </exception> + /// <exception cref="T:System.NotSupportedException"> + /// The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only. + /// </exception> + public void Add(K key, V value) { + throw new NotSupportedException(); + } + + /// <summary> + /// Determines whether the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key. + /// </summary> + /// <param name="key">The key to locate in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.</param> + /// <returns> + /// true if the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the key; otherwise, false. + /// </returns> + /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. + /// </exception> + public bool ContainsKey(K key) { + return this.baseDictionary.ContainsKey(key); + } + + /// <summary> + /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </summary> + /// <param name="key">The key of the element to remove.</param> + /// <returns> + /// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>. + /// </returns> + /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. + /// </exception> + /// <exception cref="T:System.NotSupportedException"> + /// The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only. + /// </exception> + public bool Remove(K key) { + throw new NotSupportedException(); + } + + /// <summary> + /// Gets the value associated with the specified key. + /// </summary> + /// <param name="key">The key whose value to get.</param> + /// <param name="value">When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.</param> + /// <returns> + /// true if the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key; otherwise, false. + /// </returns> + /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null. + /// </exception> + public bool TryGetValue(K key, out V value) { + return this.baseDictionary.TryGetValue(key, out value); + } + + /// <summary> + /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </summary> + /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param> + /// <exception cref="T:System.NotSupportedException"> + /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. + /// </exception> + public void Add(KeyValuePair<K, V> item) { + throw new NotSupportedException(); + } + + /// <summary> + /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </summary> + /// <exception cref="T:System.NotSupportedException"> + /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. + /// </exception> + public void Clear() { + throw new NotSupportedException(); + } + + /// <summary> + /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value. + /// </summary> + /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param> + /// <returns> + /// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. + /// </returns> + public bool Contains(KeyValuePair<K, V> item) { + return this.baseDictionary.Contains(item); + } + + /// <summary> + /// Copies to. + /// </summary> + /// <param name="array">The array.</param> + /// <param name="arrayIndex">Index of the array.</param> + public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) { + this.baseDictionary.CopyTo(array, arrayIndex); + } + + /// <summary> + /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </summary> + /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param> + /// <returns> + /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>. + /// </returns> + /// <exception cref="T:System.NotSupportedException"> + /// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. + /// </exception> + public bool Remove(KeyValuePair<K, V> item) { + throw new NotSupportedException(); + } + + /// <summary> + /// Returns an enumerator that iterates through the collection. + /// </summary> + /// <returns> + /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection. + /// </returns> + public IEnumerator<KeyValuePair<K, V>> GetEnumerator() { + return this.baseDictionary.GetEnumerator(); + } + + /// <summary> + /// Returns an enumerator that iterates through a collection. + /// </summary> + /// <returns> + /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection. + /// </returns> + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { + return this.baseDictionary.GetEnumerator(); + } + } +}
\ No newline at end of file diff --git a/src/DotNetOpenAuth.Core/Messaging/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth.Core/Messaging/UntrustedWebRequestHandler.cs index c490127..25a7bbb 100644 --- a/src/DotNetOpenAuth.Core/Messaging/UntrustedWebRequestHandler.cs +++ b/src/DotNetOpenAuth.Core/Messaging/UntrustedWebRequestHandler.cs @@ -383,7 +383,7 @@ namespace DotNetOpenAuth.Messaging { /// <exception cref="ProtocolException">Thrown when the URI is disallowed for security reasons.</exception> private void EnsureAllowableRequestUri(Uri requestUri, bool requireSsl) { ErrorUtilities.VerifyProtocol(this.IsUriAllowable(requestUri), MessagingStrings.UnsafeWebRequestDetected, requestUri); - ErrorUtilities.VerifyProtocol(!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); } /// <summary> diff --git a/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs b/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs index 84e75b0..92b1928 100644 --- a/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs +++ b/src/DotNetOpenAuth.Core/Messaging/UriStyleMessageFormatter.cs @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Messaging { /// <param name="decodeOnceOnly">The nonce store to use to ensure that this instance is only decoded once.</param> protected internal UriStyleMessageFormatter(ICryptoKeyStore cryptoKeyStore = null, string bucket = null, bool signed = false, bool encrypted = false, bool compressed = false, TimeSpan? minimumAge = null, TimeSpan? maximumAge = null, INonceStore decodeOnceOnly = null) : base(cryptoKeyStore, bucket, signed, encrypted, compressed, minimumAge, maximumAge, decodeOnceOnly) { - Requires.True((cryptoKeyStore != null && !String.IsNullOrEmpty(bucket)) || (!signed && !encrypted), null); + Requires.True((cryptoKeyStore != null && !string.IsNullOrEmpty(bucket)) || (!signed && !encrypted), null); } /// <summary> diff --git a/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs index 950a7cd..e57b211 100644 --- a/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.Core/Properties/AssemblyInfo.cs @@ -67,6 +67,8 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client.UI, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] #else [assembly: InternalsVisibleTo("DotNetOpenAuth.Test")] @@ -88,5 +90,7 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.AuthorizationServer")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.ResourceServer")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2.Client")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] #endif diff --git a/src/DotNetOpenAuth.Core/Reporting.cs b/src/DotNetOpenAuth.Core/Reporting.cs index a7940b6..951bb7c 100644 --- a/src/DotNetOpenAuth.Core/Reporting.cs +++ b/src/DotNetOpenAuth.Core/Reporting.cs @@ -170,7 +170,7 @@ namespace DotNetOpenAuth { /// <param name="category">The category within the event. Null and empty strings are allowed, but considered the same.</param> [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "PersistentCounter instances are stored in a table for later use.")] internal static void RecordEventOccurrence(string eventName, string category) { - Contract.Requires(!String.IsNullOrEmpty(eventName)); + Contract.Requires(!string.IsNullOrEmpty(eventName)); // In release builds, just quietly return. if (string.IsNullOrEmpty(eventName)) { @@ -213,7 +213,7 @@ namespace DotNetOpenAuth { /// </summary> /// <param name="feature">The feature.</param> internal static void RecordFeatureUse(string feature) { - Contract.Requires(!String.IsNullOrEmpty(feature)); + Contract.Requires(!string.IsNullOrEmpty(feature)); // In release builds, just quietly return. if (string.IsNullOrEmpty(feature)) { @@ -297,7 +297,7 @@ namespace DotNetOpenAuth { /// Records statistics collected from incoming requests. /// </summary> /// <param name="request">The request.</param> - internal static void RecordRequestStatistics(HttpRequestInfo request) { + internal static void RecordRequestStatistics(HttpRequestBase request) { Contract.Requires(request != null); // In release builds, just quietly return. @@ -311,7 +311,7 @@ namespace DotNetOpenAuth { } if (Configuration.IncludeLocalRequestUris && !observedRequests.IsFull) { - var requestBuilder = new UriBuilder(request.UrlBeforeRewriting); + var requestBuilder = new UriBuilder(request.GetPublicFacingUrl()); requestBuilder.Query = null; requestBuilder.Fragment = null; observedRequests.Add(requestBuilder.Uri.AbsoluteUri); diff --git a/src/DotNetOpenAuth.Core/Requires.cs b/src/DotNetOpenAuth.Core/Requires.cs index 8aa15dd..7a196a3 100644 --- a/src/DotNetOpenAuth.Core/Requires.cs +++ b/src/DotNetOpenAuth.Core/Requires.cs @@ -24,16 +24,18 @@ namespace DotNetOpenAuth { /// <typeparam name="T">The type of the parameter</typeparam> /// <param name="value">The value.</param> /// <param name="parameterName">Name of the parameter.</param> + /// <returns>The tested value, guaranteed to not be null.</returns> #if !CLR4 [ContractArgumentValidator] #endif [Pure, DebuggerStepThrough] - internal static void NotNull<T>(T value, string parameterName) where T : class { + internal static T NotNull<T>(T value, string parameterName) where T : class { if (value == null) { throw new ArgumentNullException(parameterName); } Contract.EndContractBlock(); + return value; } /// <summary> @@ -134,7 +136,7 @@ namespace DotNetOpenAuth { [Pure, DebuggerStepThrough] internal static void True(bool condition, string parameterName, string unformattedMessage, params object[] args) { if (!condition) { - throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, unformattedMessage, args), parameterName); + throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, unformattedMessage, args), parameterName); } Contract.EndContractBlock(); @@ -185,7 +187,7 @@ namespace DotNetOpenAuth { [Pure, DebuggerStepThrough] internal static void ValidState(bool condition, string unformattedMessage, params object[] args) { if (!condition) { - throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, unformattedMessage, args)); + throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, unformattedMessage, args)); } Contract.EndContractBlock(); diff --git a/src/DotNetOpenAuth.Core/Settings.StyleCop b/src/DotNetOpenAuth.Core/Settings.StyleCop index 017d610..ac744c0 100644 --- a/src/DotNetOpenAuth.Core/Settings.StyleCop +++ b/src/DotNetOpenAuth.Core/Settings.StyleCop @@ -1,6 +1,6 @@ <StyleCopSettings Version="4.3"> <Analyzers> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.DocumentationRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules"> <Rules> <Rule Name="ElementDocumentationMustNotBeCopiedAndPasted"> <RuleSettings> @@ -10,7 +10,7 @@ </Rules> <AnalyzerSettings /> </Analyzer> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.MaintainabilityRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules"> <Rules> <Rule Name="StatementMustNotUseUnnecessaryParenthesis"> <RuleSettings> @@ -20,7 +20,7 @@ </Rules> <AnalyzerSettings /> </Analyzer> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.ReadabilityRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules"> <Rules> <Rule Name="UseStringEmptyForEmptyStrings"> <RuleSettings> diff --git a/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardImage.cs b/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardImage.cs index dfcc3e3..821ea1b 100644 --- a/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardImage.cs +++ b/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardImage.cs @@ -132,7 +132,7 @@ namespace DotNetOpenAuth.InfoCard { string imageSize = size.ToString(); Contract.Assume(imageSize.Length >= 6); imageSize = imageSize.Substring(4); - return String.Format(CultureInfo.InvariantCulture, UrlFormatString, imageSize); + return string.Format(CultureInfo.InvariantCulture, UrlFormatString, imageSize); } } } diff --git a/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardSelector.cs b/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardSelector.cs index 756b9a7..c4563f2 100644 --- a/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardSelector.cs +++ b/src/DotNetOpenAuth.InfoCard.UI/InfoCard/InfoCardSelector.cs @@ -279,7 +279,7 @@ namespace DotNetOpenAuth.InfoCard { if (!string.IsNullOrEmpty(value)) { if (this.Page != null && !this.DesignMode) { // Validate new value by trying to construct a Uri based on it. - new Uri(new HttpRequestInfo(HttpContext.Current.Request).UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure. + new Uri(new HttpRequestWrapper(HttpContext.Current.Request).GetPublicFacingUrl(), this.Page.ResolveUrl(value)); // throws an exception on failure. } else { // We can't fully test it, but it should start with either ~/ or a protocol. if (Regex.IsMatch(value, @"^https?://")) { diff --git a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs index d599598..086ff7a 100644 --- a/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs +++ b/src/DotNetOpenAuth.OAuth.Consumer/OAuth/WebConsumer.cs @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.OAuth { /// Requires HttpContext.Current. /// </remarks> public UserAuthorizationRequest PrepareRequestUserAuthorization() { - Uri callback = this.Channel.GetRequestFromContext().UrlBeforeRewriting.StripQueryArgumentsWithPrefix(Protocol.ParameterPrefix); + Uri callback = this.Channel.GetRequestFromContext().GetPublicFacingUrl().StripQueryArgumentsWithPrefix(Protocol.ParameterPrefix); return this.PrepareRequestUserAuthorization(callback, null, null); } @@ -76,7 +76,7 @@ namespace DotNetOpenAuth.OAuth { /// </summary> /// <param name="request">The incoming HTTP request.</param> /// <returns>The access token, or null if no incoming authorization message was recognized.</returns> - public AuthorizedTokenResponse ProcessUserAuthorization(HttpRequestInfo request) { + public AuthorizedTokenResponse ProcessUserAuthorization(HttpRequestBase request) { Requires.NotNull(request, "request"); UserAuthorizationResponse authorizationMessage; diff --git a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs index 9d93e4f..ecfd191 100644 --- a/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs +++ b/src/DotNetOpenAuth.OAuth.ServiceProvider/OAuth/ServiceProvider.cs @@ -216,7 +216,7 @@ namespace DotNetOpenAuth.OAuth { /// </summary> /// <param name="request">The HTTP request to read the message from.</param> /// <returns>The deserialized message.</returns> - public IDirectedProtocolMessage ReadRequest(HttpRequestInfo request) { + public IDirectedProtocolMessage ReadRequest(HttpRequestBase request) { return this.Channel.ReadFromRequest(request); } @@ -238,7 +238,7 @@ namespace DotNetOpenAuth.OAuth { /// <param name="request">The HTTP request to read from.</param> /// <returns>The incoming request, or null if no OAuth message was attached.</returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public UnauthorizedTokenRequest ReadTokenRequest(HttpRequestInfo request) { + public UnauthorizedTokenRequest ReadTokenRequest(HttpRequestBase request) { UnauthorizedTokenRequest message; if (this.Channel.TryReadFromRequest(request, out message)) { ErrorUtilities.VerifyProtocol(message.Version >= Protocol.Lookup(this.SecuritySettings.MinimumRequiredOAuthVersion).Version, OAuthStrings.MinimumConsumerVersionRequirementNotMet, this.SecuritySettings.MinimumRequiredOAuthVersion, message.Version); @@ -282,7 +282,7 @@ namespace DotNetOpenAuth.OAuth { /// <param name="request">The HTTP request to read from.</param> /// <returns>The incoming request, or null if no OAuth message was attached.</returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public UserAuthorizationRequest ReadAuthorizationRequest(HttpRequestInfo request) { + public UserAuthorizationRequest ReadAuthorizationRequest(HttpRequestBase request) { UserAuthorizationRequest message; this.Channel.TryReadFromRequest(request, out message); return message; @@ -368,7 +368,7 @@ namespace DotNetOpenAuth.OAuth { /// <param name="request">The HTTP request to read from.</param> /// <returns>The incoming request, or null if no OAuth message was attached.</returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> - public AuthorizedTokenRequest ReadAccessTokenRequest(HttpRequestInfo request) { + public AuthorizedTokenRequest ReadAccessTokenRequest(HttpRequestBase request) { AuthorizedTokenRequest message; this.Channel.TryReadFromRequest(request, out message); return message; @@ -436,7 +436,7 @@ namespace DotNetOpenAuth.OAuth { /// to access the resources being requested. /// </remarks> /// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception> - public AccessProtectedResourceRequest ReadProtectedResourceAuthorization(HttpRequestInfo request) { + public AccessProtectedResourceRequest ReadProtectedResourceAuthorization(HttpRequestBase request) { Requires.NotNull(request, "request"); AccessProtectedResourceRequest accessMessage; diff --git a/src/DotNetOpenAuth.OAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth.OAuth/OAuth/ChannelElements/OAuthChannel.cs index 2cbc16b..b04c67e 100644 --- a/src/DotNetOpenAuth.OAuth/OAuth/ChannelElements/OAuthChannel.cs +++ b/src/DotNetOpenAuth.OAuth/OAuth/ChannelElements/OAuthChannel.cs @@ -109,15 +109,15 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// </summary> /// <param name="request">The HTTP request to search.</param> /// <returns>The deserialized message, if one is found. Null otherwise.</returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { // First search the Authorization header. - string authorization = request.Headers[HttpRequestHeader.Authorization]; + string authorization = request.Headers[HttpRequestHeaders.Authorization]; var fields = MessagingUtilities.ParseAuthorizationHeader(Protocol.AuthorizationHeaderScheme, authorization).ToDictionary(); fields.Remove("realm"); // ignore the realm parameter, since we don't use it, and it must be omitted from signature base string. // Scrape the entity - if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeader.ContentType])) { - var contentType = new ContentType(request.Headers[HttpRequestHeader.ContentType]); + if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeaders.ContentType])) { + var contentType = new ContentType(request.Headers[HttpRequestHeaders.ContentType]); if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) { foreach (string key in request.Form) { if (key != null) { @@ -130,11 +130,12 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { } // Scrape the query string - foreach (string key in request.QueryStringBeforeRewriting) { + var qs = request.GetQueryStringBeforeRewriting(); + foreach (string key in qs) { if (key != null) { - fields.Add(key, request.QueryStringBeforeRewriting[key]); + fields.Add(key, qs[key]); } else { - Logger.OAuth.WarnFormat("Ignoring query string parameter '{0}' since it isn't a standard name=value parameter.", request.QueryStringBeforeRewriting[key]); + Logger.OAuth.WarnFormat("Ignoring query string parameter '{0}' since it isn't a standard name=value parameter.", qs[key]); } } @@ -152,7 +153,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { // Add receiving HTTP transport information required for signature generation. var signedMessage = message as ITamperResistantOAuthMessage; if (signedMessage != null) { - signedMessage.Recipient = request.UrlBeforeRewriting; + signedMessage.Recipient = request.GetPublicFacingUrl(); signedMessage.HttpMethod = request.HttpMethod; } @@ -223,7 +224,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { Headers = new System.Net.WebHeaderCollection(), }; - this.ApplyMessageTemplate(response, encodedResponse); + ApplyMessageTemplate(response, encodedResponse); return encodedResponse; } diff --git a/src/DotNetOpenAuth.OAuth/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.OAuth/Properties/AssemblyInfo.cs index cbc1307..7f63d1b 100644 --- a/src/DotNetOpenAuth.OAuth/Properties/AssemblyInfo.cs +++ b/src/DotNetOpenAuth.OAuth/Properties/AssemblyInfo.cs @@ -53,6 +53,7 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth.ServiceProvider, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenIdOAuth, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100AD093C3765257C89A7010E853F2C7C741FF92FA8ACE06D7B8254702CAD5CF99104447F63AB05F8BB6F51CE0D81C8C93D2FCE8C20AAFF7042E721CBA16EAAE98778611DED11C0ABC8900DC5667F99B50A9DADEC24DBD8F2C91E3E8AD300EF64F1B4B9536CEB16FB440AF939F57624A9B486F867807C649AE4830EAB88C6C03998")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] #else [assembly: InternalsVisibleTo("DotNetOpenAuth.Test")] @@ -60,5 +61,6 @@ using System.Web.UI; [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth.ServiceProvider")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OpenIdOAuth")] [assembly: InternalsVisibleTo("DotNetOpenAuth.OAuth2")] +[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] #endif diff --git a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs index 9840218..f555248 100644 --- a/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs +++ b/src/DotNetOpenAuth.OAuth2.AuthorizationServer/OAuth2/AuthorizationServer.cs @@ -12,6 +12,8 @@ namespace DotNetOpenAuth.OAuth2 { using System.Linq; using System.Security.Cryptography; using System.Text; + using System.Web; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.ChannelElements; using DotNetOpenAuth.OAuth2.Messages; @@ -51,7 +53,7 @@ namespace DotNetOpenAuth.OAuth2 { /// <returns>The incoming request, or null if no OAuth message was attached.</returns> /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception> [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "unauthorizedclient", Justification = "Protocol required.")] - public EndUserAuthorizationRequest ReadAuthorizationRequest(HttpRequestInfo request = null) { + public EndUserAuthorizationRequest ReadAuthorizationRequest(HttpRequestBase request = null) { if (request == null) { request = this.Channel.GetRequestFromContext(); } @@ -61,7 +63,7 @@ namespace DotNetOpenAuth.OAuth2 { if (message.ResponseType == EndUserAuthorizationResponseType.AuthorizationCode) { // Clients with no secrets can only request implicit grant types. var client = this.AuthorizationServerServices.GetClientOrThrow(message.ClientIdentifier); - ErrorUtilities.VerifyProtocol(!String.IsNullOrEmpty(client.Secret), Protocol.unauthorized_client); + ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(client.Secret), Protocol.unauthorized_client); } } @@ -95,55 +97,33 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found. - /// </summary> - /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param> - /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns> - /// <remarks> - /// This method assumes that the authorization server and the resource server are the same and that they share a single - /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead. - /// </remarks> - public bool TryPrepareAccessTokenResponse(out IDirectResponseProtocolMessage response) { - return this.TryPrepareAccessTokenResponse(this.Channel.GetRequestFromContext(), out response); - } - - /// <summary> - /// Checks the incoming HTTP request for an access token request and prepares a response if the request message was found. + /// Handles an incoming request to the authorization server's token endpoint. /// </summary> - /// <param name="httpRequestInfo">The HTTP request info.</param> - /// <param name="response">The formulated response, or <c>null</c> if the request was not found..</param> - /// <returns>A value indicating whether any access token request was found in the HTTP request.</returns> - /// <remarks> - /// This method assumes that the authorization server and the resource server are the same and that they share a single - /// asymmetric key for signing and encrypting the access token. If this is not true, use the <see cref="ReadAccessTokenRequest"/> method instead. - /// </remarks> - public bool TryPrepareAccessTokenResponse(HttpRequestInfo httpRequestInfo, out IDirectResponseProtocolMessage response) { - Requires.NotNull(httpRequestInfo, "httpRequestInfo"); - Contract.Ensures(Contract.Result<bool>() == (Contract.ValueAtReturn<IDirectResponseProtocolMessage>(out response) != null)); - - var request = this.ReadAccessTokenRequest(httpRequestInfo); - if (request != null) { - response = this.PrepareAccessTokenResponse(request); - return true; + /// <param name="request">The HTTP request.</param> + /// <returns>The HTTP response to send to the client.</returns> + public OutgoingWebResponse HandleTokenRequest(HttpRequestBase request = null) { + if (request == null) { + request = this.Channel.GetRequestFromContext(); } - response = null; - return false; - } - - /// <summary> - /// Reads the access token request. - /// </summary> - /// <param name="requestInfo">The request info.</param> - /// <returns>The Client's request for an access token; or <c>null</c> if no such message was found in the request.</returns> - public AccessTokenRequestBase ReadAccessTokenRequest(HttpRequestInfo requestInfo = null) { - if (requestInfo == null) { - requestInfo = this.Channel.GetRequestFromContext(); + AccessTokenRequestBase requestMessage; + IProtocolMessage responseMessage; + try { + if (this.Channel.TryReadFromRequest(request, out requestMessage)) { + // TODO: refreshToken should be set appropriately based on authorization server policy. + responseMessage = this.PrepareAccessTokenResponse(requestMessage); + } else { + responseMessage = new AccessTokenFailedResponse() { + Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, + }; + } + } catch (ProtocolException) { + responseMessage = new AccessTokenFailedResponse() { + Error = Protocol.AccessTokenRequestErrorCodes.InvalidRequest, + }; } - AccessTokenRequestBase request; - this.Channel.TryReadFromRequest(requestInfo, out request); - return request; + return this.Channel.PrepareResponse(responseMessage); } /// <summary> @@ -207,33 +187,6 @@ namespace DotNetOpenAuth.OAuth2 { } /// <summary> - /// Prepares the response to an access token request. - /// </summary> - /// <param name="request">The request for an access token.</param> - /// <param name="includeRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param> - /// <returns>The response message to send to the client.</returns> - public virtual IDirectResponseProtocolMessage PrepareAccessTokenResponse(AccessTokenRequestBase request, bool includeRefreshToken = true) { - Requires.NotNull(request, "request"); - - if (includeRefreshToken) { - if (request is AccessTokenClientCredentialsRequest) { - // Per OAuth 2.0 section 4.4.3 (draft 23), refresh tokens should never be included - // in a response to an access token request that used the client credential grant type. - Logger.OAuth.Debug("Suppressing refresh token in access token response because the grant type used by the client disallows it."); - includeRefreshToken = false; - } - } - - var tokenRequest = (IAuthorizationCarryingRequest)request; - var response = new AccessTokenSuccessResponse(request) { - Lifetime = this.AuthorizationServerServices.GetAccessTokenLifetime(request), - HasRefreshToken = includeRefreshToken, - }; - response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope); - return response; - } - - /// <summary> /// Gets the redirect URL to use for a particular authorization request. /// </summary> /// <param name="authorizationRequest">The authorization request.</param> @@ -258,5 +211,32 @@ namespace DotNetOpenAuth.OAuth2 { ErrorUtilities.VerifyProtocol(defaultCallback != null, OAuthStrings.NoCallback); return defaultCallback; } + + /// <summary> + /// Prepares the response to an access token request. + /// </summary> + /// <param name="request">The request for an access token.</param> + /// <param name="includeRefreshToken">If set to <c>true</c>, the response will include a long-lived refresh token.</param> + /// <returns>The response message to send to the client.</returns> + private IDirectResponseProtocolMessage PrepareAccessTokenResponse(AccessTokenRequestBase request, bool includeRefreshToken = true) { + Requires.NotNull(request, "request"); + + if (includeRefreshToken) { + if (request is AccessTokenClientCredentialsRequest) { + // Per OAuth 2.0 section 4.4.3 (draft 23), refresh tokens should never be included + // in a response to an access token request that used the client credential grant type. + Logger.OAuth.Debug("Suppressing refresh token in access token response because the grant type used by the client disallows it."); + includeRefreshToken = false; + } + } + + var tokenRequest = (IAuthorizationCarryingRequest)request; + var response = new AccessTokenSuccessResponse(request) { + Lifetime = this.AuthorizationServerServices.GetAccessTokenLifetime(request), + HasRefreshToken = includeRefreshToken, + }; + response.Scope.ResetContents(tokenRequest.AuthorizationDescription.Scope); + return response; + } } } diff --git a/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.Designer.cs b/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.Designer.cs index c05a4b8..c06a134 100644 --- a/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.Designer.cs +++ b/src/DotNetOpenAuth.OAuth2.Client.UI/OAuth2/ClientAuthorizationView.Designer.cs @@ -1,4 +1,6 @@ namespace DotNetOpenAuth.OAuth2 { + using System.Diagnostics.CodeAnalysis; + partial class ClientAuthorizationView { /// <summary> /// Required designer variable. @@ -22,6 +24,7 @@ /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> + [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "I don't see a problem here.")] private void InitializeComponent() { this.webBrowser1 = new System.Windows.Forms.WebBrowser(); this.SuspendLayout(); diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs index b8cfbe3..7697244 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs @@ -167,27 +167,22 @@ namespace DotNetOpenAuth.OAuth2 { Requires.NotNullOrEmpty(userName, "userName"); Requires.NotNull(password, "password"); - var authorizationState = new AuthorizationState(scopes); - var request = new AccessTokenResourceOwnerPasswordCredentialsRequest(this.AuthorizationServer.TokenEndpoint, this.AuthorizationServer.Version) { - ClientIdentifier = this.ClientIdentifier, - ClientSecret = this.ClientSecret, UserName = userName, Password = password, }; - var response = this.Channel.Request(request); - var success = response as AccessTokenSuccessResponse; - var failure = response as AccessTokenFailedResponse; - ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany); - if (success != null) { - UpdateAuthorizationWithResponse(authorizationState, success); - } else { // failure - Logger.OAuth.Info("Resource Owner credentials rejected by the Authorization Server."); - authorizationState.Delete(); - } + return this.RequestAccessToken(request, scopes); + } - return authorizationState; + /// <summary> + /// Obtains an access token for accessing client-controlled resources on the resource server. + /// </summary> + /// <param name="scopes">The desired scopes.</param> + /// <returns>The result of the authorization request.</returns> + public IAuthorizationState GetClientAccessToken(IEnumerable<string> scopes = null) { + var request = new AccessTokenClientCredentialsRequest(this.AuthorizationServer.TokenEndpoint, this.AuthorizationServer.Version); + return this.RequestAccessToken(request, scopes); } /// <summary> @@ -287,5 +282,34 @@ namespace DotNetOpenAuth.OAuth2 { double proportionLifetimeRemaining = 1 - (elapsedLifetime.TotalSeconds / totalLifetime.TotalSeconds); return proportionLifetimeRemaining; } + + /// <summary> + /// Requests an access token using a partially .initialized request message. + /// </summary> + /// <param name="request">The request message.</param> + /// <param name="scopes">The scopes requested by the client.</param> + /// <returns>The result of the request.</returns> + private IAuthorizationState RequestAccessToken(ScopedAccessTokenRequest request, IEnumerable<string> scopes = null) { + Requires.NotNull(request, "request"); + + var authorizationState = new AuthorizationState(scopes); + + request.ClientIdentifier = this.ClientIdentifier; + request.ClientSecret = this.ClientSecret; + request.Scope.UnionWith(authorizationState.Scope); + + var response = this.Channel.Request(request); + var success = response as AccessTokenSuccessResponse; + var failure = response as AccessTokenFailedResponse; + ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany); + if (success != null) { + UpdateAuthorizationWithResponse(authorizationState, success); + } else { // failure + Logger.OAuth.Info("Credentials rejected by the Authorization Server."); + authorizationState.Delete(); + } + + return authorizationState; + } } } diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs index d140b7e..74c0685 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.261 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx index 114b3e8..0a41e42 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx @@ -125,6 +125,7 @@ </data> <data name="AuthorizationResponseUnexpectedMismatch" xml:space="preserve"> <value>Unexpected OAuth authorization response received with callback and client state that does not match an expected value.</value> + <comment>The error message generated when detecting a mismatch between the state sent to the authorization server originally and what we got back with successful authorization, or that the user sessions were not identical between the two requests, suggesting XSRF or other attack on the user (victim).</comment> </data> <data name="RequiredPropertyNotYetPreset" xml:space="preserve"> <value>The property {0} must be set before this operation is allowed.</value> diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs index 5131b10..c29d167 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/UserAgentClient.cs @@ -10,6 +10,8 @@ namespace DotNetOpenAuth.OAuth2 { using System.Diagnostics.Contracts; using System.Linq; using System.Text; + using System.Web; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2.Messages; @@ -56,7 +58,7 @@ namespace DotNetOpenAuth.OAuth2 { Callback = returnTo, }; - return this.RequestUserAuthorization(authorization); + return this.RequestUserAuthorization(authorization, state: state); } /// <summary> @@ -93,7 +95,7 @@ namespace DotNetOpenAuth.OAuth2 { authorizationState = new AuthorizationState(); } - var carrier = new HttpRequestInfo("GET", actualRedirectUrl, actualRedirectUrl.PathAndQuery, new System.Net.WebHeaderCollection(), null); + var carrier = new HttpRequestInfo("GET", actualRedirectUrl); IDirectedProtocolMessage response = this.Channel.ReadFromRequest(carrier); if (response == null) { return null; @@ -116,12 +118,11 @@ namespace DotNetOpenAuth.OAuth2 { EndUserAuthorizationSuccessAccessTokenResponse accessTokenSuccess; EndUserAuthorizationSuccessAuthCodeResponse authCodeSuccess; - EndUserAuthorizationFailedResponse failure; if ((accessTokenSuccess = response as EndUserAuthorizationSuccessAccessTokenResponse) != null) { UpdateAuthorizationWithResponse(authorizationState, accessTokenSuccess); } else if ((authCodeSuccess = response as EndUserAuthorizationSuccessAuthCodeResponse) != null) { this.UpdateAuthorizationWithResponse(authorizationState, authCodeSuccess); - } else if ((failure = response as EndUserAuthorizationFailedResponse) != null) { + } else if (response is EndUserAuthorizationFailedResponse) { authorizationState.Delete(); return null; } diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs index ffcc1ee..671214f 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs @@ -39,43 +39,40 @@ namespace DotNetOpenAuth.OAuth2 { /// Prepares a request for user authorization from an authorization server. /// </summary> /// <param name="scope">The scope of authorized access requested.</param> - /// <param name="state">The state of the client that should be sent back with the authorization response.</param> /// <param name="returnTo">The URL the authorization server should redirect the browser (typically on this site) to when the authorization is completed. If null, the current request's URL will be used.</param> - public void RequestUserAuthorization(IEnumerable<string> scope = null, string state = null, Uri returnTo = null) { + public void RequestUserAuthorization(IEnumerable<string> scope = null, Uri returnTo = null) { var authorizationState = new AuthorizationState(scope) { Callback = returnTo, }; - this.PrepareRequestUserAuthorization(authorizationState, state).Send(); + this.PrepareRequestUserAuthorization(authorizationState).Send(); } /// <summary> /// Prepares a request for user authorization from an authorization server. /// </summary> /// <param name="scopes">The scope of authorized access requested.</param> - /// <param name="state">The state of the client that should be sent back with the authorization response.</param> /// <param name="returnTo">The URL the authorization server should redirect the browser (typically on this site) to when the authorization is completed. If null, the current request's URL will be used.</param> /// <returns>The authorization request.</returns> - public OutgoingWebResponse PrepareRequestUserAuthorization(IEnumerable<string> scopes = null, string state = null, Uri returnTo = null) { + public OutgoingWebResponse PrepareRequestUserAuthorization(IEnumerable<string> scopes = null, Uri returnTo = null) { var authorizationState = new AuthorizationState(scopes) { Callback = returnTo, }; - return this.PrepareRequestUserAuthorization(authorizationState, state); + return this.PrepareRequestUserAuthorization(authorizationState); } /// <summary> /// Prepares a request for user authorization from an authorization server. /// </summary> /// <param name="authorization">The authorization state to associate with this particular request.</param> - /// <param name="state">The state of the client that should be sent back with the authorization response.</param> /// <returns>The authorization request.</returns> - public OutgoingWebResponse PrepareRequestUserAuthorization(IAuthorizationState authorization, string state = null) { + public OutgoingWebResponse PrepareRequestUserAuthorization(IAuthorizationState authorization) { Requires.NotNull(authorization, "authorization"); Requires.ValidState(authorization.Callback != null || (HttpContext.Current != null && HttpContext.Current.Request != null), MessagingStrings.HttpContextRequired); Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier"); Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null); if (authorization.Callback == null) { - authorization.Callback = this.Channel.GetRequestFromContext().UrlBeforeRewriting + authorization.Callback = this.Channel.GetRequestFromContext().GetPublicFacingUrl() .StripMessagePartsFromQueryString(this.Channel.MessageDescriptions.Get(typeof(EndUserAuthorizationSuccessResponseBase), Protocol.Default.Version)) .StripMessagePartsFromQueryString(this.Channel.MessageDescriptions.Get(typeof(EndUserAuthorizationFailedResponse), Protocol.Default.Version)); authorization.SaveChanges(); @@ -84,10 +81,21 @@ namespace DotNetOpenAuth.OAuth2 { var request = new EndUserAuthorizationRequest(this.AuthorizationServer) { ClientIdentifier = this.ClientIdentifier, Callback = authorization.Callback, - ClientState = state, }; request.Scope.ResetContents(authorization.Scope); + // Mitigate XSRF attacks by including a state value that would be unpredictable between users, but + // verifiable for the same user/session. + // If the host is implementing the authorization tracker though, they're handling this protection themselves. + if (this.AuthorizationTracker == null) { + var context = this.Channel.GetHttpContext(); + if (context.Session != null) { + request.ClientState = context.Session.SessionID; + } else { + Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be set to mitigate XSRF attacks."); + } + } + return this.Channel.PrepareResponse(request); } @@ -96,7 +104,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> /// <param name="request">The incoming HTTP request that may carry an authorization response.</param> /// <returns>The authorization state that contains the details of the authorization.</returns> - public IAuthorizationState ProcessUserAuthorization(HttpRequestInfo request = null) { + public IAuthorizationState ProcessUserAuthorization(HttpRequestBase request = null) { Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier"); Requires.ValidState(!string.IsNullOrEmpty(this.ClientSecret), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientSecret"); @@ -106,12 +114,19 @@ namespace DotNetOpenAuth.OAuth2 { IMessageWithClientState response; if (this.Channel.TryReadFromRequest<IMessageWithClientState>(request, out response)) { - Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.UrlBeforeRewriting, this.Channel.MessageDescriptions.Get(response)); + Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.GetPublicFacingUrl(), this.Channel.MessageDescriptions.Get(response)); IAuthorizationState authorizationState; if (this.AuthorizationTracker != null) { authorizationState = this.AuthorizationTracker.GetAuthorizationState(callback, response.ClientState); ErrorUtilities.VerifyProtocol(authorizationState != null, OAuth2Strings.AuthorizationResponseUnexpectedMismatch); } else { + var context = this.Channel.GetHttpContext(); + if (context.Session != null) { + ErrorUtilities.VerifyProtocol(string.Equals(response.ClientState, context.Session.SessionID, StringComparison.Ordinal), OAuth2Strings.AuthorizationResponseUnexpectedMismatch); + } else { + Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be checked to mitigate XSRF attacks."); + } + authorizationState = new AuthorizationState { Callback = callback }; } var success = response as EndUserAuthorizationSuccessAuthCodeResponse; diff --git a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs index a614219..79cbbd7 100644 --- a/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs +++ b/src/DotNetOpenAuth.OAuth2.ResourceServer/OAuth2/ResourceServer.cs @@ -71,7 +71,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </returns> [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")] [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Try pattern")] - public virtual OutgoingWebResponse VerifyAccess(HttpRequestInfo httpRequestInfo, out string userName, out HashSet<string> scope) { + public virtual OutgoingWebResponse VerifyAccess(HttpRequestBase httpRequestInfo, out string userName, out HashSet<string> scope) { Requires.NotNull(httpRequestInfo, "httpRequestInfo"); AccessProtectedResourceRequest request = null; @@ -108,7 +108,7 @@ namespace DotNetOpenAuth.OAuth2 { /// An error to return to the client if access is not authorized; <c>null</c> if access is granted. /// </returns> [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#", Justification = "Try pattern")] - public virtual OutgoingWebResponse VerifyAccess(HttpRequestInfo httpRequestInfo, out IPrincipal principal) { + public virtual OutgoingWebResponse VerifyAccess(HttpRequestBase httpRequestInfo, out IPrincipal principal) { string username; HashSet<string> scope; var result = this.VerifyAccess(httpRequestInfo, out username, out scope); diff --git a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj index 0a2a8ff..438a21d 100644 --- a/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj +++ b/src/DotNetOpenAuth.OAuth2/DotNetOpenAuth.OAuth2.csproj @@ -18,6 +18,7 @@ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> </PropertyGroup> <ItemGroup> + <Compile Include="GlobalSuppressions.cs" /> <Compile Include="OAuth2\AuthorizationState.cs" /> <Compile Include="OAuth2\ChannelElements\AccessRequestBindingElement.cs" /> <Compile Include="OAuth2\ChannelElements\AccessToken.cs" /> diff --git a/src/DotNetOpenAuth.OAuth2/GlobalSuppressions.cs b/src/DotNetOpenAuth.OAuth2/GlobalSuppressions.cs new file mode 100644 index 0000000..b91bb2e --- /dev/null +++ b/src/DotNetOpenAuth.OAuth2/GlobalSuppressions.cs @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------- +// <copyright file="GlobalSuppressions.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Error List, point to "Suppress Message(s)", and click +// "In Project Suppression File". +// You do not need to add suppressions to this file manually. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OAuth2.Messages.AccessTokenRequestBase.#DotNetOpenAuth.OAuth2.Messages.IAccessTokenRequest.ClientAuthenticated", Justification = "By design")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OAuth2.Messages.AccessTokenRequestBase.#DotNetOpenAuth.OAuth2.Messages.IAccessTokenRequest.Scope", Justification = "By design")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OAuth2.Messages.EndUserAuthorizationImplicitRequest.#DotNetOpenAuth.OAuth2.Messages.IAccessTokenRequest.ClientAuthenticated", Justification = "By design")] diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs index b0cef58..7a68060 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/AccessRequestBindingElement.cs @@ -115,20 +115,23 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { var authCodeCarrier = message as IAuthorizationCodeCarryingRequest; var refreshTokenCarrier = message as IRefreshTokenCarryingRequest; var resourceOwnerPasswordCarrier = message as AccessTokenResourceOwnerPasswordCredentialsRequest; + var clientCredentialOnly = message as AccessTokenClientCredentialsRequest; if (authCodeCarrier != null) { var authorizationCodeFormatter = AuthorizationCode.CreateFormatter(this.AuthorizationServer); - var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code); + var authorizationCode = authorizationCodeFormatter.Deserialize(message, authCodeCarrier.Code, Protocol.code); authCodeCarrier.AuthorizationDescription = authorizationCode; } else if (refreshTokenCarrier != null) { var refreshTokenFormatter = RefreshToken.CreateFormatter(this.AuthorizationServer.CryptoKeyStore); - var refreshToken = refreshTokenFormatter.Deserialize(message, refreshTokenCarrier.RefreshToken); + var refreshToken = refreshTokenFormatter.Deserialize(message, refreshTokenCarrier.RefreshToken, Protocol.refresh_token); refreshTokenCarrier.AuthorizationDescription = refreshToken; } else if (resourceOwnerPasswordCarrier != null) { try { if (this.AuthorizationServer.IsResourceOwnerCredentialValid(resourceOwnerPasswordCarrier.UserName, resourceOwnerPasswordCarrier.Password)) { resourceOwnerPasswordCarrier.CredentialsValidated = true; } else { - Logger.OAuth.WarnFormat("Resource owner password credential for user \"{0}\" rejected by authorization server host.", resourceOwnerPasswordCarrier.UserName); + Logger.OAuth.WarnFormat( + "Resource owner password credential for user \"{0}\" rejected by authorization server host.", + resourceOwnerPasswordCarrier.UserName); // TODO: fix this to report the appropriate error code for a bad credential. throw new ProtocolException(); @@ -140,6 +143,9 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { // TODO: fix this to return the appropriate error code for not supporting resource owner password credentials throw new ProtocolException(); } + } else if (clientCredentialOnly != null) { + // this method will throw later if the credentials are false. + clientCredentialOnly.CredentialsValidated = true; } else { throw ErrorUtilities.ThrowInternal("Unexpected message type: " + tokenRequest.GetType()); } @@ -155,7 +161,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { // Check that the client secret is correct. var client = this.AuthorizationServer.GetClientOrThrow(accessRequest.ClientIdentifier); string secret = client.Secret; - ErrorUtilities.VerifyProtocol(!String.IsNullOrEmpty(secret), Protocol.unauthorized_client); // an empty secret is not allowed for client authenticated calls. + ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(secret), Protocol.unauthorized_client); // an empty secret is not allowed for client authenticated calls. ErrorUtilities.VerifyProtocol(MessagingUtilities.EqualsConstantTime(secret, accessRequest.ClientSecret), Protocol.incorrect_client_credentials); var scopedAccessRequest = accessRequest as ScopedAccessTokenRequest; diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationDescription.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationDescription.cs index 150a6a9..1ad0422 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationDescription.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/IAuthorizationDescription.cs @@ -68,11 +68,13 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { } /// <summary> - /// Gets the name on the account whose data on the resource server is accessible using this authorization. + /// Gets the name on the account whose data on the resource server is accessible using this authorization, if applicable. /// </summary> + /// <value>A username, or <c>null</c> if the authorization is to access the client's own data (not a distinct resource owner's data).</value> string IAuthorizationDescription.User { get { - Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); + // Null and non-empty are allowed, but not empty. + Contract.Ensures(Contract.Result<string>() != string.Empty); throw new NotImplementedException(); } } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs index 3375328..6717717 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2AuthorizationServerChannel.cs @@ -56,7 +56,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// </remarks> protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { var webResponse = new OutgoingWebResponse(); - this.ApplyMessageTemplate(response, webResponse); + ApplyMessageTemplate(response, webResponse); string json = this.SerializeAsJson(response); webResponse.SetResponse(json, new ContentType(JsonEncoded)); return webResponse; @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// <returns> /// The deserialized message, if one is found. Null otherwise. /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { if (!string.IsNullOrEmpty(request.Url.Fragment)) { var fields = HttpUtility.ParseQueryString(request.Url.Fragment.Substring(1)).ToDictionary(); diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs index 117d526..51ac58a 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ChannelBase.cs @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { // Parameters sent without a value MUST be treated as if they were omitted from the request. // The authorization server SHOULD ignore unrecognized request parameters. var emptyKeys = from pair in fields - where String.IsNullOrEmpty(pair.Value) + where string.IsNullOrEmpty(pair.Value) select pair.Key; foreach (string emptyKey in emptyKeys.ToList()) { fields.Remove(emptyKey); diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs index 3a8a7c0..c9981d3 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ClientChannel.cs @@ -76,16 +76,16 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// <returns> /// The deserialized message, if one is found. Null otherwise. /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { - Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.UrlBeforeRewriting.AbsoluteUri); + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { + Logger.Channel.DebugFormat("Incoming HTTP request: {0} {1}", request.HttpMethod, request.GetPublicFacingUrl().AbsoluteUri); - var fields = request.QueryStringBeforeRewriting.ToDictionary(); + var fields = request.GetQueryStringBeforeRewriting().ToDictionary(); // Also read parameters from the fragment, if it's available. // Typically the fragment is not available because the browser doesn't send it to a web server // but this request may have been fabricated by an installed desktop app, in which case // the fragment is available. - string fragment = request.UrlBeforeRewriting.Fragment; + string fragment = request.GetPublicFacingUrl().Fragment; if (!string.IsNullOrEmpty(fragment)) { foreach (var pair in HttpUtility.ParseQueryString(fragment.Substring(1)).ToDictionary()) { fields.Add(pair.Key, pair.Value); diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs index 1c2a080..947c044 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/ChannelElements/OAuth2ResourceServerChannel.cs @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// <returns> /// The deserialized message, if one is found. Null otherwise. /// </returns> - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { var fields = new Dictionary<string, string>(); string accessToken; if ((accessToken = SearchForBearerAccessTokenInRequest(request)) != null) { @@ -106,7 +106,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { ErrorUtilities.VerifyInternal(unauthorizedResponse != null, "Only unauthorized responses are expected."); // First initialize based on the specifics within the message. - this.ApplyMessageTemplate(response, webResponse); + ApplyMessageTemplate(response, webResponse); if (!(response is IHttpDirectResponse)) { webResponse.Status = HttpStatusCode.Unauthorized; } @@ -122,18 +122,18 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { /// </summary> /// <param name="request">The request.</param> /// <returns>The bearer access token, if one exists. Otherwise <c>null</c>.</returns> - private static string SearchForBearerAccessTokenInRequest(HttpRequestInfo request) { + private static string SearchForBearerAccessTokenInRequest(HttpRequestBase request) { Requires.NotNull(request, "request"); // First search the authorization header. - string authorizationHeader = request.Headers[HttpRequestHeader.Authorization]; + string authorizationHeader = request.Headers[HttpRequestHeaders.Authorization]; if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace, StringComparison.OrdinalIgnoreCase)) { return authorizationHeader.Substring(Protocol.BearerHttpAuthorizationSchemeWithTrailingSpace.Length); } // Failing that, scan the entity - if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeader.ContentType])) { - var contentType = new ContentType(request.Headers[HttpRequestHeader.ContentType]); + if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeaders.ContentType])) { + var contentType = new ContentType(request.Headers[HttpRequestHeaders.ContentType]); if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) { if (request.Form[Protocol.BearerTokenEncodedUrlParameterName] != null) { return request.Form[Protocol.BearerTokenEncodedUrlParameterName]; @@ -142,8 +142,9 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements { } // Finally, check the least desirable location: the query string - if (!String.IsNullOrEmpty(request.QueryStringBeforeRewriting[Protocol.BearerTokenEncodedUrlParameterName])) { - return request.QueryStringBeforeRewriting[Protocol.BearerTokenEncodedUrlParameterName]; + var unrewrittenQuery = request.GetQueryStringBeforeRewriting(); + if (!string.IsNullOrEmpty(unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName])) { + return unrewrittenQuery[Protocol.BearerTokenEncodedUrlParameterName]; } return null; diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs index 8f4745f..a0a2ad9 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/IAuthorizationServer.cs @@ -256,7 +256,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </returns> /// <exception cref="NotSupportedException">May be thrown if the authorization server does not support the resource owner password credential grant type.</exception> bool IAuthorizationServer.IsResourceOwnerCredentialValid(string userName, string password) { - Contract.Requires(!String.IsNullOrEmpty(userName)); + Contract.Requires(!string.IsNullOrEmpty(userName)); Contract.Requires(password != null); throw new NotImplementedException(); } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessProtectedResourceRequest.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessProtectedResourceRequest.cs index 6cf8919..dbfe46b 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessProtectedResourceRequest.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessProtectedResourceRequest.cs @@ -62,7 +62,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// Always "bearer". /// </value> [MessagePart("token_type", IsRequired = true)] - internal string TokenType { + internal static string TokenType { get { return Protocol.AccessTokenTypes.Bearer; } } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs index 266dbce..48419eb 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenClientCredentialsRequest.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <remarks> /// This is somewhat analogous to 2-legged OAuth. /// </remarks> - internal class AccessTokenClientCredentialsRequest : ScopedAccessTokenRequest { + internal class AccessTokenClientCredentialsRequest : ScopedAccessTokenRequest, IAuthorizationCarryingRequest, IAuthorizationDescription { /// <summary> /// Initializes a new instance of the <see cref="AccessTokenClientCredentialsRequest"/> class. /// </summary> @@ -30,6 +30,43 @@ namespace DotNetOpenAuth.OAuth2.Messages { this.HttpMethods = HttpDeliveryMethods.PostRequest; } + #region IAuthorizationCarryingRequest members + + /// <summary> + /// Gets the authorization that the code or token describes. + /// </summary> + IAuthorizationDescription IAuthorizationCarryingRequest.AuthorizationDescription { + get { return this.CredentialsValidated ? this : null; } + } + + #endregion + + #region IAuthorizationDescription Members + + /// <summary> + /// Gets the date this authorization was established or the token was issued. + /// </summary> + /// <value>A date/time expressed in UTC.</value> + DateTime IAuthorizationDescription.UtcIssued { + get { return DateTime.UtcNow; } + } + + /// <summary> + /// Gets the name on the account whose data on the resource server is accessible using this authorization. + /// </summary> + string IAuthorizationDescription.User { + get { return null; } + } + + /// <summary> + /// Gets the scope of operations the client is allowed to invoke. + /// </summary> + HashSet<string> IAuthorizationDescription.Scope { + get { return this.Scope; } + } + + #endregion + /// <summary> /// Gets the type of the grant. /// </summary> @@ -37,5 +74,10 @@ namespace DotNetOpenAuth.OAuth2.Messages { internal override GrantType GrantType { get { return Messages.GrantType.ClientCredentials; } } + + /// <summary> + /// Gets or sets a value indicating whether the resource owner's credentials have been validated at the authorization server. + /// </summary> + internal bool CredentialsValidated { get; set; } } } diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs index 09acbc5..8c4b1c3 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenFailedResponse.cs @@ -38,11 +38,18 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <param name="request">The faulty request.</param> /// <param name="invalidClientCredentialsInAuthorizationHeader">A value indicating whether this error response is in result to a request that had invalid client credentials which were supplied in the HTTP Authorization header.</param> internal AccessTokenFailedResponse(AccessTokenRequestBase request, bool invalidClientCredentialsInAuthorizationHeader) - : base(request) - { + : base(request) { this.invalidClientCredentialsInAuthorizationHeader = invalidClientCredentialsInAuthorizationHeader; } + /// <summary> + /// Initializes a new instance of the <see cref="AccessTokenFailedResponse"/> class. + /// </summary> + /// <param name="version">The protocol version.</param> + internal AccessTokenFailedResponse(Version version = null) + : base(version ?? Protocol.Default.Version) { + } + #region IHttpDirectResponse Members /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs index 28f15ef..6d278c4 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/AccessTokenSuccessResponse.cs @@ -65,7 +65,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// <remarks> /// Described in OAuth 2.0 section 7.1. /// </remarks> - [MessagePart(Protocol.token_type, IsRequired = true)] + [MessagePart(Protocol.token_type, IsRequired = false)] // HACKHACK: This is actually required, but wasn't in older drafts of OAuth 2 public string TokenType { get; internal set; } /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs index 1d9618b..ef0010e 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/Messages/EndUserAuthorizationSuccessResponseBase.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Security.Cryptography; @@ -59,6 +60,7 @@ namespace DotNetOpenAuth.OAuth2.Messages { /// Gets or sets the scope of the <see cref="AccessToken"/> if one is given; otherwise the scope of the authorization code. /// </summary> /// <value>The scope.</value> + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")] public ICollection<string> Scope { get; protected set; } /// <summary> diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs index 68ccc1d..dd7909b 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/OAuthUtilities.cs @@ -104,7 +104,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> /// <param name="scopeToken">The scope token.</param> internal static void VerifyValidScopeToken(string scopeToken) { - ErrorUtilities.VerifyProtocol(!String.IsNullOrEmpty(scopeToken), OAuthStrings.InvalidScopeToken, scopeToken); + ErrorUtilities.VerifyProtocol(!string.IsNullOrEmpty(scopeToken), OAuthStrings.InvalidScopeToken, scopeToken); for (int i = 0; i < scopeToken.Length; i++) { // The allowed set of characters comes from OAuth 2.0 section 3.3 (draft 23) char ch = scopeToken[i]; diff --git a/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs b/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs index 3bd2169..636f490 100644 --- a/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs +++ b/src/DotNetOpenAuth.OAuth2/OAuth2/StandardAccessTokenAnalyzer.cs @@ -57,7 +57,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </remarks> public virtual bool TryValidateAccessToken(IDirectedProtocolMessage message, string accessToken, out string user, out HashSet<string> scope) { var accessTokenFormatter = AccessToken.CreateFormatter(this.AuthorizationServerPublicSigningKey, this.ResourceServerPrivateEncryptionKey); - var token = accessTokenFormatter.Deserialize(message, accessToken); + var token = accessTokenFormatter.Deserialize(message, accessToken, Protocol.access_token); user = token.User; scope = new HashSet<string>(token.Scope, OAuthUtilities.ScopeStringComparer); return true; diff --git a/src/DotNetOpenAuth.OpenId.Provider.UI/OpenId/Provider/IdentityEndpoint.cs b/src/DotNetOpenAuth.OpenId.Provider.UI/OpenId/Provider/IdentityEndpoint.cs index 43dd54d..efcabd8 100644 --- a/src/DotNetOpenAuth.OpenId.Provider.UI/OpenId/Provider/IdentityEndpoint.cs +++ b/src/DotNetOpenAuth.OpenId.Provider.UI/OpenId/Provider/IdentityEndpoint.cs @@ -164,8 +164,8 @@ namespace DotNetOpenAuth.OpenId.Provider { // We compare path and query with case sensitivity and host name without case sensitivity deliberately, // and the fragment will be asserted or cleared by the OP during authentication. if (normalizationArgs.NormalizedIdentifier != null && - (!String.Equals(normalizationArgs.NormalizedIdentifier.Host, normalizationArgs.UserSuppliedIdentifier.Host, StringComparison.OrdinalIgnoreCase) || - !String.Equals(normalizationArgs.NormalizedIdentifier.PathAndQuery, normalizationArgs.UserSuppliedIdentifier.PathAndQuery, StringComparison.Ordinal))) { + (!string.Equals(normalizationArgs.NormalizedIdentifier.Host, normalizationArgs.UserSuppliedIdentifier.Host, StringComparison.OrdinalIgnoreCase) || + !string.Equals(normalizationArgs.NormalizedIdentifier.PathAndQuery, normalizationArgs.UserSuppliedIdentifier.PathAndQuery, StringComparison.Ordinal))) { Page.Response.Redirect(normalizationArgs.NormalizedIdentifier.AbsoluteUri); } } diff --git a/src/DotNetOpenAuth.OpenId.Provider/DotNetOpenAuth.OpenId.Provider.csproj b/src/DotNetOpenAuth.OpenId.Provider/DotNetOpenAuth.OpenId.Provider.csproj index 53a1b8e..524415f 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/DotNetOpenAuth.OpenId.Provider.csproj +++ b/src/DotNetOpenAuth.OpenId.Provider/DotNetOpenAuth.OpenId.Provider.csproj @@ -31,11 +31,11 @@ <Compile Include="OpenId\Provider\Extensions\UI\UIRequestTools.cs" /> <Compile Include="OpenId\Provider\HmacShaAssociationProvider.cs" /> <Compile Include="OpenId\Messages\AssociateDiffieHellmanProviderRequest.cs" /> - <Compile Include="OpenId\Messages\AssociateDiffieHellmanProviderResponse.cs" Condition=" '$(ExcludeDiffieHellman)' != 'true' " /> + <Compile Include="OpenId\Messages\AssociateDiffieHellmanProviderResponse.cs" /> <Compile Include="OpenId\Messages\IAssociateRequestProvider.cs" /> <Compile Include="OpenId\Messages\AssociateRequestProviderTools.cs" /> - <Compile Include="OpenId\Messages\AssociateSuccessfulResponseProvider.cs" /> - <Compile Include="OpenId\Messages\AssociateSuccessfulResponseProviderContract.cs" /> + <Compile Include="OpenId\Messages\IAssociateSuccessfulResponseProvider.cs" /> + <Compile Include="OpenId\Messages\IAssociateSuccessfulResponseProviderContract.cs" /> <Compile Include="OpenId\Messages\AssociateUnencryptedResponseProvider.cs" /> <Compile Include="OpenId\Messages\CheckAuthenticationResponseProvider.cs" /> <Compile Include="OpenId\Provider\OpenIdProviderUtilities.cs" /> @@ -67,7 +67,7 @@ <Project>{3896A32A-E876-4C23-B9B8-78E17D134CD3}</Project> <Name>DotNetOpenAuth.OpenId</Name> </ProjectReference> - <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj" Condition=" '$(ExcludeDiffieHellman)' != 'true' "> + <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj" > <Project>{26DC877F-5987-48DD-9DDB-E62F2DE0E150}</Project> <Name>Org.Mentalis.Security.Cryptography</Name> </ProjectReference> diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateDiffieHellmanProviderRequest.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateDiffieHellmanProviderRequest.cs index 977ce71..00c9a6c 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateDiffieHellmanProviderRequest.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateDiffieHellmanProviderRequest.cs @@ -31,13 +31,9 @@ namespace DotNetOpenAuth.OpenId.Messages { /// The appropriate association response message. /// </returns> public IProtocolMessage CreateResponseCore() { -#if !ExcludeDiffieHellman var response = new AssociateDiffieHellmanProviderResponse(this.Version, this); response.AssociationType = this.AssociationType; return response; -#else - throw new NotSupportedException(); -#endif } } } diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateSuccessfulResponseProvider.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/IAssociateSuccessfulResponseProvider.cs index 215128c..070f235 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateSuccessfulResponseProvider.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/IAssociateSuccessfulResponseProvider.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="AssociateSuccessfulResponseProvider.cs" company="Outercurve Foundation"> +// <copyright file="IAssociateSuccessfulResponseProvider.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateSuccessfulResponseProviderContract.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/IAssociateSuccessfulResponseProviderContract.cs index c0a42e0..6788a84 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/AssociateSuccessfulResponseProviderContract.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Messages/IAssociateSuccessfulResponseProviderContract.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="AssociateSuccessfulResponseProviderContract.cs" company="Outercurve Foundation"> +// <copyright file="IAssociateSuccessfulResponseProviderContract.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/Behaviors/GsaIcamProfile.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/Behaviors/GsaIcamProfile.cs index a68028f..feb56eb 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/Behaviors/GsaIcamProfile.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/Behaviors/GsaIcamProfile.cs @@ -182,7 +182,7 @@ namespace DotNetOpenAuth.OpenId.Provider.Behaviors { /// <param name="maximumLifetime">The maximum lifetime.</param> /// <param name="securitySettings">The security settings to adjust.</param> private static void SetMaximumAssociationLifetimeToNotExceed(string associationType, TimeSpan maximumLifetime, ProviderSecuritySettings securitySettings) { - Contract.Requires(!String.IsNullOrEmpty(associationType)); + Contract.Requires(!string.IsNullOrEmpty(associationType)); Contract.Requires(maximumLifetime.TotalSeconds > 0); if (!securitySettings.AssociationLifetimes.ContainsKey(associationType) || securitySettings.AssociationLifetimes[associationType] > maximumLifetime) { diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/HmacShaAssociationProvider.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/HmacShaAssociationProvider.cs index 7a5b662..bdf3e9b 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/HmacShaAssociationProvider.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/HmacShaAssociationProvider.cs @@ -63,7 +63,7 @@ namespace DotNetOpenAuth.OpenId.Provider { Contract.Assert(protocol != null); // All the way up to the method call, the condition holds, yet we get a Requires failure next Contract.Assert(secret != null); - Contract.Assert(!String.IsNullOrEmpty(associationType)); + Contract.Assert(!string.IsNullOrEmpty(associationType)); var result = HmacShaAssociation.Create(protocol, associationType, handle, secret, lifetime); return result; } diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/IProviderAssociationStore.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/IProviderAssociationStore.cs index b23af2c..930abcd 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/IProviderAssociationStore.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/IProviderAssociationStore.cs @@ -67,7 +67,7 @@ namespace DotNetOpenAuth.OpenId.Provider { string IProviderAssociationStore.Serialize(byte[] secret, DateTime expiresUtc, bool privateAssociation) { Requires.NotNull(secret, "secret"); Requires.True(expiresUtc.Kind == DateTimeKind.Utc, "expiresUtc"); - Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); throw new NotImplementedException(); } diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/OpenIdProvider.cs index f7e49f2..72fdc80 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/OpenIdProvider.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/OpenIdProvider.cs @@ -256,7 +256,7 @@ namespace DotNetOpenAuth.OpenId.Provider { /// </remarks> /// <exception cref="ProtocolException">Thrown if the incoming message is recognized /// but deviates from the protocol specification irrecoverably.</exception> - public IRequest GetRequest(HttpRequestInfo httpRequestInfo) { + public IRequest GetRequest(HttpRequestBase httpRequestInfo) { Requires.NotNull(httpRequestInfo, "httpRequestInfo"); IDirectedProtocolMessage incomingMessage = null; @@ -266,7 +266,7 @@ namespace DotNetOpenAuth.OpenId.Provider { // If the incoming request does not resemble an OpenID message at all, // it's probably a user who just navigated to this URL, and we should // just return null so the host can display a message to the user. - if (httpRequestInfo.HttpMethod == "GET" && !httpRequestInfo.UrlBeforeRewriting.QueryStringContainPrefixedParameters(Protocol.Default.openid.Prefix)) { + if (httpRequestInfo.HttpMethod == "GET" && !httpRequestInfo.GetPublicFacingUrl().QueryStringContainPrefixedParameters(Protocol.Default.openid.Prefix)) { return null; } @@ -533,7 +533,7 @@ namespace DotNetOpenAuth.OpenId.Provider { /// <returns> /// Either the <see cref="IRequest"/> to return to the host site or null to indicate no response could be reasonably created and that the caller should rethrow the exception. /// </returns> - private IRequest GetErrorResponse(ProtocolException ex, HttpRequestInfo httpRequestInfo, IDirectedProtocolMessage incomingMessage) { + private IRequest GetErrorResponse(ProtocolException ex, HttpRequestBase httpRequestInfo, IDirectedProtocolMessage incomingMessage) { Requires.NotNull(ex, "ex"); Requires.NotNull(httpRequestInfo, "httpRequestInfo"); diff --git a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs index 916740c..594803d 100644 --- a/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs +++ b/src/DotNetOpenAuth.OpenId.Provider/OpenId/Provider/ProviderAssociationHandleEncoder.cs @@ -70,7 +70,7 @@ namespace DotNetOpenAuth.OpenId.Provider { var formatter = AssociationDataBag.CreateFormatter(this.cryptoKeyStore, AssociationHandleEncodingSecretBucket); AssociationDataBag bag; try { - bag = formatter.Deserialize(containingMessage, handle); + bag = formatter.Deserialize(containingMessage, handle, Protocol.Default.openid.assoc_handle); } catch (ProtocolException ex) { Logger.OpenId.Error("Rejecting an association because deserialization of the encoded handle failed.", ex); return null; diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdMobileTextBox.cs index baf8b44..b3d208a 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdMobileTextBox.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdMobileTextBox.cs @@ -325,7 +325,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { if (Page != null && !DesignMode) { // Validate new value by trying to construct a Uri based on it. - new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure. + new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), this.Page.ResolveUrl(value)); // throws an exception on failure. } else { // We can't fully test it, but it should start with either ~/ or a protocol. if (Regex.IsMatch(value, @"^https?://")) { @@ -603,7 +603,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { if (string.IsNullOrEmpty(this.ReturnToUrl)) { this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm); } else { - Uri returnTo = new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.ReturnToUrl); + Uri returnTo = new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), this.ReturnToUrl); this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm, returnTo); } this.Request.Mode = this.ImmediateMode ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; @@ -747,7 +747,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { Language = this.RequestLanguage, TimeZone = this.RequestTimeZone, PolicyUrl = string.IsNullOrEmpty(this.PolicyUrl) ? - null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(this.PolicyUrl)), + null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), this.Page.ResolveUrl(this.PolicyUrl)), }); } diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs index acd8c50..34c4df4 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs @@ -183,11 +183,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { if (!string.IsNullOrEmpty(formAuthData) && !string.Equals(viewstateAuthData, formAuthData, StringComparison.Ordinal)) { this.ViewState[AuthDataViewStateKey] = formAuthData; - Uri authUri = new Uri(formAuthData); - HttpRequestInfo clientResponseInfo = new HttpRequestInfo { - UrlBeforeRewriting = authUri, - }; - + HttpRequestBase clientResponseInfo = new HttpRequestInfo("GET", new Uri(formAuthData)); this.authenticationResponse = this.RelyingParty.GetResponse(clientResponseInfo); Logger.Controls.DebugFormat( "The {0} control checked for an authentication response and found: {1}", diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs index dfac2be..c730dea 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs @@ -395,7 +395,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { if (this.Page != null && !this.DesignMode) { // Validate new value by trying to construct a Uri based on it. - new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure. + new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), this.Page.ResolveUrl(value)); // throws an exception on failure. } else { // We can't fully test it, but it should start with either ~/ or a protocol. if (Regex.IsMatch(value, @"^https?://")) { @@ -919,7 +919,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { Uri returnToApproximation; if (this.ReturnToUrl != null) { string returnToResolvedPath = this.ResolveUrl(this.ReturnToUrl); - returnToApproximation = new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, returnToResolvedPath); + returnToApproximation = new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), returnToResolvedPath); } else { returnToApproximation = this.Page.Request.Url; } diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdTextBox.cs index a8af6e0..8ba689f 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdTextBox.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty.UI/OpenId/RelyingParty/OpenIdTextBox.cs @@ -696,7 +696,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { Language = this.RequestLanguage, TimeZone = this.RequestTimeZone, PolicyUrl = string.IsNullOrEmpty(this.PolicyUrl) ? - null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(this.PolicyUrl)), + null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().GetPublicFacingUrl(), this.Page.ResolveUrl(this.PolicyUrl)), }; // Only actually add the extension request if fields are actually being requested. diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj index 6fa3076..3ebd698 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/DotNetOpenAuth.OpenId.RelyingParty.csproj @@ -20,6 +20,7 @@ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> </PropertyGroup> <ItemGroup> + <Compile Include="OpenId\Interop\IOpenIdRelyingParty.cs" /> <Compile Include="OpenId\RelyingParty\Behaviors\AXFetchAsSregTransform.cs" /> <Compile Include="OpenId\RelyingParty\Behaviors\GsaIcamProfile.cs" /> <Compile Include="OpenId\ChannelElements\ExtensionsBindingElementRelyingParty.cs" /> @@ -33,9 +34,9 @@ <Compile Include="OpenId\Interop\AuthenticationResponseShim.cs" /> <Compile Include="OpenId\Interop\ClaimsResponseShim.cs" /> <Compile Include="OpenId\Interop\OpenIdRelyingPartyShim.cs" /> - <Compile Include="OpenId\Messages\AssociateDiffieHellmanRelyingPartyResponse.cs" Condition=" '$(ExcludeDiffieHellman)' != 'true' " /> + <Compile Include="OpenId\Messages\AssociateDiffieHellmanRelyingPartyResponse.cs" /> <Compile Include="OpenId\Messages\AssociateRequestRelyingParty.cs" /> - <Compile Include="OpenId\Messages\AssociateSuccessfulResponseRelyingPartyContract.cs" /> + <Compile Include="OpenId\Messages\IAssociateSuccessfulResponseRelyingPartyContract.cs" /> <Compile Include="OpenId\Messages\IAssociateSuccessfulResponseRelyingParty.cs" /> <Compile Include="OpenId\Messages\AssociateUnencryptedResponseRelyingParty.cs" /> <Compile Include="OpenId\RelyingParty\CryptoKeyStoreAsRelyingPartyAssociationStore.cs" /> @@ -70,7 +71,7 @@ <Project>{3896A32A-E876-4C23-B9B8-78E17D134CD3}</Project> <Name>DotNetOpenAuth.OpenId</Name> </ProjectReference> - <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj" Condition=" '$(ExcludeDiffieHellman)' != 'true' "> + <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj"> <Project>{26DC877F-5987-48DD-9DDB-E62F2DE0E150}</Project> <Name>Org.Mentalis.Security.Cryptography</Name> </ProjectReference> diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/OpenIdRelyingPartyMessageFactory.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/OpenIdRelyingPartyMessageFactory.cs index ea771e1..957fd1b 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/OpenIdRelyingPartyMessageFactory.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/OpenIdRelyingPartyMessageFactory.cs @@ -95,12 +95,12 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { // This is a special recognized error case that we create a special message for. message = new AssociateUnsuccessfulResponse(protocol.Version, associateRequest); } else if (message == null) { -#if !ExcludeDiffieHellman - var associateDiffieHellmanRequest = request as AssociateDiffieHellmanRequest; - if (associateDiffieHellmanRequest != null) { - message = new AssociateDiffieHellmanRelyingPartyResponse(protocol.Version, associateDiffieHellmanRequest); + if (OpenIdUtilities.IsDiffieHellmanPresent) { + var associateDiffieHellmanRequest = request as AssociateDiffieHellmanRequest; + if (associateDiffieHellmanRequest != null) { + message = new AssociateDiffieHellmanRelyingPartyResponse(protocol.Version, associateDiffieHellmanRequest); + } } -#endif var associateUnencryptedRequest = request as AssociateUnencryptedRequest; if (associateUnencryptedRequest != null) { diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/IOpenIdRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/IOpenIdRelyingParty.cs new file mode 100644 index 0000000..398c284 --- /dev/null +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/IOpenIdRelyingParty.cs @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------- +// <copyright file="IOpenIdRelyingParty.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Interop { + using System.Diagnostics.CodeAnalysis; + using System.Runtime.InteropServices; + using DotNetOpenAuth.Messaging; + + /// <summary> + /// The COM interface describing the DotNetOpenAuth functionality available to + /// COM client OpenID relying parties. + /// </summary> + [Guid("56BD3DB0-EE0D-4191-ADFC-1F3705CD2636")] + [InterfaceType(ComInterfaceType.InterfaceIsDual)] + public interface IOpenIdRelyingParty { + /// <summary> + /// Creates an authentication request to verify that a user controls + /// some given Identifier. + /// </summary> + /// <param name="userSuppliedIdentifier"> + /// The Identifier supplied by the user. This may be a URL, an XRI or i-name. + /// </param> + /// <param name="realm"> + /// The shorest URL that describes this relying party web site's address. + /// For example, if your login page is found at https://www.example.com/login.aspx, + /// your realm would typically be https://www.example.com/. + /// </param> + /// <param name="returnToUrl"> + /// The URL of the login page, or the page prepared to receive authentication + /// responses from the OpenID Provider. + /// </param> + /// <returns> + /// An authentication request object that describes the HTTP response to + /// send to the user agent to initiate the authentication. + /// </returns> + /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception> + string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl); + + /// <summary> + /// Creates an authentication request to verify that a user controls + /// some given Identifier. + /// </summary> + /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param> + /// <param name="realm">The shorest URL that describes this relying party web site's address. + /// For example, if your login page is found at https://www.example.com/login.aspx, + /// your realm would typically be https://www.example.com/.</param> + /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication + /// responses from the OpenID Provider.</param> + /// <param name="optionalSreg">A comma-delimited list of simple registration fields to request as optional.</param> + /// <param name="requiredSreg">A comma-delimited list of simple registration fields to request as required.</param> + /// <returns> + /// An authentication request object that describes the HTTP response to + /// send to the user agent to initiate the authentication. + /// </returns> + /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception> + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Accepted acronym")] + string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg); + + /// <summary> + /// Gets the result of a user agent's visit to his OpenId provider in an + /// authentication attempt. Null if no response is available. + /// </summary> + /// <param name="url">The incoming request URL .</param> + /// <param name="form">The form data that may have been included in the case of a POST request.</param> + /// <returns>The Provider's response to a previous authentication request, or null if no response is present.</returns> +#pragma warning disable 0618 // we're using the COM type properly + AuthenticationResponseShim ProcessAuthentication(string url, string form); +#pragma warning restore 0618 + } +}
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs index 97b3780..eb37d86 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Interop/OpenIdRelyingPartyShim.cs @@ -6,6 +6,7 @@ namespace DotNetOpenAuth.OpenId.Interop { using System; + using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.InteropServices; @@ -16,68 +17,6 @@ namespace DotNetOpenAuth.OpenId.Interop { using DotNetOpenAuth.OpenId.RelyingParty; /// <summary> - /// The COM interface describing the DotNetOpenAuth functionality available to - /// COM client OpenID relying parties. - /// </summary> - [Guid("56BD3DB0-EE0D-4191-ADFC-1F3705CD2636")] - [InterfaceType(ComInterfaceType.InterfaceIsDual)] - public interface IOpenIdRelyingParty { - /// <summary> - /// Creates an authentication request to verify that a user controls - /// some given Identifier. - /// </summary> - /// <param name="userSuppliedIdentifier"> - /// The Identifier supplied by the user. This may be a URL, an XRI or i-name. - /// </param> - /// <param name="realm"> - /// The shorest URL that describes this relying party web site's address. - /// For example, if your login page is found at https://www.example.com/login.aspx, - /// your realm would typically be https://www.example.com/. - /// </param> - /// <param name="returnToUrl"> - /// The URL of the login page, or the page prepared to receive authentication - /// responses from the OpenID Provider. - /// </param> - /// <returns> - /// An authentication request object that describes the HTTP response to - /// send to the user agent to initiate the authentication. - /// </returns> - /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception> - string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl); - - /// <summary> - /// Creates an authentication request to verify that a user controls - /// some given Identifier. - /// </summary> - /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param> - /// <param name="realm">The shorest URL that describes this relying party web site's address. - /// For example, if your login page is found at https://www.example.com/login.aspx, - /// your realm would typically be https://www.example.com/.</param> - /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication - /// responses from the OpenID Provider.</param> - /// <param name="optionalSreg">A comma-delimited list of simple registration fields to request as optional.</param> - /// <param name="requiredSreg">A comma-delimited list of simple registration fields to request as required.</param> - /// <returns> - /// An authentication request object that describes the HTTP response to - /// send to the user agent to initiate the authentication. - /// </returns> - /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception> - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Accepted acronym")] - string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg); - - /// <summary> - /// Gets the result of a user agent's visit to his OpenId provider in an - /// authentication attempt. Null if no response is available. - /// </summary> - /// <param name="url">The incoming request URL .</param> - /// <param name="form">The form data that may have been included in the case of a POST request.</param> - /// <returns>The Provider's response to a previous authentication request, or null if no response is present.</returns> -#pragma warning disable 0618 // we're using the COM type properly - AuthenticationResponseShim ProcessAuthentication(string url, string form); -#pragma warning restore 0618 - } - - /// <summary> /// Implementation of <see cref="IOpenIdRelyingParty"/>, providing a subset of the /// functionality available to .NET clients. /// </summary> @@ -173,12 +112,14 @@ namespace DotNetOpenAuth.OpenId.Interop { /// <param name="form">The form data that may have been included in the case of a POST request.</param> /// <returns>The Provider's response to a previous authentication request, or null if no response is present.</returns> public AuthenticationResponseShim ProcessAuthentication(string url, string form) { - HttpRequestInfo requestInfo = new HttpRequestInfo { UrlBeforeRewriting = new Uri(url) }; + string method = "GET"; + NameValueCollection formMap = null; if (!string.IsNullOrEmpty(form)) { - requestInfo.HttpMethod = "POST"; - requestInfo.InputStream = new MemoryStream(Encoding.Unicode.GetBytes(form)); + method = "POST"; + formMap = HttpUtility.ParseQueryString(form); } + HttpRequestBase requestInfo = new HttpRequestInfo(method, new Uri(url), form: formMap); var response = relyingParty.GetResponse(requestInfo); if (response != null) { return new AuthenticationResponseShim(response); diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateRequestRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateRequestRelyingParty.cs index 28deb20..1ac8488 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateRequestRelyingParty.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateRequestRelyingParty.cs @@ -68,15 +68,15 @@ namespace DotNetOpenAuth.OpenId.Messages { associateRequest.AssociationType = associationType; return associateRequest; } else { -#if !ExcludeDiffieHellman - var associateRequest = new AssociateDiffieHellmanRequest(provider.Version, provider.Uri); - associateRequest.AssociationType = associationType; - associateRequest.SessionType = sessionType; - associateRequest.InitializeRequest(); - return associateRequest; -#else - return null; -#endif + if (OpenIdUtilities.IsDiffieHellmanPresent) { + var associateRequest = new AssociateDiffieHellmanRequest(provider.Version, provider.Uri); + associateRequest.AssociationType = associationType; + associateRequest.SessionType = sessionType; + associateRequest.InitializeRequest(); + return associateRequest; + } else { + return null; + } } } } diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateSuccessfulResponseRelyingPartyContract.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/IAssociateSuccessfulResponseRelyingPartyContract.cs index 9da19d7..e870c33 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/AssociateSuccessfulResponseRelyingPartyContract.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/Messages/IAssociateSuccessfulResponseRelyingPartyContract.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="AssociateSuccessfulResponseRelyingPartyContract.cs" company="Outercurve Foundation"> +// <copyright file="IAssociateSuccessfulResponseRelyingPartyContract.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/IRelyingPartyAssociationStore.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/IRelyingPartyAssociationStore.cs index 1cf3e4c..a97449e 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/IRelyingPartyAssociationStore.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/IRelyingPartyAssociationStore.cs @@ -126,7 +126,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </returns> Association IRelyingPartyAssociationStore.GetAssociation(Uri providerEndpoint, string handle) { Requires.NotNull(providerEndpoint, "providerEndpoint"); - Contract.Requires(!String.IsNullOrEmpty(handle)); + Contract.Requires(!string.IsNullOrEmpty(handle)); throw new NotImplementedException(); } @@ -144,7 +144,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </remarks> bool IRelyingPartyAssociationStore.RemoveAssociation(Uri providerEndpoint, string handle) { Requires.NotNull(providerEndpoint, "providerEndpoint"); - Contract.Requires(!String.IsNullOrEmpty(handle)); + Contract.Requires(!string.IsNullOrEmpty(handle)); throw new NotImplementedException(); } diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs index aa53277..6e991d2 100644 --- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs +++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs @@ -502,12 +502,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { ////Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<IAuthenticationRequest>>(), el => el != null)); // Build the return_to URL - UriBuilder returnTo = new UriBuilder(this.Channel.GetRequestFromContext().UrlBeforeRewriting); + UriBuilder returnTo = new UriBuilder(this.Channel.GetRequestFromContext().GetPublicFacingUrl()); // Trim off any parameters with an "openid." prefix, and a few known others // to avoid carrying state from a prior login attempt. returnTo.Query = string.Empty; - NameValueCollection queryParams = this.Channel.GetRequestFromContext().QueryStringBeforeRewriting; + NameValueCollection queryParams = this.Channel.GetRequestFromContext().GetQueryStringBeforeRewriting(); var returnToParams = new Dictionary<string, string>(queryParams.Count); foreach (string key in queryParams) { if (!IsOpenIdSupportingParameter(key) && key != null) { @@ -564,7 +564,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </summary> /// <param name="httpRequestInfo">The HTTP request that may be carrying an authentication response from the Provider.</param> /// <returns>The processed authentication response if there is any; <c>null</c> otherwise.</returns> - public IAuthenticationResponse GetResponse(HttpRequestInfo httpRequestInfo) { + public IAuthenticationResponse GetResponse(HttpRequestBase httpRequestInfo) { Requires.NotNull(httpRequestInfo, "httpRequestInfo"); try { var message = this.Channel.ReadFromRequest(httpRequestInfo); @@ -619,7 +619,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </summary> /// <param name="request">The incoming HTTP request that is expected to carry an OpenID authentication response.</param> /// <returns>The HTTP response to send to this HTTP request.</returns> - public OutgoingWebResponse ProcessResponseFromPopup(HttpRequestInfo request) { + public OutgoingWebResponse ProcessResponseFromPopup(HttpRequestBase request) { Requires.NotNull(request, "request"); Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null); @@ -706,7 +706,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// The HTTP response to send to this HTTP request. /// </returns> [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "real word"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "iframe", Justification = "Code contracts")] - internal OutgoingWebResponse ProcessResponseFromPopup(HttpRequestInfo request, Action<AuthenticationStatus> callback) { + internal OutgoingWebResponse ProcessResponseFromPopup(HttpRequestBase request, Action<AuthenticationStatus> callback) { Requires.NotNull(request, "request"); Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null); diff --git a/src/DotNetOpenAuth.OpenId/DotNetOpenAuth.OpenId.csproj b/src/DotNetOpenAuth.OpenId/DotNetOpenAuth.OpenId.csproj index d80b104..95dccc1 100644 --- a/src/DotNetOpenAuth.OpenId/DotNetOpenAuth.OpenId.csproj +++ b/src/DotNetOpenAuth.OpenId/DotNetOpenAuth.OpenId.csproj @@ -28,7 +28,7 @@ <Compile Include="Configuration\OpenIdRelyingPartyElement.cs" /> <Compile Include="Configuration\OpenIdRelyingPartySecuritySettingsElement.cs" /> <Compile Include="Configuration\XriResolverElement.cs" /> - <Compile Include="OpenIdXrdsHelper.cs" /> + <Compile Include="OpenIdXrdsHelperRelyingParty.cs" /> <Compile Include="OpenId\Association.cs" /> <Compile Include="OpenId\AuthenticationRequestMode.cs" /> <Compile Include="OpenId\Behaviors\AXFetchAsSregTransformBase.cs" /> @@ -69,6 +69,7 @@ <Compile Include="OpenId\Extensions\OAuth\Constants.cs" /> <Compile Include="OpenId\Extensions\OAuth\AuthorizationDeclinedResponse.cs" /> <Compile Include="OpenId\Extensions\OpenIdExtensionFactoryAggregator.cs" /> + <Compile Include="OpenId\Extensions\SimpleRegistration\GenderEncoder.cs" /> <Compile Include="OpenId\Extensions\StandardOpenIdExtensionFactory.cs" /> <Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\AuthenticationPolicies.cs" /> <Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\Constants.cs" /> @@ -121,12 +122,12 @@ <Compile Include="OpenId\OpenIdXrdsHelper.cs" /> <Compile Include="OpenId\ProviderEndpointDescription.cs" /> <Compile Include="OpenId\Realm.cs" /> - <Compile Include="OpenId\RelyingPartyDescription.cs" /> - <Compile Include="OpenId\DiffieHellmanUtilities.cs" Condition=" '$(ExcludeDiffieHellman)' != 'true' " /> + <Compile Include="OpenId\RelyingPartyEndpointDescription.cs" /> + <Compile Include="OpenId\DiffieHellmanUtilities.cs" /> <Compile Include="OpenId\HmacShaAssociation.cs" /> <Compile Include="OpenId\Messages\AssociateUnencryptedRequest.cs" /> <Compile Include="OpenId\Messages\AssociateDiffieHellmanRequest.cs" /> - <Compile Include="OpenId\Messages\AssociateDiffieHellmanResponse.cs" Condition=" '$(ExcludeDiffieHellman)' != 'true' " /> + <Compile Include="OpenId\Messages\AssociateDiffieHellmanResponse.cs" /> <Compile Include="OpenId\Messages\AssociateRequest.cs" /> <Compile Include="OpenId\Messages\AssociateSuccessfulResponse.cs" /> <Compile Include="OpenId\Messages\AssociateUnencryptedResponse.cs" /> @@ -179,7 +180,7 @@ <Project>{60426312-6AE5-4835-8667-37EDEA670222}</Project> <Name>DotNetOpenAuth.Core</Name> </ProjectReference> - <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj" Condition=" '$(ExcludeDiffieHellman)' != 'true' "> + <ProjectReference Include="..\Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj"> <Project>{26DC877F-5987-48DD-9DDB-E62F2DE0E150}</Project> <Name>Org.Mentalis.Security.Cryptography</Name> </ProjectReference> diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Association.cs b/src/DotNetOpenAuth.OpenId/OpenId/Association.cs index 700b24e..764f4fa 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Association.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Association.cs @@ -222,7 +222,7 @@ namespace DotNetOpenAuth.OpenId { if (a.Handle != this.Handle || a.Issued != this.Issued || - !MessagingUtilities.Equals(a.TotalLifeLength, this.TotalLifeLength, TimeSpan.FromSeconds(1))) { + !MessagingUtilities.Equals(a.TotalLifeLength, this.TotalLifeLength, TimeSpan.FromSeconds(2))) { return false; } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ITamperResistantOpenIdMessage.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ITamperResistantOpenIdMessage.cs index 379e5e7..fb8c445 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ITamperResistantOpenIdMessage.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/ITamperResistantOpenIdMessage.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { using System; using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using DotNetOpenAuth.Messaging; @@ -39,6 +40,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// and if present in the response, "claimed_id" and "identity". /// Additional keys MAY be signed as part of the message. See Generating Signatures. /// </remarks> + [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1630:DocumentationTextMustContainWhitespace", Justification = "The samples are string literals.")] string SignedParameterOrder { get; set; } // TODO: make sure we have a unit test to verify that an incoming message with fewer signed fields than required will be rejected. } } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs index 357c02d..6b88b3f 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/OpenIdChannel.cs @@ -181,7 +181,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { byte[] keyValueEncoding = KeyValueFormEncoding.GetBytes(fields); OutgoingWebResponse preparedResponse = new OutgoingWebResponse(); - this.ApplyMessageTemplate(response, preparedResponse); + ApplyMessageTemplate(response, preparedResponse); preparedResponse.Headers.Add(HttpResponseHeader.ContentType, KeyValueFormContentType); preparedResponse.OriginalMessage = response; preparedResponse.ResponseStream = new MemoryStream(keyValueEncoding); diff --git a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs index ebe20d2..363ff28 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/ChannelElements/SigningBindingElement.cs @@ -121,7 +121,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <returns>The calculated signature of the method.</returns> protected string GetSignature(ITamperResistantOpenIdMessage signedMessage, Association association) { Requires.NotNull(signedMessage, "signedMessage"); - Requires.True(!String.IsNullOrEmpty(signedMessage.SignedParameterOrder), "signedMessage"); + Requires.True(!string.IsNullOrEmpty(signedMessage.SignedParameterOrder), "signedMessage"); Requires.NotNull(association, "association"); // Prepare the parts to sign, taking care to replace an openid.mode value diff --git a/src/DotNetOpenAuth.OpenId/OpenId/DiffieHellmanUtilities.cs b/src/DotNetOpenAuth.OpenId/OpenId/DiffieHellmanUtilities.cs index 5c18275..e15bd6e 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/DiffieHellmanUtilities.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/DiffieHellmanUtilities.cs @@ -22,12 +22,7 @@ namespace DotNetOpenAuth.OpenId { /// <summary> /// An array of known Diffie Hellman sessions, sorted by decreasing hash size. /// </summary> - private static DHSha[] diffieHellmanSessionTypes = new List<DHSha> { - new DHSha(SHA512.Create(), protocol => protocol.Args.SessionType.DH_SHA512), - new DHSha(SHA384.Create(), protocol => protocol.Args.SessionType.DH_SHA384), - new DHSha(SHA256.Create(), protocol => protocol.Args.SessionType.DH_SHA256), - new DHSha(SHA1.Create(), protocol => protocol.Args.SessionType.DH_SHA1), - } .ToArray(); + private static DHSha[] diffieHellmanSessionTypes = CreateSessionTypes(); /// <summary> /// Finds the hashing algorithm to use given an openid.session_type value. @@ -41,7 +36,7 @@ namespace DotNetOpenAuth.OpenId { Requires.NotNull(sessionType, "sessionType"); // We COULD use just First instead of FirstOrDefault, but we want to throw ProtocolException instead of InvalidOperationException. - DHSha match = diffieHellmanSessionTypes.FirstOrDefault(dhsha => String.Equals(dhsha.GetName(protocol), sessionType, StringComparison.Ordinal)); + DHSha match = diffieHellmanSessionTypes.FirstOrDefault(dhsha => string.Equals(dhsha.GetName(protocol), sessionType, StringComparison.Ordinal)); ErrorUtilities.VerifyProtocol(match != null, OpenIdStrings.NoSessionTypeFound, sessionType, protocol.Version); return match.Algorithm; } @@ -119,6 +114,23 @@ namespace DotNetOpenAuth.OpenId { } /// <summary> + /// Returns the value used to initialize the static field storing DH session types. + /// </summary> + /// <returns>A non-null, non-empty array.</returns> + /// <remarks>> + /// This is a method rather than being inlined to the field initializer to try to avoid + /// the CLR bug that crops up sometimes if we initialize arrays using object initializer syntax. + /// </remarks> + private static DHSha[] CreateSessionTypes() { + return new[] { + new DHSha(SHA512.Create(), protocol => protocol.Args.SessionType.DH_SHA512), + new DHSha(SHA384.Create(), protocol => protocol.Args.SessionType.DH_SHA384), + new DHSha(SHA256.Create(), protocol => protocol.Args.SessionType.DH_SHA256), + new DHSha(SHA1.Create(), protocol => protocol.Args.SessionType.DH_SHA1), + }; + } + + /// <summary> /// Provides access to a Diffie-Hellman session algorithm and its name. /// </summary> private class DHSha { diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Extensions/AttributeExchange/WellKnownAttributes.cs b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/AttributeExchange/WellKnownAttributes.cs index c48b804..e96ef2e 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Extensions/AttributeExchange/WellKnownAttributes.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/AttributeExchange/WellKnownAttributes.cs @@ -15,6 +15,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// You can use new ones directly without adding them to this class, and can even make /// up your own if you expect the other end to understand what you make up. /// </remarks> + [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1630:DocumentationTextMustContainWhitespace", Justification = "The samples are string literals.")] + [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1631:DocumentationMustMeetCharacterPercentage", Justification = "The samples are string literals.")] public static class WellKnownAttributes { /// <summary> /// Inherent attributes about a personality such as gender and bio. diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/Gender.cs b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/Gender.cs index 05cbfbb..c0b1c03 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/Gender.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/Gender.cs @@ -5,10 +5,6 @@ //----------------------------------------------------------------------- namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration { - using System; - using DotNetOpenAuth.Messaging; - using DotNetOpenAuth.Messaging.Reflection; - /// <summary> /// Indicates the gender of a user. /// </summary> @@ -23,48 +19,4 @@ namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration { /// </summary> Female, } - - /// <summary> - /// Encodes/decodes the Simple Registration Gender type to its string representation. - /// </summary> - internal class GenderEncoder : IMessagePartEncoder { - #region IMessagePartEncoder Members - - /// <summary> - /// Encodes the specified value. - /// </summary> - /// <param name="value">The value. Guaranteed to never be null.</param> - /// <returns> - /// The <paramref name="value"/> in string form, ready for message transport. - /// </returns> - public string Encode(object value) { - var gender = (Gender?)value; - if (gender.HasValue) { - switch (gender.Value) { - case Gender.Male: return Constants.Genders.Male; - case Gender.Female: return Constants.Genders.Female; - } - } - - return null; - } - - /// <summary> - /// Decodes the specified value. - /// </summary> - /// <param name="value">The string value carried by the transport. Guaranteed to never be null, although it may be empty.</param> - /// <returns> - /// The deserialized form of the given string. - /// </returns> - /// <exception cref="FormatException">Thrown when the string value given cannot be decoded into the required object type.</exception> - public object Decode(string value) { - switch (value) { - case Constants.Genders.Male: return SimpleRegistration.Gender.Male; - case Constants.Genders.Female: return SimpleRegistration.Gender.Female; - default: throw new FormatException(); - } - } - - #endregion - } }
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/GenderEncoder.cs b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/GenderEncoder.cs new file mode 100644 index 0000000..abc51c1 --- /dev/null +++ b/src/DotNetOpenAuth.OpenId/OpenId/Extensions/SimpleRegistration/GenderEncoder.cs @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------- +// <copyright file="GenderEncoder.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration { + using System; + using DotNetOpenAuth.Messaging.Reflection; + + /// <summary> + /// Encodes/decodes the Simple Registration Gender type to its string representation. + /// </summary> + internal class GenderEncoder : IMessagePartEncoder { + #region IMessagePartEncoder Members + + /// <summary> + /// Encodes the specified value. + /// </summary> + /// <param name="value">The value. Guaranteed to never be null.</param> + /// <returns> + /// The <paramref name="value"/> in string form, ready for message transport. + /// </returns> + public string Encode(object value) { + var gender = (Gender?)value; + if (gender.HasValue) { + switch (gender.Value) { + case Gender.Male: return Constants.Genders.Male; + case Gender.Female: return Constants.Genders.Female; + } + } + + return null; + } + + /// <summary> + /// Decodes the specified value. + /// </summary> + /// <param name="value">The string value carried by the transport. Guaranteed to never be null, although it may be empty.</param> + /// <returns> + /// The deserialized form of the given string. + /// </returns> + /// <exception cref="FormatException">Thrown when the string value given cannot be decoded into the required object type.</exception> + public object Decode(string value) { + switch (value) { + case Constants.Genders.Male: return SimpleRegistration.Gender.Male; + case Constants.Genders.Female: return SimpleRegistration.Gender.Female; + default: throw new FormatException(); + } + } + + #endregion + } +}
\ No newline at end of file diff --git a/src/DotNetOpenAuth.OpenId/OpenId/HmacShaAssociation.cs b/src/DotNetOpenAuth.OpenId/OpenId/HmacShaAssociation.cs index 7c3ea3d..5e3553d 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/HmacShaAssociation.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/HmacShaAssociation.cs @@ -24,28 +24,7 @@ namespace DotNetOpenAuth.OpenId { /// <summary> /// A list of HMAC-SHA algorithms in order of decreasing bit lengths. /// </summary> - private static HmacSha[] hmacShaAssociationTypes = new List<HmacSha> { - new HmacSha { - CreateHasher = secretKey => new HMACSHA512(secretKey), - GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA512, - BaseHashAlgorithm = SHA512.Create(), - }, - new HmacSha { - CreateHasher = secretKey => new HMACSHA384(secretKey), - GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA384, - BaseHashAlgorithm = SHA384.Create(), - }, - new HmacSha { - CreateHasher = secretKey => new HMACSHA256(secretKey), - GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA256, - BaseHashAlgorithm = SHA256.Create(), - }, - new HmacSha { - CreateHasher = secretKey => new HMACSHA1(secretKey), - GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA1, - BaseHashAlgorithm = SHA1.Create(), - }, - } .ToArray(); + private static HmacSha[] hmacShaAssociationTypes = CreateAssociationTypes(); /// <summary> /// The specific variety of HMAC-SHA this association is based on (whether it be HMAC-SHA1, HMAC-SHA256, etc.) @@ -95,7 +74,7 @@ namespace DotNetOpenAuth.OpenId { Requires.NotNullOrEmpty(associationType, "associationType"); Requires.NotNull(secret, "secret"); Contract.Ensures(Contract.Result<HmacShaAssociation>() != null); - HmacSha match = hmacShaAssociationTypes.FirstOrDefault(sha => String.Equals(sha.GetAssociationType(protocol), associationType, StringComparison.Ordinal)); + HmacSha match = hmacShaAssociationTypes.FirstOrDefault(sha => string.Equals(sha.GetAssociationType(protocol), associationType, StringComparison.Ordinal)); ErrorUtilities.VerifyProtocol(match != null, OpenIdStrings.NoAssociationTypeFoundByName, associationType); return new HmacShaAssociation(match, handle, secret, totalLifeLength); } @@ -125,7 +104,7 @@ namespace DotNetOpenAuth.OpenId { /// <returns>The length (in bytes) of the association secret.</returns> /// <exception cref="ProtocolException">Thrown if no association can be found by the given name.</exception> public static int GetSecretLength(Protocol protocol, string associationType) { - HmacSha match = hmacShaAssociationTypes.FirstOrDefault(shaType => String.Equals(shaType.GetAssociationType(protocol), associationType, StringComparison.Ordinal)); + HmacSha match = hmacShaAssociationTypes.FirstOrDefault(shaType => string.Equals(shaType.GetAssociationType(protocol), associationType, StringComparison.Ordinal)); ErrorUtilities.VerifyProtocol(match != null, OpenIdStrings.NoAssociationTypeFoundByName, associationType); return match.SecretLength; } @@ -161,11 +140,13 @@ namespace DotNetOpenAuth.OpenId { hashSizeInBits < securityRequirements.MinimumHashBitLength) { continue; } -#if !ExcludeDiffieHellman - sessionType = DiffieHellmanUtilities.GetNameForSize(protocol, hashSizeInBits); -#else - sessionType = requireMatchingDHSessionType ? null : protocol.Args.SessionType.NoEncryption; -#endif + + if (OpenIdUtilities.IsDiffieHellmanPresent) { + sessionType = DiffieHellmanUtilities.GetNameForSize(protocol, hashSizeInBits); + } else { + sessionType = requireMatchingDHSessionType ? null : protocol.Args.SessionType.NoEncryption; + } + if (requireMatchingDHSessionType && sessionType == null) { continue; } @@ -199,14 +180,14 @@ namespace DotNetOpenAuth.OpenId { return true; } -#if !ExcludeDiffieHellman - // When there _is_ a DH session, it must match in hash length with the association type. - int associationSecretLengthInBytes = GetSecretLength(protocol, associationType); - int sessionHashLengthInBytes = DiffieHellmanUtilities.Lookup(protocol, sessionType).HashSize / 8; - return associationSecretLengthInBytes == sessionHashLengthInBytes; -#else - return false; -#endif + if (OpenIdUtilities.IsDiffieHellmanPresent) { + // When there _is_ a DH session, it must match in hash length with the association type. + int associationSecretLengthInBytes = GetSecretLength(protocol, associationType); + int sessionHashLengthInBytes = DiffieHellmanUtilities.Lookup(protocol, sessionType).HashSize / 8; + return associationSecretLengthInBytes == sessionHashLengthInBytes; + } else { + return false; + } } /// <summary> @@ -235,6 +216,39 @@ namespace DotNetOpenAuth.OpenId { } /// <summary> + /// Returns the value used to initialize the static field storing association types. + /// </summary> + /// <returns>A non-null, non-empty array.</returns> + /// <remarks>> + /// This is a method rather than being inlined to the field initializer to try to avoid + /// the CLR bug that crops up sometimes if we initialize arrays using object initializer syntax. + /// </remarks> + private static HmacSha[] CreateAssociationTypes() { + return new[] { + new HmacSha { + CreateHasher = secretKey => new HMACSHA512(secretKey), + GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA512, + BaseHashAlgorithm = SHA512.Create(), + }, + new HmacSha { + CreateHasher = secretKey => new HMACSHA384(secretKey), + GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA384, + BaseHashAlgorithm = SHA384.Create(), + }, + new HmacSha { + CreateHasher = secretKey => new HMACSHA256(secretKey), + GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA256, + BaseHashAlgorithm = SHA256.Create(), + }, + new HmacSha { + CreateHasher = secretKey => new HMACSHA1(secretKey), + GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA1, + BaseHashAlgorithm = SHA1.Create(), + }, + }; + } + + /// <summary> /// Provides information about some HMAC-SHA hashing algorithm that OpenID supports. /// </summary> private class HmacSha { diff --git a/src/DotNetOpenAuth.OpenId/OpenId/IdentifierDiscoveryResult.cs b/src/DotNetOpenAuth.OpenId/OpenId/IdentifierDiscoveryResult.cs index 137ab28..ab69bf6 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/IdentifierDiscoveryResult.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/IdentifierDiscoveryResult.cs @@ -110,7 +110,7 @@ namespace DotNetOpenAuth.OpenId { XriIdentifier xri = this.ClaimedIdentifier as XriIdentifier; UriIdentifier uri = this.ClaimedIdentifier as UriIdentifier; if (xri != null) { - if (this.UserSuppliedIdentifier == null || String.Equals(this.UserSuppliedIdentifier, this.ClaimedIdentifier, StringComparison.OrdinalIgnoreCase)) { + if (this.UserSuppliedIdentifier == null || string.Equals(this.UserSuppliedIdentifier, this.ClaimedIdentifier, StringComparison.OrdinalIgnoreCase)) { this.friendlyIdentifierForDisplay = this.ClaimedIdentifier; } else { this.friendlyIdentifierForDisplay = this.UserSuppliedIdentifier; diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/AssociateDiffieHellmanRequest.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/AssociateDiffieHellmanRequest.cs index ebe9f34..ed96ce7 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/AssociateDiffieHellmanRequest.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/AssociateDiffieHellmanRequest.cs @@ -12,9 +12,7 @@ namespace DotNetOpenAuth.OpenId.Messages { using System.Text; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Reflection; -#if !ExcludeDiffieHellman using Org.Mentalis.Security.Cryptography; -#endif /// <summary> /// An OpenID direct request from Relying Party to Provider to initiate an association that uses Diffie-Hellman encryption. @@ -78,7 +76,6 @@ namespace DotNetOpenAuth.OpenId.Messages { [MessagePart("openid.dh_consumer_public", IsRequired = true, AllowEmpty = false)] internal byte[] DiffieHellmanConsumerPublic { get; set; } -#if !ExcludeDiffieHellman /// <summary> /// Gets the Diffie-Hellman algorithm. /// </summary> @@ -86,13 +83,11 @@ namespace DotNetOpenAuth.OpenId.Messages { /// This property is initialized with a call to <see cref="InitializeRequest"/>. /// </remarks> internal DiffieHellman Algorithm { get; private set; } -#endif /// <summary> /// Called by the Relying Party to initialize the Diffie-Hellman algorithm and consumer public key properties. /// </summary> internal void InitializeRequest() { -#if !ExcludeDiffieHellman if (this.DiffieHellmanModulus == null || this.DiffieHellmanGen == null) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.DiffieHellmanRequiredPropertiesNotSet, string.Join(", ", new string[] { "DiffieHellmanModulus", "DiffieHellmanGen" }))); } @@ -100,9 +95,6 @@ namespace DotNetOpenAuth.OpenId.Messages { this.Algorithm = new DiffieHellmanManaged(this.DiffieHellmanModulus ?? DefaultMod, this.DiffieHellmanGen ?? DefaultGen, DefaultX); byte[] consumerPublicKeyExchange = this.Algorithm.CreateKeyExchange(); this.DiffieHellmanConsumerPublic = DiffieHellmanUtilities.EnsurePositive(consumerPublicKeyExchange); -#else - throw new NotSupportedException(); -#endif } } } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/IOpenIdMessageExtension.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/IOpenIdMessageExtension.cs index b1321f1..dabb752 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/IOpenIdMessageExtension.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/IOpenIdMessageExtension.cs @@ -72,7 +72,7 @@ namespace DotNetOpenAuth.OpenId.Messages { /// </summary> string IOpenIdMessageExtension.TypeUri { get { - Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); throw new NotImplementedException(); } } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/IndirectSignedResponse.cs index 46c5d35..8bceb68 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/IndirectSignedResponse.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/IndirectSignedResponse.cs @@ -26,6 +26,8 @@ namespace DotNetOpenAuth.OpenId.Messages { /// </summary> [DebuggerDisplay("OpenID {Version} {Mode} (no id assertion)")] [Serializable] + [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1630:DocumentationTextMustContainWhitespace", Justification = "The samples are string literals.")] + [SuppressMessage("Microsoft.StyleCop.CSharp.DocumentationRules", "SA1631:DocumentationMustMeetCharacterPercentage", Justification = "The samples are string literals.")] internal class IndirectSignedResponse : IndirectResponseBase, ITamperResistantOpenIdMessage { /// <summary> /// The allowed date/time formats for the response_nonce parameter. diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs index c6cd967..43fd6f5 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/NegativeAssertionResponse.cs @@ -72,9 +72,9 @@ namespace DotNetOpenAuth.OpenId.Messages { if (this.OriginatingRequest != null) { return this.OriginatingRequest.Immediate; } else { - if (String.Equals(this.Mode, Protocol.Args.Mode.setup_needed, StringComparison.Ordinal)) { + if (string.Equals(this.Mode, Protocol.Args.Mode.setup_needed, StringComparison.Ordinal)) { return true; - } else if (String.Equals(this.Mode, Protocol.Args.Mode.cancel, StringComparison.Ordinal)) { + } else if (string.Equals(this.Mode, Protocol.Args.Mode.cancel, StringComparison.Ordinal)) { return false; } else { throw ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, Protocol.openid.mode, this.Mode); @@ -99,7 +99,7 @@ namespace DotNetOpenAuth.OpenId.Messages { base.EnsureValidMessage(); // Since there are a couple of negative assertion modes, ensure that the mode given is one of the allowed ones. - ErrorUtilities.VerifyProtocol(String.Equals(this.Mode, Protocol.Args.Mode.setup_needed, StringComparison.Ordinal) || String.Equals(this.Mode, Protocol.Args.Mode.cancel, StringComparison.Ordinal), MessagingStrings.UnexpectedMessagePartValue, Protocol.openid.mode, this.Mode); + ErrorUtilities.VerifyProtocol(string.Equals(this.Mode, Protocol.Args.Mode.setup_needed, StringComparison.Ordinal) || string.Equals(this.Mode, Protocol.Args.Mode.cancel, StringComparison.Ordinal), MessagingStrings.UnexpectedMessagePartValue, Protocol.openid.mode, this.Mode); if (this.Immediate && Protocol.Version.Major < 2) { ErrorUtilities.VerifyProtocol(this.UserSetupUrl != null, OpenIdStrings.UserSetupUrlRequiredInImmediateNegativeResponse); diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Messages/SignedResponseRequest.cs b/src/DotNetOpenAuth.OpenId/OpenId/Messages/SignedResponseRequest.cs index c300e04..a2ebb64 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Messages/SignedResponseRequest.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Messages/SignedResponseRequest.cs @@ -58,7 +58,7 @@ namespace DotNetOpenAuth.OpenId.Messages { /// </summary> /// <value><c>true</c> if using OpenID immediate mode; otherwise, <c>false</c>.</value> internal bool Immediate { - get { return String.Equals(this.Mode, Protocol.Args.Mode.checkid_immediate, StringComparison.Ordinal); } + get { return string.Equals(this.Mode, Protocol.Args.Mode.checkid_immediate, StringComparison.Ordinal); } } /// <summary> diff --git a/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs b/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs index 1b848f9..a5202de 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/OpenIdUtilities.cs @@ -10,14 +10,15 @@ namespace DotNetOpenAuth.OpenId { using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Globalization; + using System.IO; using System.Linq; - using System.Text; using System.Text.RegularExpressions; + using System.Web; using System.Web.UI; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId.ChannelElements; using DotNetOpenAuth.OpenId.Extensions; - using DotNetOpenAuth.OpenId.Messages; + using Org.Mentalis.Security.Cryptography; /// <summary> /// A set of utilities especially useful to OpenID. @@ -29,11 +30,46 @@ namespace DotNetOpenAuth.OpenId { internal const string CustomParameterPrefix = "dnoa."; /// <summary> + /// A static variable that carries the results of a check for the presence of + /// assemblies that are required for the Diffie-Hellman algorithm. + /// </summary> + private static bool? diffieHellmanPresent; + + /// <summary> + /// Gets a value indicating whether Diffie Hellman is available in this installation. + /// </summary> + /// <value> + /// <c>true</c> if Diffie-Hellman functionality is present; otherwise, <c>false</c>. + /// </value> + internal static bool IsDiffieHellmanPresent { + get { + if (!diffieHellmanPresent.HasValue) { + try { + LoadDiffieHellmanTypes(); + diffieHellmanPresent = true; + } catch (FileNotFoundException) { + diffieHellmanPresent = false; + } catch (TypeLoadException) { + diffieHellmanPresent = false; + } + + if (diffieHellmanPresent.Value) { + Logger.OpenId.Info("Diffie-Hellman supporting assemblies found and loaded."); + } else { + Logger.OpenId.Warn("Diffie-Hellman supporting assemblies failed to load. Only associations with HTTPS OpenID Providers will be supported."); + } + } + + return diffieHellmanPresent.Value; + } + } + + /// <summary> /// Creates a random association handle. /// </summary> /// <returns>The association handle.</returns> public static string GenerateRandomAssociationHandle() { - Contract.Ensures(!String.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); // Generate the handle. It must be unique, and preferably unpredictable, // so we use a time element and a random data element to generate it. @@ -115,7 +151,7 @@ namespace DotNetOpenAuth.OpenId { /// <param name="requestContext">The request context.</param> /// <returns>The fully-qualified realm.</returns> [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using ctor for validation.")] - internal static UriBuilder GetResolvedRealm(Page page, string realm, HttpRequestInfo requestContext) { + internal static UriBuilder GetResolvedRealm(Page page, string realm, HttpRequestBase requestContext) { Requires.NotNull(page, "page"); Requires.NotNull(requestContext, "requestContext"); @@ -134,7 +170,7 @@ namespace DotNetOpenAuth.OpenId { string realmNoWildcard = Regex.Replace(realm, @"^(\w+://)\*\.", matchDelegate); UriBuilder fullyQualifiedRealm = new UriBuilder( - new Uri(requestContext.UrlBeforeRewriting, page.ResolveUrl(realmNoWildcard))); + new Uri(requestContext.GetPublicFacingUrl(), page.ResolveUrl(realmNoWildcard))); if (foundWildcard) { fullyQualifiedRealm.Host = "*." + fullyQualifiedRealm.Host; @@ -168,5 +204,15 @@ namespace DotNetOpenAuth.OpenId { ErrorUtilities.VerifyOperation(aggregator != null, OpenIdStrings.UnsupportedChannelConfiguration); return aggregator.Factories; } + + /// <summary> + /// Loads the Diffie-Hellman assemblies. + /// </summary> + /// <exception cref="FileNotFoundException">Thrown if the DH assemblies are missing.</exception> + private static void LoadDiffieHellmanTypes() { + // This seeming no-op instruction is enough for the CLR to throw a FileNotFoundException + // If the assemblies are missing. + new DiffieHellmanManaged(); + } } } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/Realm.cs b/src/DotNetOpenAuth.OpenId/OpenId/Realm.cs index 5c2ff8b..d682542 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/Realm.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/Realm.cs @@ -126,8 +126,8 @@ namespace DotNetOpenAuth.OpenId { Requires.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired); Contract.Ensures(Contract.Result<Realm>() != null); - HttpRequestInfo requestInfo = new HttpRequestInfo(HttpContext.Current.Request); - UriBuilder realmUrl = new UriBuilder(requestInfo.UrlBeforeRewriting); + HttpRequestBase requestInfo = new HttpRequestWrapper(HttpContext.Current.Request); + UriBuilder realmUrl = new UriBuilder(requestInfo.GetPublicFacingUrl()); realmUrl.Path = HttpContext.Current.Request.ApplicationPath; realmUrl.Query = null; realmUrl.Fragment = null; diff --git a/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequestContract.cs b/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequestContract.cs index fa16c41..4ddc6ae 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequestContract.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/RelyingParty/IAuthenticationRequestContract.cs @@ -74,7 +74,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { void IAuthenticationRequest.AddCallbackArguments(IDictionary<string, string> arguments) { Requires.NotNull(arguments, "arguments"); - Requires.True(arguments.Keys.All(k => !String.IsNullOrEmpty(k)), "arguments"); + Requires.True(arguments.Keys.All(k => !string.IsNullOrEmpty(k)), "arguments"); Requires.True(arguments.Values.All(v => v != null), "arguments"); throw new NotImplementedException(); } diff --git a/src/DotNetOpenAuth.OpenId/OpenId/RelyingPartyDescription.cs b/src/DotNetOpenAuth.OpenId/OpenId/RelyingPartyEndpointDescription.cs index a671090..f0d3b6a 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/RelyingPartyDescription.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/RelyingPartyEndpointDescription.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="RelyingPartyDescription.cs" company="Outercurve Foundation"> +// <copyright file="RelyingPartyEndpointDescription.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.OpenId/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth.OpenId/OpenId/UriIdentifier.cs index 307ba90..2048b0f 100644 --- a/src/DotNetOpenAuth.OpenId/OpenId/UriIdentifier.cs +++ b/src/DotNetOpenAuth.OpenId/OpenId/UriIdentifier.cs @@ -349,7 +349,7 @@ namespace DotNetOpenAuth.OpenId { // If this identifier already uses SSL for initial discovery, return one // that guarantees it will be used throughout the discovery process. - if (String.Equals(Uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) { + if (string.Equals(Uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) { secureIdentifier = new UriIdentifier(this.Uri, true); return true; } diff --git a/src/DotNetOpenAuth.OpenId/OpenIdXrdsHelper.cs b/src/DotNetOpenAuth.OpenId/OpenIdXrdsHelperRelyingParty.cs index 818704e..4e3221f 100644 --- a/src/DotNetOpenAuth.OpenId/OpenIdXrdsHelper.cs +++ b/src/DotNetOpenAuth.OpenId/OpenIdXrdsHelperRelyingParty.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// <copyright file="OpenIdXrdsHelper.cs" company="Outercurve Foundation"> +// <copyright file="OpenIdXrdsHelperRelyingParty.cs" company="Outercurve Foundation"> // Copyright (c) Outercurve Foundation. All rights reserved. // </copyright> //----------------------------------------------------------------------- diff --git a/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs b/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs index ac98205..3f6d4c9 100644 --- a/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs +++ b/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs @@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Test.Configuration { [TestFixture] public class SectionTests { - [TestCase] + [Test] public void UntrustedWebRequest() { var uwr = DotNetOpenAuthSection.Messaging.UntrustedWebRequest; @@ -29,12 +29,12 @@ namespace DotNetOpenAuth.Test.Configuration { Assert.IsTrue(uwr.WhitelistHostsRegex.KeysAsStrings.Contains(".+trusted.+")); } - [TestCase] + [Test] public void OpenIdMaxAuthenticationTime() { Assert.AreEqual(TimeSpan.Parse("00:08:17"), OpenIdElement.Configuration.MaxAuthenticationTime); } - [TestCase] + [Test] public void OpenIdRelyingParty() { var rp = OpenIdElement.Configuration.RelyingParty; Assert.IsNull(rp.ApplicationStore.CustomType); @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.Configuration { Assert.IsFalse(rp.SecuritySettings.RequireSsl); } - [TestCase] + [Test] public void OpenIdProvider() { var op = OpenIdElement.Configuration.Provider; Assert.IsNull(op.ApplicationStore.CustomType); diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index af0e09a..00c1bb4 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -91,7 +91,7 @@ </CodeContractsCustomRewriterAssembly> <CodeContractsCustomRewriterClass> </CodeContractsCustomRewriterClass> - <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsRuntimeCheckingLevel>None</CodeContractsRuntimeCheckingLevel> <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> @@ -130,7 +130,7 @@ <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> <ErrorReport>prompt</ErrorReport> - <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> + <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> <CodeContractsCustomRewriterAssembly> </CodeContractsCustomRewriterAssembly> <CodeContractsCustomRewriterClass> @@ -221,6 +221,7 @@ <Compile Include="Mocks\CoordinatingOAuth2AuthServerChannel.cs" /> <Compile Include="Mocks\CoordinatingOutgoingWebResponse.cs" /> <Compile Include="Mocks\CoordinatingOAuthConsumerChannel.cs" /> + <Compile Include="Mocks\IBaseMessageExplicitMembers.cs" /> <Compile Include="Mocks\InMemoryTokenManager.cs" /> <Compile Include="Mocks\MockHttpRequest.cs" /> <Compile Include="Mocks\MockIdentifier.cs" /> @@ -242,6 +243,7 @@ <Compile Include="Mocks\TestChannel.cs" /> <Compile Include="Mocks\TestMessage.cs" /> <Compile Include="Mocks\TestMessageFactory.cs" /> + <Compile Include="OAuth2\AuthorizationServerTests.cs" /> <Compile Include="OAuth2\MessageFactoryTests.cs" /> <Compile Include="OAuth2\UserAgentClientAuthorizeTests.cs" /> <Compile Include="OAuth2\OAuth2Coordinator.cs" /> diff --git a/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs b/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs index 43890b6..5c9ed41 100644 --- a/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs +++ b/src/DotNetOpenAuth.Test/Hosting/AspNetHost.cs @@ -38,8 +38,7 @@ namespace DotNetOpenAuth.Test.Hosting { } public static AspNetHost CreateHost(string webDirectory) { - AspNetHost host = (AspNetHost)ApplicationHost. - CreateApplicationHost(typeof(AspNetHost), "/", webDirectory); + AspNetHost host = (AspNetHost)ApplicationHost.CreateApplicationHost(typeof(AspNetHost), "/", webDirectory); return host; } diff --git a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs index 549b742..0f3f6e9 100644 --- a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs +++ b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.Hosting { [TestFixture, Category("HostASPNET")] public class HostingTests : TestBase { - [TestCase] + [Test] public void AspHostBasicTest() { try { using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) { diff --git a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs index b6dd02a..acd41bc 100644 --- a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs @@ -15,7 +15,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings { [TestFixture] public class StandardExpirationBindingElementTests : MessagingTestBase { - [TestCase] + [Test] public void SendSetsTimestamp() { TestExpiringMessage message = new TestExpiringMessage(MessageTransport.Indirect); message.Recipient = new Uri("http://localtest"); @@ -26,13 +26,13 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings { Assert.IsTrue(DateTime.UtcNow - ((IExpiringProtocolMessage)message).UtcCreationDate < TimeSpan.FromSeconds(3), "The timestamp on the message was not set on send."); } - [TestCase] + [Test] public void VerifyGoodTimestampIsAccepted() { this.Channel = CreateChannel(MessageProtections.Expiration); this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false); } - [TestCase] + [Test] public void VerifyFutureTimestampWithinClockSkewIsAccepted() { this.Channel = CreateChannel(MessageProtections.Expiration); this.ParameterizedReceiveProtectedTest(DateTime.UtcNow + DotNetOpenAuthSection.Messaging.MaximumClockSkew - TimeSpan.FromSeconds(1), false); diff --git a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs index a429e17..34c3a85 100644 --- a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings { /// <summary> /// Verifies that the generated nonce includes random characters. /// </summary> - [TestCase] + [Test] public void RandomCharactersTest() { Assert.IsNotNull(this.nonceElement.ProcessOutgoingMessage(this.message)); Assert.IsNotNull(this.message.Nonce, "No nonce was set on the message."); @@ -56,7 +56,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings { /// <summary> /// Verifies that a message is received correctly. /// </summary> - [TestCase] + [Test] public void ValidMessageReceivedTest() { this.message.Nonce = "a"; Assert.IsNotNull(this.nonceElement.ProcessIncomingMessage(this.message)); @@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings { /// <summary> /// Verifies that a message that doesn't have a string of random characters is received correctly. /// </summary> - [TestCase] + [Test] public void ValidMessageNoNonceReceivedTest() { this.message.Nonce = string.Empty; this.nonceElement.AllowZeroLengthNonce = true; diff --git a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs index 2d103d1..425f5f3 100644 --- a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs @@ -24,12 +24,12 @@ namespace DotNetOpenAuth.Test.Messaging { new TestBadChannel(true); } - [TestCase] + [Test] public void ReadFromRequestQueryString() { this.ParameterizedReceiveTest("GET"); } - [TestCase] + [Test] public void ReadFromRequestForm() { this.ParameterizedReceiveTest("POST"); } @@ -68,7 +68,7 @@ namespace DotNetOpenAuth.Test.Messaging { this.Channel.PrepareResponse(message); } - [TestCase] + [Test] public void SendIndirectMessage301Get() { TestDirectedMessage message = new TestDirectedMessage(MessageTransport.Indirect); GetStandardTestMessage(FieldFill.CompleteBeforeBindings, message); @@ -109,7 +109,7 @@ namespace DotNetOpenAuth.Test.Messaging { badChannel.Create301RedirectResponse(message, null); } - [TestCase] + [Test] public void SendIndirectMessageFormPost() { // We craft a very large message to force fallback to form POST. // We'll also stick some HTML reserved characters in the string value @@ -183,13 +183,13 @@ namespace DotNetOpenAuth.Test.Messaging { badChannel.Receive(null, null); } - [TestCase] + [Test] public void ReceiveUnrecognizedMessage() { TestBadChannel badChannel = new TestBadChannel(false); Assert.IsNull(badChannel.Receive(new Dictionary<string, string>(), null)); } - [TestCase] + [Test] public void ReadFromRequestWithContext() { var fields = GetStandardTestFields(FieldFill.AllRequired); TestMessage expectedMessage = GetStandardTestMessage(FieldFill.AllRequired); @@ -214,7 +214,7 @@ namespace DotNetOpenAuth.Test.Messaging { badChannel.ReadFromRequest(null); } - [TestCase] + [Test] public void SendReplayProtectedMessageSetsNonce() { TestReplayProtectedMessage message = new TestReplayProtectedMessage(MessageTransport.Indirect); message.Recipient = new Uri("http://localtest"); @@ -230,7 +230,7 @@ namespace DotNetOpenAuth.Test.Messaging { this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, true); } - [TestCase] + [Test] public void ReceivedReplayProtectedMessageJustOnce() { this.Channel = CreateChannel(MessageProtections.ReplayProtection); this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false); @@ -259,7 +259,7 @@ namespace DotNetOpenAuth.Test.Messaging { channel.ProcessOutgoingMessageTestHook(new TestSignedDirectedMessage()); } - [TestCase] + [Test] public void BindingElementsOrdering() { IChannelBindingElement transformA = new MockTransformationBindingElement("a"); IChannelBindingElement transformB = new MockTransformationBindingElement("b"); diff --git a/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs b/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs index 6b1caaa..f425563 100644 --- a/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.Messaging { this.generatorCompleted = 0; } - [TestCase] + [Test] public void EnumerableCache() { // Baseline var generator = this.NumberGenerator(); @@ -58,7 +58,7 @@ namespace DotNetOpenAuth.Test.Messaging { CollectionAssert.AreEqual(list1, list4); } - [TestCase] + [Test] public void GeneratesOnlyRequiredElements() { var generator = this.NumberGenerator().CacheGeneratedResults(); Assert.AreEqual(0, this.generatorInvocations); @@ -67,28 +67,28 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreEqual(0, this.generatorCompleted, "Only taking part of the list should not have completed the generator."); } - [TestCase] + [Test] public void PassThruDoubleCache() { var cache1 = this.NumberGenerator().CacheGeneratedResults(); var cache2 = cache1.CacheGeneratedResults(); Assert.AreSame(cache1, cache2, "Two caches were set up rather than just sharing the first one."); } - [TestCase] + [Test] public void PassThruList() { var list = this.NumberGenerator().ToList(); var cache = list.CacheGeneratedResults(); Assert.AreSame(list, cache); } - [TestCase] + [Test] public void PassThruArray() { var array = this.NumberGenerator().ToArray(); var cache = array.CacheGeneratedResults(); Assert.AreSame(array, cache); } - [TestCase] + [Test] public void PassThruCollection() { var collection = new Collection<int>(); var cache = collection.CacheGeneratedResults(); diff --git a/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs index f58980a..10aeef1 100644 --- a/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.Messaging { ErrorUtilities.VerifyArgumentNotNull(null, "someArg"); } - [TestCase] + [Test] public void VerifyArgumentNotNullDoesNotThrow() { ErrorUtilities.VerifyArgumentNotNull("hi", "someArg"); } @@ -31,7 +31,7 @@ namespace DotNetOpenAuth.Test.Messaging { ErrorUtilities.VerifyNonZeroLength(string.Empty, "someArg"); } - [TestCase] + [Test] public void VerifyNonZeroLengthOnNonEmpty() { ErrorUtilities.VerifyNonZeroLength("some Value", "someArg"); } diff --git a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs index dc1f633..fbe1d6b 100644 --- a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs @@ -13,27 +13,8 @@ namespace DotNetOpenAuth.Test.Messaging { [TestFixture] public class HttpRequestInfoTests : TestBase { - [TestCase] - public void CtorDefault() { - HttpRequestInfo info = new HttpRequestInfo(); - Assert.AreEqual("GET", info.HttpMethod); - } - - [TestCase] - public void CtorRequest() { - HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b"); - ////request.Headers["headername"] = "headervalue"; // PlatformNotSupportedException prevents us mocking this up - HttpRequestInfo info = new HttpRequestInfo(request); - Assert.AreEqual(request.Headers["headername"], info.Headers["headername"]); - Assert.AreEqual(request.Url.Query, info.Query); - Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]); - Assert.AreEqual(request.Url, info.Url); - Assert.AreEqual(request.Url, info.UrlBeforeRewriting); - Assert.AreEqual(request.HttpMethod, info.HttpMethod); - } - // All these tests are ineffective because ServerVariables[] cannot be set. - ////[TestCase] + ////[Test] ////public void CtorRequestWithDifferentPublicHttpHost() { //// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b"); //// request.ServerVariables["HTTP_HOST"] = "publichost"; @@ -44,7 +25,7 @@ namespace DotNetOpenAuth.Test.Messaging { //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]); ////} - ////[TestCase] + ////[Test] ////public void CtorRequestWithDifferentPublicHttpsHost() { //// HttpRequest request = new HttpRequest("file", "https://someserver?a=b", "a=b"); //// request.ServerVariables["HTTP_HOST"] = "publichost"; @@ -55,7 +36,7 @@ namespace DotNetOpenAuth.Test.Messaging { //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]); ////} - ////[TestCase] + ////[Test] ////public void CtorRequestWithDifferentPublicHostNonstandardPort() { //// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b"); //// request.ServerVariables["HTTP_HOST"] = "publichost:550"; @@ -66,7 +47,7 @@ namespace DotNetOpenAuth.Test.Messaging { //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]); ////} - ////[TestCase] + ////[Test] ////public void CtorRequestWithDifferentPublicIPv6Host() { //// HttpRequest request = new HttpRequest("file", "http://[fe80::587e:c6e5:d3aa:657a]:8089/v3.1/", ""); //// request.ServerVariables["HTTP_HOST"] = "[fe80::587e:c6e5:d3aa:657b]:8089"; @@ -77,34 +58,24 @@ namespace DotNetOpenAuth.Test.Messaging { ////} /// <summary> - /// Checks that a property dependent on another null property - /// doesn't generate a NullReferenceException. - /// </summary> - [TestCase] - public void QueryBeforeSettingUrl() { - HttpRequestInfo info = new HttpRequestInfo(); - Assert.IsNull(info.Query); - } - - /// <summary> /// Verifies that looking up a querystring variable is gracefully handled without a query in the URL. /// </summary> - [TestCase] + [Test] public void QueryStringLookupWithoutQuery() { - HttpRequestInfo info = new HttpRequestInfo(); + var info = new HttpRequestInfo("GET", new Uri("http://somehost/somepath")); Assert.IsNull(info.QueryString["hi"]); } /// <summary> /// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST /// </summary> - [TestCase] + [Test] public void GetPublicFacingUrlSSLForwarder1() { HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); var serverVariables = new NameValueCollection(); serverVariables["HTTP_X_FORWARDED_PROTO"] = "https"; serverVariables["HTTP_HOST"] = "somehost"; - Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri actual = new HttpRequestWrapper(req).GetPublicFacingUrl(serverVariables); Uri expected = new Uri("https://somehost/a.aspx?a=b"); Assert.AreEqual(expected, actual); } @@ -112,13 +83,13 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST:port /// </summary> - [TestCase] + [Test] public void GetPublicFacingUrlSSLForwarder2() { HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); var serverVariables = new NameValueCollection(); serverVariables["HTTP_X_FORWARDED_PROTO"] = "https"; serverVariables["HTTP_HOST"] = "somehost:999"; - Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri actual = new HttpRequestWrapper(req).GetPublicFacingUrl(serverVariables); Uri expected = new Uri("https://somehost:999/a.aspx?a=b"); Assert.AreEqual(expected, actual); } @@ -126,12 +97,12 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies SSL forwarders are correctly handled when they supply just HOST /// </summary> - [TestCase] + [Test] public void GetPublicFacingUrlSSLForwarder3() { HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); var serverVariables = new NameValueCollection(); serverVariables["HTTP_HOST"] = "somehost"; - Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri actual = new HttpRequestWrapper(req).GetPublicFacingUrl(serverVariables); Uri expected = new Uri("http://somehost/a.aspx?a=b"); Assert.AreEqual(expected, actual); } @@ -139,12 +110,12 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies SSL forwarders are correctly handled when they supply just HOST:port /// </summary> - [TestCase] + [Test] public void GetPublicFacingUrlSSLForwarder4() { HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); var serverVariables = new NameValueCollection(); serverVariables["HTTP_HOST"] = "somehost:79"; - Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri actual = new HttpRequestWrapper(req).GetPublicFacingUrl(serverVariables); Uri expected = new Uri("http://somehost:79/a.aspx?a=b"); Assert.AreEqual(expected, actual); } diff --git a/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs index f44f94a..3a07b45 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs @@ -17,7 +17,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Tests for the <see cref="MessageSerializer"/> class. /// </summary> - [TestFixture()] + [TestFixture] public class MessageSerializerTests : MessagingTestBase { [TestCase, ExpectedException(typeof(ArgumentNullException))] public void SerializeNull() { @@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.Messaging { MessageSerializer.Get(null); } - [TestCase()] + [TestCase] public void SerializeTest() { var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage)); var message = GetStandardTestMessage(FieldFill.CompleteBeforeBindings); @@ -58,7 +58,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies JSON serialization /// </summary> - [TestCase] + [Test] public void SerializeDeserializeJson() { var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage)); var message = GetStandardTestMessage(FieldFill.CompleteBeforeBindings); @@ -89,7 +89,7 @@ namespace DotNetOpenAuth.Test.Messaging { MessageSerializer.Deserialize(null, null); } - [TestCase] + [Test] public void DeserializeSimple() { var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage)); Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal); @@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// The element sorting rules are first inheritance order, then alphabetical order. /// This test validates correct behavior on both. /// </remarks> - [TestCase] + [Test] public void DeserializeVerifyElementOrdering() { var serializer = MessageSerializer.Get(typeof(Mocks.TestDerivedMessage)); Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal); @@ -136,7 +136,7 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreEqual("privateValue", actual.PrivatePropertyAccessor); } - [TestCase] + [Test] public void DeserializeWithExtraFields() { var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage)); Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal); diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs index e3700b8..b7c0980 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.Test { using System; using System.Collections.Generic; + using System.Collections.Specialized; using System.IO; using System.Net; using System.Xml; @@ -19,6 +20,8 @@ namespace DotNetOpenAuth.Test { /// The base class that all messaging test classes inherit from. /// </summary> public class MessagingTestBase : TestBase { + protected internal const string DefaultUrlForHttpRequestInfo = "http://localhost/path"; + internal enum FieldFill { /// <summary> /// An empty dictionary is returned. @@ -53,29 +56,19 @@ namespace DotNetOpenAuth.Test { } internal static HttpRequestInfo CreateHttpRequestInfo(string method, IDictionary<string, string> fields) { - string query = MessagingUtilities.CreateQueryString(fields); - UriBuilder requestUri = new UriBuilder("http://localhost/path"); - WebHeaderCollection headers = new WebHeaderCollection(); - MemoryStream ms = new MemoryStream(); + var requestUri = new UriBuilder(DefaultUrlForHttpRequestInfo); + var headers = new NameValueCollection(); + NameValueCollection form = null; if (method == "POST") { - headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); - StreamWriter sw = new StreamWriter(ms); - sw.Write(query); - sw.Flush(); - ms.Position = 0; + form = fields.ToNameValueCollection(); + headers.Add(HttpRequestHeaders.ContentType, Channel.HttpFormUrlEncoded); } else if (method == "GET") { - requestUri.Query = query; + requestUri.Query = MessagingUtilities.CreateQueryString(fields); } else { throw new ArgumentOutOfRangeException("method", method, "Expected POST or GET"); } - HttpRequestInfo request = new HttpRequestInfo { - HttpMethod = method, - UrlBeforeRewriting = requestUri.Uri, - Headers = headers, - InputStream = ms, - }; - return request; + return new HttpRequestInfo(method, requestUri.Uri, form: form, headers: headers); } internal static Channel CreateChannel(MessageProtections capabilityAndRecognition) { diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs index 0550f9d..1f4b1d0 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Test.Messaging { [TestFixture] public class MessagingUtilitiesTests : TestBase { - [TestCase] + [Test] public void CreateQueryString() { var args = new Dictionary<string, string>(); args.Add("a", "b"); @@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreEqual("a=b&c%2Fd=e%2Ff", MessagingUtilities.CreateQueryString(args)); } - [TestCase] + [Test] public void CreateQueryStringEmptyCollection() { Assert.AreEqual(0, MessagingUtilities.CreateQueryString(new Dictionary<string, string>()).Length); } @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.Messaging { MessagingUtilities.CreateQueryString(null); } - [TestCase] + [Test] public void AppendQueryArgs() { UriBuilder uri = new UriBuilder("http://baseline.org/page"); var args = new Dictionary<string, string>(); @@ -56,12 +56,12 @@ namespace DotNetOpenAuth.Test.Messaging { MessagingUtilities.AppendQueryArgs(null, new Dictionary<string, string>()); } - [TestCase] + [Test] public void AppendQueryArgsNullDictionary() { MessagingUtilities.AppendQueryArgs(new UriBuilder(), null); } - [TestCase] + [Test] public void ToDictionary() { NameValueCollection nvc = new NameValueCollection(); nvc["a"] = "b"; @@ -81,7 +81,7 @@ namespace DotNetOpenAuth.Test.Messaging { nvc.ToDictionary(true); } - [TestCase] + [Test] public void ToDictionaryWithSkippedNullKey() { NameValueCollection nvc = new NameValueCollection(); nvc[null] = "a"; @@ -91,7 +91,7 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreEqual(nvc["b"], dictionary["b"]); } - [TestCase] + [Test] public void ToDictionaryNull() { Assert.IsNull(MessagingUtilities.ToDictionary(null)); } @@ -111,7 +111,7 @@ namespace DotNetOpenAuth.Test.Messaging { MessagingUtilities.ApplyHeadersToResponse(null, new HttpResponseWrapper(new HttpResponse(new StringWriter()))); } - [TestCase] + [Test] public void ApplyHeadersToResponse() { var headers = new WebHeaderCollection(); headers[HttpResponseHeader.ContentType] = "application/binary"; @@ -128,7 +128,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <remarks> /// The tests in this method come from http://wiki.oauth.net/TestCases /// </remarks> - [TestCase] + [Test] public void EscapeUriDataStringRfc3986Tests() { Assert.AreEqual("abcABC123", MessagingUtilities.EscapeUriDataStringRfc3986("abcABC123")); Assert.AreEqual("-._~", MessagingUtilities.EscapeUriDataStringRfc3986("-._~")); @@ -145,7 +145,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies the overall format of the multipart POST is correct. /// </summary> - [TestCase] + [Test] public void PostMultipart() { var httpHandler = new TestWebRequestHandler(); bool callbackTriggered = false; @@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies proper behavior of GetHttpVerb /// </summary> - [TestCase] + [Test] public void GetHttpVerbTest() { Assert.AreEqual("GET", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.GetRequest)); Assert.AreEqual("POST", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PostRequest)); @@ -200,7 +200,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies proper behavior of GetHttpDeliveryMethod /// </summary> - [TestCase] + [Test] public void GetHttpDeliveryMethodTest() { Assert.AreEqual(HttpDeliveryMethods.GetRequest, MessagingUtilities.GetHttpDeliveryMethod("GET")); Assert.AreEqual(HttpDeliveryMethods.PostRequest, MessagingUtilities.GetHttpDeliveryMethod("POST")); @@ -217,7 +217,7 @@ namespace DotNetOpenAuth.Test.Messaging { MessagingUtilities.GetHttpDeliveryMethod("UNRECOGNIZED"); } - [TestCase] + [Test] public void EncryptDecrypt() { const string PlainText = "Hi folks!"; byte[] key = MessagingUtilities.GetCryptoRandomData(128 / 8); @@ -232,7 +232,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies that the time-independent string equality check works accurately. /// </summary> - [TestCase] + [Test] public void EqualsConstantTime() { this.EqualsConstantTimeHelper(null, null); this.EqualsConstantTimeHelper(null, string.Empty); diff --git a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs index d378692..39267ca 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies that the Length property matches the length actually serialized. /// </summary> - [TestCase] + [Test] public void FormDataSerializeMatchesLength() { var part = MultipartPostPart.CreateFormPart("a", "b"); VerifyLength(part); @@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies that the length property matches the length actually serialized. /// </summary> - [TestCase] + [Test] public void FileSerializeMatchesLength() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension(".txt"); @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies file multiparts identify themselves as files and not merely form-data. /// </summary> - [TestCase] + [Test] public void FilePartAsFile() { var part = MultipartPostPart.CreateFormFilePart("somename", "somefile", "plain/text", new MemoryStream()); Assert.AreEqual("file", part.ContentDisposition); @@ -49,7 +49,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies MultiPartPost sends the right number of bytes. /// </summary> - [TestCase] + [Test] public void MultiPartPostAscii() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension("txt"); @@ -64,7 +64,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies MultiPartPost sends the right number of bytes. /// </summary> - [TestCase] + [Test] public void MultiPartPostMultiByteCharacters() { using (TempFileCollection tfc = new TempFileCollection()) { string file = tfc.AddExtension("txt"); diff --git a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs index 7f8825a..3efc471 100644 --- a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies that setting the Body property correctly converts to a byte stream. /// </summary> - [TestCase] + [Test] public void SetBodyToByteStream() { var response = new OutgoingWebResponse(); string stringValue = "abc"; diff --git a/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs b/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs index 3a2f040..c05f8c3 100644 --- a/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs @@ -11,18 +11,18 @@ namespace DotNetOpenAuth.Test.Messaging { [TestFixture] public class ProtocolExceptionTests : TestBase { - [TestCase] + [Test] public void CtorDefault() { ProtocolException ex = new ProtocolException(); } - [TestCase] + [Test] public void CtorWithTextMessage() { ProtocolException ex = new ProtocolException("message"); Assert.AreEqual("message", ex.Message); } - [TestCase] + [Test] public void CtorWithTextMessageAndInnerException() { Exception innerException = new Exception(); ProtocolException ex = new ProtocolException("message", innerException); @@ -30,7 +30,7 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreSame(innerException, ex.InnerException); } - [TestCase] + [Test] public void CtorWithProtocolMessage() { IProtocolMessage message = new Mocks.TestDirectedMessage(); ProtocolException ex = new ProtocolException("message", message); diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs index eea802b..66aef6c 100644 --- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs @@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { new MessageDescription(typeof(string), new Version(1, 0)); } - [TestCase] + [Test] public void MultiVersionedMessageTest() { var v10 = new MessageDescription(typeof(MultiVersionMessage), new Version(1, 0)); var v20 = new MessageDescription(typeof(MultiVersionMessage), new Version(2, 0)); @@ -76,7 +76,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// Verifies that the constructors cache is properly initialized. /// </summary> - [TestCase] + [Test] public void CtorsCache() { var message = new MessageDescription(typeof(MultiVersionMessage), new Version(1, 0)); Assert.IsNotNull(message.Constructors); diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs index b5e32ff..ec21e31 100644 --- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.Values /// </summary> - [TestCase] + [Test] public void Values() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); Collection<string> expected = new Collection<string> { @@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.Keys /// </summary> - [TestCase] + [Test] public void Keys() { // We expect that non-nullable value type fields will automatically have keys // in the dictionary for them. @@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.Item /// </summary> - [TestCase] + [Test] public void Item() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); @@ -103,7 +103,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.IsReadOnly /// </summary> - [TestCase] + [Test] public void IsReadOnly() { ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); Assert.IsFalse(target.IsReadOnly); @@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.Count /// </summary> - [TestCase] + [Test] public void Count() { ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target; @@ -124,7 +124,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<System.String,System.String<<.GetEnumerator /// </summary> - [TestCase] + [Test] public void GetEnumerator() { IEnumerable<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target; @@ -147,7 +147,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { Assert.IsTrue(keysLast == valuesLast && keysLast == actualLast); } - [TestCase] + [Test] public void GetEnumeratorUntyped() { IEnumerable target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target; @@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.TryGetValue /// </summary> - [TestCase] + [Test] public void TryGetValue() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); this.message.Name = "andrew"; @@ -194,7 +194,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.Remove /// </summary> - [TestCase] + [Test] public void RemoveTest1() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); this.message.Name = "andrew"; @@ -211,7 +211,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.ContainsKey /// </summary> - [TestCase] + [Test] public void ContainsKey() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); Assert.IsTrue(target.ContainsKey("age"), "Value type declared element should have a key."); @@ -225,7 +225,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.IDictionary<System.String,System.String>.Add /// </summary> - [TestCase] + [Test] public void AddByKeyAndValue() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); target.Add("extra", "value"); @@ -243,7 +243,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.Add /// </summary> - [TestCase] + [Test] public void AddByKeyValuePair() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); target.Add(new KeyValuePair<string, string>("extra", "value")); @@ -264,14 +264,14 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { target.Add("Name", "andrew"); } - [TestCase] + [Test] public void DefaultReferenceTypeDeclaredPropertyHasNoKey() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); Assert.IsFalse(target.ContainsKey("Name"), "A null value should result in no key."); Assert.IsFalse(target.Keys.Contains("Name"), "A null value should result in no key."); } - [TestCase] + [Test] public void RemoveStructDeclaredProperty() { IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message); this.message.Age = 5; @@ -284,7 +284,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.Remove /// </summary> - [TestCase] + [Test] public void RemoveByKeyValuePair() { ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); this.message.Name = "Andrew"; @@ -297,7 +297,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.CopyTo /// </summary> - [TestCase] + [Test] public void CopyTo() { ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target; @@ -314,7 +314,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.Contains /// </summary> - [TestCase] + [Test] public void ContainsKeyValuePair() { ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target; @@ -330,7 +330,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { /// <summary> /// A test for System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.String<<.Clear /// </summary> - [TestCase] + [Test] public void ClearValues() { MessageDictionary target = this.MessageDescriptions.GetAccessor(this.message); IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target; diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs index 65bb3f2..1d820d4 100644 --- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs @@ -21,12 +21,12 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { this.ParameterizedMessageTypeTest(typeof(MessageWithNonNullableOptionalStruct)); } - [TestCase] + [Test] public void RequiredNonNullableStruct() { this.ParameterizedMessageTypeTest(typeof(MessageWithNonNullableRequiredStruct)); } - [TestCase] + [Test] public void OptionalNullableStruct() { var message = new MessageWithNullableOptionalStruct(); var part = this.ParameterizedMessageTypeTest(message.GetType()); @@ -36,7 +36,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { Assert.AreEqual("3", part.GetValue(message)); } - [TestCase] + [Test] public void RequiredNullableStruct() { this.ParameterizedMessageTypeTest(typeof(MessageWithNullableRequiredStruct)); } @@ -52,7 +52,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { new MessagePart(field, null); } - [TestCase] + [Test] public void SetValue() { var message = new MessageWithNonNullableRequiredStruct(); MessagePart part = this.ParameterizedMessageTypeTest(message.GetType()); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { Assert.AreEqual(5, message.OptionalInt); } - [TestCase] + [Test] public void GetValue() { var message = new MessageWithNonNullableRequiredStruct(); message.OptionalInt = 8; @@ -68,7 +68,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { Assert.AreEqual("8", part.GetValue(message)); } - [TestCase] + [Test] public void Base64Member() { var message = new MessageWithBase64EncodedString(); message.LastName = "andrew"; @@ -78,7 +78,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { Assert.AreEqual("arnott", message.LastName); } - [TestCase] + [Test] public void ConstantFieldMemberValidValues() { var message = new MessageWithConstantField(); MessagePart part = GetMessagePart(message.GetType(), "ConstantField"); @@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection { new MessagePart(method, new MessagePartAttribute()); } - [TestCase] + [Test] public void RequiredMinAndMaxVersions() { Type messageType = typeof(MessageWithMinAndMaxVersionParts); FieldInfo newIn2Field = messageType.GetField("NewIn2", BindingFlags.Public | BindingFlags.Instance); diff --git a/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs index 05f9c41..63e0d74 100644 --- a/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Test.Messaging { new OutgoingWebResponse().Respond(); } - [TestCase] + [Test] public void Respond() { StringWriter writer = new StringWriter(); HttpRequest httpRequest = new HttpRequest("file", "http://server", string.Empty); diff --git a/src/DotNetOpenAuth.Test/Messaging/StandardMessageFactoryTests.cs b/src/DotNetOpenAuth.Test/Messaging/StandardMessageFactoryTests.cs index 86bf67e..e3316f1 100644 --- a/src/DotNetOpenAuth.Test/Messaging/StandardMessageFactoryTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/StandardMessageFactoryTests.cs @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies very simple recognition of a single message type /// </summary> - [TestCase] + [Test] public void SingleRequestMessageType() { this.factory.AddMessageTypes(new MessageDescription[] { MessageDescriptions.Get(typeof(RequestMessageMock), V1) }); var fields = new Dictionary<string, string> { @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.Messaging { /// <summary> /// Verifies very simple recognition of a single message type /// </summary> - [TestCase] + [Test] public void SingleResponseMessageType() { this.factory.AddMessageTypes(new MessageDescription[] { MessageDescriptions.Get(typeof(DirectResponseMessageMock), V1) }); var fields = new Dictionary<string, string> { diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs index 8d5295b..d7205d6 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs @@ -11,6 +11,8 @@ namespace DotNetOpenAuth.Test.Mocks { using System.Linq; using System.Text; using System.Threading; + using System.Web; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Reflection; using DotNetOpenAuth.Test.OpenId; @@ -125,7 +127,7 @@ namespace DotNetOpenAuth.Test.Mocks { /// </summary> /// <param name="message">The message to replay.</param> internal void Replay(IProtocolMessage message) { - this.ProcessIncomingMessage(CloneSerializedParts(message)); + this.ProcessIncomingMessage(this.CloneSerializedParts(message)); } /// <summary> @@ -146,7 +148,7 @@ namespace DotNetOpenAuth.Test.Mocks { this.incomingMessageSignal.Set(); } - protected internal override HttpRequestInfo GetRequestFromContext() { + protected internal override HttpRequestBase GetRequestFromContext() { MessageReceivingEndpoint recipient; var messageData = this.AwaitIncomingMessage(out recipient); if (messageData != null) { @@ -191,12 +193,13 @@ namespace DotNetOpenAuth.Test.Mocks { return this.PrepareDirectResponse(message); } - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { - if (request.Message != null) { - this.ProcessMessageFilter(request.Message, false); + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { + var mockRequest = (CoordinatingHttpRequestInfo)request; + if (mockRequest.Message != null) { + this.ProcessMessageFilter(mockRequest.Message, false); } - return request.Message; + return mockRequest.Message; } protected override IDictionary<string, string> ReadFromResponseCore(IncomingWebResponse response) { diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs index bfb9017..9f139f3 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs @@ -5,15 +5,21 @@ //----------------------------------------------------------------------- namespace DotNetOpenAuth.Test.Mocks { + using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using DotNetOpenAuth.Messaging; internal class CoordinatingHttpRequestInfo : HttpRequestInfo { - private IDictionary<string, string> messageData; - private IMessageFactory messageFactory; - private MessageReceivingEndpoint recipient; - private Channel channel; + private readonly Channel channel; + + private readonly IDictionary<string, string> messageData; + + private readonly IMessageFactory messageFactory; + + private readonly MessageReceivingEndpoint recipient; + + private IDirectedProtocolMessage message; /// <summary> /// Initializes a new instance of the <see cref="CoordinatingHttpRequestInfo"/> class @@ -23,14 +29,18 @@ namespace DotNetOpenAuth.Test.Mocks { /// <param name="messageFactory">The message factory.</param> /// <param name="messageData">The message data.</param> /// <param name="recipient">The recipient.</param> - internal CoordinatingHttpRequestInfo(Channel channel, IMessageFactory messageFactory, IDictionary<string, string> messageData, MessageReceivingEndpoint recipient) + internal CoordinatingHttpRequestInfo( + Channel channel, + IMessageFactory messageFactory, + IDictionary<string, string> messageData, + MessageReceivingEndpoint recipient) : this(recipient) { Contract.Requires(channel != null); Contract.Requires(messageFactory != null); Contract.Requires(messageData != null); this.channel = channel; - this.messageFactory = messageFactory; this.messageData = messageData; + this.messageFactory = messageFactory; } /// <summary> @@ -38,35 +48,56 @@ namespace DotNetOpenAuth.Test.Mocks { /// that will not generate any message. /// </summary> /// <param name="recipient">The recipient.</param> - internal CoordinatingHttpRequestInfo(MessageReceivingEndpoint recipient) { + internal CoordinatingHttpRequestInfo(MessageReceivingEndpoint recipient) + : base(GetHttpVerb(recipient), recipient != null ? recipient.Location : new Uri("http://host/path")) { this.recipient = recipient; - if (recipient != null) { - this.UrlBeforeRewriting = recipient.Location; - } + } - if (recipient == null || (recipient.AllowedMethods & HttpDeliveryMethods.GetRequest) != 0) { - this.HttpMethod = "GET"; - } else if ((recipient.AllowedMethods & HttpDeliveryMethods.PostRequest) != 0) { - this.HttpMethod = "POST"; - } + /// <summary> + /// Initializes a new instance of the <see cref="CoordinatingHttpRequestInfo"/> class. + /// </summary> + /// <param name="message">The message being passed in through a mock transport. May be null.</param> + /// <param name="httpMethod">The HTTP method that the incoming request came in on, whether or not <paramref name="message"/> is null.</param> + internal CoordinatingHttpRequestInfo(IDirectedProtocolMessage message, HttpDeliveryMethods httpMethod) + : base(GetHttpVerb(httpMethod), message.Recipient) { + this.message = message; } - internal override IDirectedProtocolMessage Message { + /// <summary> + /// Gets the message deserialized from the remote channel. + /// </summary> + internal IDirectedProtocolMessage Message { get { - if (base.Message == null && this.messageData != null) { - IDirectedProtocolMessage message = this.messageFactory.GetNewRequestMessage(this.recipient, this.messageData); + if (this.message == null && this.messageData != null) { + var message = this.messageFactory.GetNewRequestMessage(this.recipient, this.messageData); if (message != null) { this.channel.MessageDescriptions.GetAccessor(message).Deserialize(this.messageData); + this.message = message; } - base.Message = message; } - return base.Message; + return this.message; + } + } + + private static string GetHttpVerb(MessageReceivingEndpoint recipient) { + if (recipient == null) { + return "GET"; } - set { - base.Message = value; + return GetHttpVerb(recipient.AllowedMethods); + } + + private static string GetHttpVerb(HttpDeliveryMethods httpMethod) { + if ((httpMethod & HttpDeliveryMethods.GetRequest) != 0) { + return "GET"; } + + if ((httpMethod & HttpDeliveryMethods.PostRequest) != 0) { + return "POST"; + } + + throw new ArgumentOutOfRangeException(); } } } diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthConsumerChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthConsumerChannel.cs index 6cc5819..e145952 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthConsumerChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthConsumerChannel.cs @@ -8,6 +8,8 @@ namespace DotNetOpenAuth.Test.Mocks { using System; using System.Diagnostics.Contracts; using System.Threading; + using System.Web; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth.ChannelElements; @@ -49,7 +51,7 @@ namespace DotNetOpenAuth.Test.Mocks { internal OutgoingWebResponse RequestProtectedResource(AccessProtectedResourceRequest request) { ((ITamperResistantOAuthMessage)request).HttpMethod = this.GetHttpMethod(((ITamperResistantOAuthMessage)request).HttpMethods); this.ProcessOutgoingMessage(request); - HttpRequestInfo requestInfo = this.SpoofHttpMethod(request); + var requestInfo = this.SpoofHttpMethod(request); TestBase.TestLogger.InfoFormat("Sending protected resource request: {0}", requestInfo.Message); // Drop the outgoing message in the other channel's in-slot and let them know it's there. this.RemoteChannel.IncomingMessage = requestInfo.Message; @@ -57,13 +59,13 @@ namespace DotNetOpenAuth.Test.Mocks { return this.AwaitIncomingRawResponse(); } - protected internal override HttpRequestInfo GetRequestFromContext() { + protected internal override HttpRequestBase GetRequestFromContext() { var directedMessage = (IDirectedProtocolMessage)this.AwaitIncomingMessage(); - return new HttpRequestInfo(directedMessage, directedMessage.HttpMethods); + return new CoordinatingHttpRequestInfo(directedMessage, directedMessage.HttpMethods); } protected override IProtocolMessage RequestCore(IDirectedProtocolMessage request) { - HttpRequestInfo requestInfo = this.SpoofHttpMethod(request); + var requestInfo = this.SpoofHttpMethod(request); // Drop the outgoing message in the other channel's in-slot and let them know it's there. this.RemoteChannel.IncomingMessage = requestInfo.Message; this.RemoteChannel.IncomingMessageSignal.Set(); @@ -72,7 +74,7 @@ namespace DotNetOpenAuth.Test.Mocks { } protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { - this.RemoteChannel.IncomingMessage = CloneSerializedParts(response, null); + this.RemoteChannel.IncomingMessage = this.CloneSerializedParts(response); this.RemoteChannel.IncomingMessageSignal.Set(); return new OutgoingWebResponse(); // not used, but returning null is not allowed } @@ -82,8 +84,9 @@ namespace DotNetOpenAuth.Test.Mocks { return this.PrepareDirectResponse(message); } - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { - return request.Message; + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { + var mockRequest = (CoordinatingHttpRequestInfo)request; + return mockRequest.Message; } /// <summary> @@ -91,19 +94,14 @@ namespace DotNetOpenAuth.Test.Mocks { /// </summary> /// <param name="message">The message to add a pretend HTTP method to.</param> /// <returns>A spoofed HttpRequestInfo that wraps the new message.</returns> - private HttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { - HttpRequestInfo requestInfo = new HttpRequestInfo(message, message.HttpMethods); - + private CoordinatingHttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { var signedMessage = message as ITamperResistantOAuthMessage; if (signedMessage != null) { string httpMethod = this.GetHttpMethod(signedMessage.HttpMethods); - requestInfo.HttpMethod = httpMethod; - requestInfo.UrlBeforeRewriting = message.Recipient; signedMessage.HttpMethod = httpMethod; } - requestInfo.Message = this.CloneSerializedParts(message, requestInfo); - + var requestInfo = new CoordinatingHttpRequestInfo(this.CloneSerializedParts(message), message.HttpMethods); return requestInfo; } @@ -121,7 +119,7 @@ namespace DotNetOpenAuth.Test.Mocks { return response; } - private T CloneSerializedParts<T>(T message, HttpRequestInfo requestInfo) where T : class, IProtocolMessage { + private T CloneSerializedParts<T>(T message) where T : class, IProtocolMessage { Requires.NotNull(message, "message"); IProtocolMessage clonedMessage; diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthServiceProviderChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthServiceProviderChannel.cs index ad5c695..012173c 100644 --- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthServiceProviderChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthServiceProviderChannel.cs @@ -8,10 +8,13 @@ namespace DotNetOpenAuth.Test.Mocks { using System; using System.Diagnostics.Contracts; using System.Threading; + using System.Web; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth.ChannelElements; using DotNetOpenAuth.OAuth.Messages; + using NUnit.Framework; /// <summary> /// A special channel used in test simulations to pass messages directly between two parties. @@ -48,9 +51,9 @@ namespace DotNetOpenAuth.Test.Mocks { internal CoordinatingOAuthConsumerChannel RemoteChannel { get; set; } internal OutgoingWebResponse RequestProtectedResource(AccessProtectedResourceRequest request) { - ((ITamperResistantOAuthMessage)request).HttpMethod = this.GetHttpMethod(((ITamperResistantOAuthMessage)request).HttpMethods); + ((ITamperResistantOAuthMessage)request).HttpMethod = GetHttpMethod(((ITamperResistantOAuthMessage)request).HttpMethods); this.ProcessOutgoingMessage(request); - HttpRequestInfo requestInfo = this.SpoofHttpMethod(request); + var requestInfo = this.SpoofHttpMethod(request); TestBase.TestLogger.InfoFormat("Sending protected resource request: {0}", requestInfo.Message); // Drop the outgoing message in the other channel's in-slot and let them know it's there. this.RemoteChannel.IncomingMessage = requestInfo.Message; @@ -63,13 +66,13 @@ namespace DotNetOpenAuth.Test.Mocks { this.RemoteChannel.IncomingMessageSignal.Set(); } - protected internal override HttpRequestInfo GetRequestFromContext() { + protected internal override HttpRequestBase GetRequestFromContext() { var directedMessage = (IDirectedProtocolMessage)this.AwaitIncomingMessage(); - return new HttpRequestInfo(directedMessage, directedMessage.HttpMethods); + return new CoordinatingHttpRequestInfo(directedMessage, directedMessage.HttpMethods); } protected override IProtocolMessage RequestCore(IDirectedProtocolMessage request) { - HttpRequestInfo requestInfo = this.SpoofHttpMethod(request); + var requestInfo = this.SpoofHttpMethod(request); // Drop the outgoing message in the other channel's in-slot and let them know it's there. this.RemoteChannel.IncomingMessage = requestInfo.Message; this.RemoteChannel.IncomingMessageSignal.Set(); @@ -78,7 +81,7 @@ namespace DotNetOpenAuth.Test.Mocks { } protected override OutgoingWebResponse PrepareDirectResponse(IProtocolMessage response) { - this.RemoteChannel.IncomingMessage = CloneSerializedParts(response, null); + this.RemoteChannel.IncomingMessage = this.CloneSerializedParts(response); this.RemoteChannel.IncomingMessageSignal.Set(); return new OutgoingWebResponse(); // not used, but returning null is not allowed } @@ -88,8 +91,13 @@ namespace DotNetOpenAuth.Test.Mocks { return this.PrepareDirectResponse(message); } - protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestInfo request) { - return request.Message; + protected override IDirectedProtocolMessage ReadFromRequestCore(HttpRequestBase request) { + var mockRequest = (CoordinatingHttpRequestInfo)request; + return mockRequest.Message; + } + + private static string GetHttpMethod(HttpDeliveryMethods methods) { + return (methods & HttpDeliveryMethods.PostRequest) != 0 ? "POST" : "GET"; } /// <summary> @@ -97,24 +105,20 @@ namespace DotNetOpenAuth.Test.Mocks { /// </summary> /// <param name="message">The message to add a pretend HTTP method to.</param> /// <returns>A spoofed HttpRequestInfo that wraps the new message.</returns> - private HttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { - HttpRequestInfo requestInfo = new HttpRequestInfo(message, message.HttpMethods); - + private CoordinatingHttpRequestInfo SpoofHttpMethod(IDirectedProtocolMessage message) { var signedMessage = message as ITamperResistantOAuthMessage; if (signedMessage != null) { - string httpMethod = this.GetHttpMethod(signedMessage.HttpMethods); - requestInfo.HttpMethod = httpMethod; - requestInfo.UrlBeforeRewriting = message.Recipient; + string httpMethod = GetHttpMethod(signedMessage.HttpMethods); signedMessage.HttpMethod = httpMethod; } - requestInfo.Message = this.CloneSerializedParts(message, requestInfo); - + var requestInfo = new CoordinatingHttpRequestInfo(this.CloneSerializedParts(message), message.HttpMethods); return requestInfo; } private IProtocolMessage AwaitIncomingMessage() { this.IncomingMessageSignal.WaitOne(); + Assert.That(this.IncomingMessage, Is.Not.Null, "Incoming message signaled, but none supplied."); IProtocolMessage response = this.IncomingMessage; this.IncomingMessage = null; return response; @@ -127,7 +131,7 @@ namespace DotNetOpenAuth.Test.Mocks { return response; } - private T CloneSerializedParts<T>(T message, HttpRequestInfo requestInfo) where T : class, IProtocolMessage { + private T CloneSerializedParts<T>(T message) where T : class, IProtocolMessage { Requires.NotNull(message, "message"); IProtocolMessage clonedMessage; @@ -155,9 +159,5 @@ namespace DotNetOpenAuth.Test.Mocks { return (T)clonedMessage; } - - private string GetHttpMethod(HttpDeliveryMethods methods) { - return (methods & HttpDeliveryMethods.PostRequest) != 0 ? "POST" : "GET"; - } } } diff --git a/src/DotNetOpenAuth.Test/Mocks/IBaseMessageExplicitMembers.cs b/src/DotNetOpenAuth.Test/Mocks/IBaseMessageExplicitMembers.cs new file mode 100644 index 0000000..129e05f --- /dev/null +++ b/src/DotNetOpenAuth.Test/Mocks/IBaseMessageExplicitMembers.cs @@ -0,0 +1,11 @@ +//----------------------------------------------------------------------- +// <copyright file="IBaseMessageExplicitMembers.cs" company="Outercurve Foundation"> +// Copyright (c) Outercurve Foundation. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Mocks { + internal interface IBaseMessageExplicitMembers { + string ExplicitProperty { get; set; } + } +}
\ No newline at end of file diff --git a/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs b/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs index 5344304..263f0fd 100644 --- a/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs +++ b/src/DotNetOpenAuth.Test/Mocks/TestBadChannel.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.Test.Mocks { using System; using System.Collections.Generic; + using System.Web; using DotNetOpenAuth.Messaging; /// <summary> @@ -33,7 +34,7 @@ namespace DotNetOpenAuth.Test.Mocks { return base.Receive(fields, recipient); } - internal new IProtocolMessage ReadFromRequest(HttpRequestInfo request) { + internal new IProtocolMessage ReadFromRequest(HttpRequestBase request) { return base.ReadFromRequest(request); } diff --git a/src/DotNetOpenAuth.Test/Mocks/TestBaseMessage.cs b/src/DotNetOpenAuth.Test/Mocks/TestBaseMessage.cs index d05af4a..39bfa58 100644 --- a/src/DotNetOpenAuth.Test/Mocks/TestBaseMessage.cs +++ b/src/DotNetOpenAuth.Test/Mocks/TestBaseMessage.cs @@ -11,10 +11,6 @@ namespace DotNetOpenAuth.Test.Mocks { using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Reflection; - internal interface IBaseMessageExplicitMembers { - string ExplicitProperty { get; set; } - } - internal class TestBaseMessage : IProtocolMessage, IBaseMessageExplicitMembers { private Dictionary<string, string> extraData = new Dictionary<string, string>(); diff --git a/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs index cae0f87..a295732 100644 --- a/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs +++ b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.OAuth { [TestFixture] public class AppendixScenarios : TestBase { - [TestCase] + [Test] public void SpecAppendixAExample() { ServiceProviderDescription serviceDescription = new ServiceProviderDescription() { RequestTokenEndpoint = new MessageReceivingEndpoint("https://photos.example.net/request_token", HttpDeliveryMethods.PostRequest), diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs index 6605fad..487ce56 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs @@ -12,7 +12,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { [TestFixture] public class HmacSha1SigningBindingElementTests : MessagingTestBase { - [TestCase] + [Test] public void SignatureTest() { UnauthorizedTokenRequest message = SigningBindingElementBaseTests.CreateTestRequestTokenMessage(this.MessageDescriptions, null); diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs index 1b9d2eb..7999a44 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs @@ -56,17 +56,17 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { new OAuthConsumerChannel(new RsaSha1ServiceProviderSigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, this.consumerSecuritySettings, new TestMessageFactory()); } - [TestCase] + [Test] public void CtorSimpleConsumer() { new OAuthConsumerChannel(new RsaSha1ServiceProviderSigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager(), this.consumerSecuritySettings); } - [TestCase] + [Test] public void CtorSimpleServiceProvider() { new OAuthServiceProviderChannel(new RsaSha1ServiceProviderSigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager(), this.serviceProviderSecuritySettings); } - [TestCase] + [Test] public void ReadFromRequestAuthorization() { this.ParameterizedReceiveTest(HttpDeliveryMethods.AuthorizationHeaderRequest); } @@ -75,26 +75,27 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// Verifies that the OAuth ReadFromRequest method gathers parameters /// from the Authorization header, the query string and the entity form data. /// </summary> - [TestCase] + [Test] public void ReadFromRequestAuthorizationScattered() { // Start by creating a standard POST HTTP request. - var fields = new Dictionary<string, string> { + var postedFields = new Dictionary<string, string> { { "age", "15" }, }; - HttpRequestInfo requestInfo = CreateHttpRequestInfo(HttpDeliveryMethods.PostRequest, fields); // Now add another field to the request URL - UriBuilder builder = new UriBuilder(requestInfo.UrlBeforeRewriting); + var builder = new UriBuilder(MessagingTestBase.DefaultUrlForHttpRequestInfo); builder.Query = "Name=Andrew"; - requestInfo.UrlBeforeRewriting = builder.Uri; - requestInfo.RawUrl = builder.Path + builder.Query + builder.Fragment; // Finally, add an Authorization header - fields = new Dictionary<string, string> { + var authHeaderFields = new Dictionary<string, string> { { "Location", "http://hostb/pathB" }, { "Timestamp", XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.Utc) }, }; - requestInfo.Headers.Add(HttpRequestHeader.Authorization, CreateAuthorizationHeader(fields)); + var headers = new NameValueCollection(); + headers.Add(HttpRequestHeaders.Authorization, CreateAuthorizationHeader(authHeaderFields)); + headers.Add(HttpRequestHeaders.ContentType, Channel.HttpFormUrlEncoded); + + var requestInfo = new HttpRequestInfo("POST", builder.Uri, form: postedFields.ToNameValueCollection(), headers: headers); IDirectedProtocolMessage requestMessage = this.channel.ReadFromRequest(requestInfo); @@ -106,17 +107,17 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.AreEqual("http://hostb/pathB", testMessage.Location.AbsoluteUri); } - [TestCase] + [Test] public void ReadFromRequestForm() { this.ParameterizedReceiveTest(HttpDeliveryMethods.PostRequest); } - [TestCase] + [Test] public void ReadFromRequestQueryString() { this.ParameterizedReceiveTest(HttpDeliveryMethods.GetRequest); } - [TestCase] + [Test] public void SendDirectMessageResponse() { IProtocolMessage message = new TestDirectedMessage { Age = 15, @@ -135,7 +136,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.AreEqual("http://hostb/pathB", body["Location"]); } - [TestCase] + [Test] public void ReadFromResponse() { var fields = new Dictionary<string, string> { { "age", "15" }, @@ -175,7 +176,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { this.channel.Request(message); } - [TestCase] + [Test] public void RequestUsingAuthorizationHeader() { this.ParameterizedRequestTest(HttpDeliveryMethods.AuthorizationHeaderRequest); } @@ -183,7 +184,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// <summary> /// Verifies that message parts can be distributed to the query, form, and Authorization header. /// </summary> - [TestCase] + [Test] public void RequestUsingAuthorizationHeaderScattered() { TestDirectedMessage request = new TestDirectedMessage(MessageTransport.Direct) { Age = 15, @@ -216,17 +217,17 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.AreEqual("appearinform=formish", this.webRequestHandler.RequestEntityAsString); } - [TestCase] + [Test] public void RequestUsingGet() { this.ParameterizedRequestTest(HttpDeliveryMethods.GetRequest); } - [TestCase] + [Test] public void RequestUsingPost() { this.ParameterizedRequestTest(HttpDeliveryMethods.PostRequest); } - [TestCase] + [Test] public void RequestUsingHead() { this.ParameterizedRequestTest(HttpDeliveryMethods.HeadRequest); } @@ -234,7 +235,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// <summary> /// Verifies that messages asking for special HTTP status codes get them. /// </summary> - [TestCase] + [Test] public void SendDirectMessageResponseHonorsHttpStatusCodes() { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); OutgoingWebResponse directResponse = this.channel.PrepareDirectResponseTestHook(message); @@ -266,51 +267,33 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { } 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(); + var requestUri = new UriBuilder(MessagingTestBase.DefaultUrlForHttpRequestInfo); + var headers = new NameValueCollection(); + NameValueCollection form = null; 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; + form = fields.ToNameValueCollection(); + headers.Add(HttpRequestHeaders.ContentType, Channel.HttpFormUrlEncoded); break; case HttpDeliveryMethods.GetRequest: method = "GET"; - requestUri.Query = query; + requestUri.Query = MessagingUtilities.CreateQueryString(fields); break; case HttpDeliveryMethods.AuthorizationHeaderRequest: method = "GET"; - headers.Add(HttpRequestHeader.Authorization, CreateAuthorizationHeader(fields)); + headers.Add(HttpRequestHeaders.Authorization, CreateAuthorizationHeader(fields)); break; default: throw new ArgumentOutOfRangeException("scheme", scheme, "Unexpected value"); } - HttpRequestInfo request = new HttpRequestInfo { - HttpMethod = method, - UrlBeforeRewriting = requestUri.Uri, - RawUrl = requestUri.Path + requestUri.Query + requestUri.Fragment, - Headers = headers, - InputStream = ms, - }; - return request; + return new HttpRequestInfo(method, requestUri.Uri, form: form, headers: headers); } private static HttpRequestInfo ConvertToRequestInfo(HttpWebRequest request, Stream postEntity) { - HttpRequestInfo info = new HttpRequestInfo { - HttpMethod = request.Method, - UrlBeforeRewriting = request.RequestUri, - RawUrl = request.RequestUri.AbsolutePath + request.RequestUri.Query + request.RequestUri.Fragment, - Headers = request.Headers, - InputStream = postEntity, - }; - return info; + return new HttpRequestInfo(request.Method, request.RequestUri, request.Headers, postEntity); } private void ParameterizedRequestTest(HttpDeliveryMethods scheme) { diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs index 8236c21..b3869e7 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs @@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { [TestFixture] public class PlaintextSigningBindingElementTest { - [TestCase] + [Test] public void HttpsSignatureGeneration() { SigningBindingElementBase target = new PlaintextSigningBindingElement(); target.Channel = new TestChannel(); @@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.AreEqual("cs&ts", message.Signature); } - [TestCase] + [Test] public void HttpsSignatureVerification() { MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://localtest", HttpDeliveryMethods.GetRequest); ITamperProtectionChannelBindingElement target = new PlaintextSigningBindingElement(); @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.IsNotNull(target.ProcessIncomingMessage(message)); } - [TestCase] + [Test] public void HttpsSignatureVerificationNotApplicable() { SigningBindingElementBase target = new PlaintextSigningBindingElement(); target.Channel = new TestChannel(); @@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.AreEqual(MessageProtections.None, target.ProcessIncomingMessage(message), "PLAINTEXT binding element should opt-out where it doesn't understand."); } - [TestCase] + [Test] public void HttpSignatureGeneration() { SigningBindingElementBase target = new PlaintextSigningBindingElement(); target.Channel = new TestChannel(); @@ -68,7 +68,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { Assert.IsNull(message.Signature); } - [TestCase] + [Test] public void HttpSignatureVerification() { SigningBindingElementBase target = new PlaintextSigningBindingElement(); target.Channel = new TestChannel(); diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs index 85f7130..dffe6c1 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { [TestFixture] public class SigningBindingElementBaseTests : MessagingTestBase { - [TestCase] + [Test] public void BaseSignatureStringTest() { // Tests a message sent by HTTP GET, with no query string included in the endpoint. UnauthorizedTokenRequest message = CreateTestRequestTokenMessage( @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message))); } - [TestCase] + [Test] public void BaseSignatureStringResourceRequests() { var message = this.CreateResourceRequest(new MessageReceivingEndpoint("http://tom.test.wishpot.com/restapi/List/Search?List.LastName=ciccotosto", HttpDeliveryMethods.GetRequest)); message.ConsumerKey = "public"; diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs index 0dc572f..185e75b 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs @@ -24,7 +24,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// <summary> /// Verifies null value encoding /// </summary> - [TestCase] + [Test] public void NullValueEncoding() { Assert.AreEqual("oob", this.encoding.EncodedNullValue); } @@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// <summary> /// Verifies decoding "oob" results in a null uri. /// </summary> - [TestCase] + [Test] public void DecodeOobToNullUri() { Assert.IsNull(this.encoding.Decode("oob")); } @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements { /// <summary> /// Verifies proper decoding/encoding of a Uri /// </summary> - [TestCase] + [Test] public void UriEncodeDecode() { Uri original = new Uri("http://somehost/p?q=a#frag"); string encodedValue = this.encoding.Encode(original); diff --git a/src/DotNetOpenAuth.Test/OAuth/ConsumerDescription.cs b/src/DotNetOpenAuth.Test/OAuth/ConsumerDescription.cs index a439e70..74752f8 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ConsumerDescription.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ConsumerDescription.cs @@ -10,7 +10,7 @@ namespace DotNetOpenAuth.Test.OAuth { /// and to tell a <see cref="ServiceProvider"/> about it. /// </summary> /// <remarks> - /// Immutable. + /// This type is immutable. /// </remarks> internal class ConsumerDescription { /// <summary> diff --git a/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs b/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs index 69ec9da..cd4d8dd 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs @@ -10,23 +10,23 @@ namespace DotNetOpenAuth.Test.OAuth { [TestFixture] public class ProtocolTests { - [TestCase] + [Test] public void Default() { Assert.AreSame(Protocol.V10a, Protocol.Default); } - [TestCase] + [Test] public void DataContractNamespace() { Assert.AreEqual("http://oauth.net/core/1.0/", Protocol.V10.DataContractNamespace); Assert.AreEqual("http://oauth.net/core/1.0/", Protocol.DataContractNamespaceV10); } - [TestCase] + [Test] public void AuthorizationHeaderScheme() { Assert.AreEqual("OAuth", Protocol.AuthorizationHeaderScheme); } - [TestCase] + [Test] public void ParameterPrefix() { Assert.AreEqual("oauth_", Protocol.ParameterPrefix); } diff --git a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs index c4afb18..42bb149 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.Test.OAuth { /// <summary> /// A test for UserAuthorizationUri /// </summary> - [TestCase] + [Test] public void UserAuthorizationUriTest() { ServiceProviderDescription target = new ServiceProviderDescription(); MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/authorization", HttpDeliveryMethods.GetRequest); @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test.OAuth { /// <summary> /// A test for RequestTokenUri /// </summary> - [TestCase] + [Test] public void RequestTokenUriTest() { var target = new ServiceProviderDescription(); MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/requesttoken", HttpDeliveryMethods.GetRequest); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OAuth { /// <summary> /// A test for AccessTokenUri /// </summary> - [TestCase] + [Test] public void AccessTokenUriTest() { var target = new ServiceProviderDescription(); MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/accesstoken", HttpDeliveryMethods.GetRequest); diff --git a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs index ae74376..82e02e7 100644 --- a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs @@ -18,7 +18,7 @@ namespace DotNetOpenAuth.Test.OAuth { /// <summary> /// Verifies the CreateVerificationCode method. /// </summary> - [TestCase] + [Test] public void CreateVerificationCode() { this.TestCode(VerificationCodeFormat.Numeric, 3, MessagingUtilities.Digits); this.TestCode(VerificationCodeFormat.AlphaLower, 5, MessagingUtilities.LowercaseLetters); diff --git a/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs b/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs new file mode 100644 index 0000000..f3d8feb --- /dev/null +++ b/src/DotNetOpenAuth.Test/OAuth2/AuthorizationServerTests.cs @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------- +// <copyright file="AuthorizationServerTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OAuth2 { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.OAuth2; + using DotNetOpenAuth.OAuth2.Messages; + using NUnit.Framework; + + /// <summary> + /// Verifies authorization server functionality. + /// </summary> + [TestFixture] + public class AuthorizationServerTests : OAuth2TestBase { + /// <summary> + /// Verifies that authorization server responds with an appropriate error response. + /// </summary> + [Test] + public void ErrorResponseTest() { + var coordinator = new OAuth2Coordinator<UserAgentClient>( + AuthorizationServerDescription, + AuthorizationServerMock, + new UserAgentClient(AuthorizationServerDescription), + client => { + var request = new AccessTokenAuthorizationCodeRequest(AuthorizationServerDescription) + { ClientIdentifier = ClientId, ClientSecret = ClientSecret, AuthorizationCode = "foo" }; + + var response = client.Channel.Request<AccessTokenFailedResponse>(request); + Assert.That(response.Error, Is.Not.Null.And.Not.Empty); + Assert.That(response.Error, Is.EqualTo(Protocol.AccessTokenRequestErrorCodes.InvalidRequest)); + }, + server => { + server.HandleTokenRequest().Respond(); + }); + coordinator.Run(); + } + } +} diff --git a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs index f46af33..bec85e2 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/MessageFactoryTests.cs @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { #region End user authorization messages - [TestCase] + [Test] public void EndUserAuthorizationRequest() { var fields = new Dictionary<string, string> { { Protocol.response_type, "code" }, @@ -41,10 +41,10 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.redirect_uri, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(EndUserAuthorizationRequest), request); + Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationRequest))); } - [TestCase] + [Test] public void EndUserAuthorizationImplicitRequest() { var fields = new Dictionary<string, string> { { Protocol.response_type, "token" }, @@ -52,42 +52,42 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.redirect_uri, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(EndUserAuthorizationImplicitRequest), request); + Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationImplicitRequest))); } - [TestCase] + [Test] public void EndUserAuthorizationSuccessResponseWithCode() { var fields = new Dictionary<string, string> { { Protocol.code, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(EndUserAuthorizationSuccessResponseBase), request); + Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationSuccessResponseBase))); } - [TestCase] + [Test] public void EndUserAuthorizationSuccessResponseWithAccessToken() { var fields = new Dictionary<string, string> { { Protocol.access_token, "abc" }, { Protocol.token_type, "bearer" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(EndUserAuthorizationSuccessResponseBase), request); + Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationSuccessResponseBase))); } - [TestCase] + [Test] public void EndUserAuthorizationFailedResponse() { var fields = new Dictionary<string, string> { { Protocol.error, "access-denied" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(EndUserAuthorizationFailedResponse), request); + Assert.That(request, Is.InstanceOf(typeof(EndUserAuthorizationFailedResponse))); } #endregion #region Access token request messages - [TestCase] + [Test] public void AccessTokenRefreshRequest() { var fields = new Dictionary<string, string> { { Protocol.client_id, "abc" }, @@ -95,10 +95,10 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.grant_type, "refresh-token" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(AccessTokenRefreshRequest), request); + Assert.That(request, Is.InstanceOf(typeof(AccessTokenRefreshRequest))); } - [TestCase] + [Test] public void AccessTokenAuthorizationCodeRequest() { var fields = new Dictionary<string, string> { { Protocol.client_id, "abc" }, @@ -107,10 +107,10 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.redirect_uri, "http://someUri" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(AccessTokenAuthorizationCodeRequest), request); + Assert.That(request, Is.InstanceOf(typeof(AccessTokenAuthorizationCodeRequest))); } - [TestCase] + [Test] public void AccessTokenBasicCredentialsRequest() { var fields = new Dictionary<string, string> { { Protocol.client_id, "abc" }, @@ -120,10 +120,10 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.password, "abc" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(AccessTokenResourceOwnerPasswordCredentialsRequest), request); + Assert.That(request, Is.InstanceOf(typeof(AccessTokenResourceOwnerPasswordCredentialsRequest))); } - [TestCase] + [Test] public void AccessTokenClientCredentialsRequest() { var fields = new Dictionary<string, string> { { Protocol.client_id, "abc" }, @@ -131,7 +131,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { { Protocol.grant_type, "none" }, }; IDirectedProtocolMessage request = this.messageFactory.GetNewRequestMessage(this.recipient, fields); - Assert.IsInstanceOf(typeof(AccessTokenClientCredentialsRequest), request); + Assert.That(request, Is.InstanceOf(typeof(AccessTokenClientCredentialsRequest))); } #endregion diff --git a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs index 1b5c329..87d91f7 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/OAuth2TestBase.cs @@ -9,6 +9,7 @@ namespace DotNetOpenAuth.Test.OAuth2 { using System.Collections.Generic; using System.Linq; using System.Text; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.Messaging.Bindings; using DotNetOpenAuth.OAuth2; using DotNetOpenAuth.OAuth2.ChannelElements; @@ -23,6 +24,8 @@ namespace DotNetOpenAuth.Test.OAuth2 { protected const string ResourceOwnerPassword = "TestUserPassword"; + protected static readonly string[] TestScopes = new[] { "Scope1", "Scope2" }; + protected static readonly Uri ClientCallback = new Uri("http://client/callback"); protected static readonly AuthorizationServerDescription AuthorizationServerDescription = new AuthorizationServerDescription { @@ -42,7 +45,13 @@ namespace DotNetOpenAuth.Test.OAuth2 { var cryptoStore = new MemoryCryptoKeyStore(); authHostMock.Setup(m => m.GetClient(ClientId)).Returns(ClientDescription); authHostMock.SetupGet(m => m.CryptoKeyStore).Returns(cryptoStore); - authHostMock.Setup(m => m.IsAuthorizationValid(It.Is<IAuthorizationDescription>(d => d.ClientIdentifier == ClientId && d.User == ResourceOwnerUsername))).Returns(true); + authHostMock.Setup( + m => + m.IsAuthorizationValid( + It.Is<IAuthorizationDescription>( + d => + d.ClientIdentifier == ClientId && d.User == ResourceOwnerUsername && + MessagingUtilities.AreEquivalent(d.Scope, TestScopes)))).Returns(true); authHostMock.Setup(m => m.IsResourceOwnerCredentialValid(ResourceOwnerUsername, ResourceOwnerPassword)).Returns(true); return authHostMock; } diff --git a/src/DotNetOpenAuth.Test/OAuth2/UserAgentClientAuthorizeTests.cs b/src/DotNetOpenAuth.Test/OAuth2/UserAgentClientAuthorizeTests.cs index 3a8944f..97c0f56 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/UserAgentClientAuthorizeTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/UserAgentClientAuthorizeTests.cs @@ -19,14 +19,14 @@ namespace DotNetOpenAuth.Test.OAuth2 { [TestFixture] public class UserAgentClientAuthorizeTests : OAuth2TestBase { - [TestCase] + [Test] public void AuthorizationCodeGrant() { var coordinator = new OAuth2Coordinator<UserAgentClient>( AuthorizationServerDescription, AuthorizationServerMock, new UserAgentClient(AuthorizationServerDescription), client => { - var authState = new AuthorizationState { + var authState = new AuthorizationState(TestScopes) { Callback = ClientCallback, }; var request = client.PrepareRequestUserAuthorization(authState); @@ -34,22 +34,19 @@ namespace DotNetOpenAuth.Test.OAuth2 { client.Channel.Respond(request); var incoming = client.Channel.ReadFromRequest(); var result = client.ProcessUserAuthorization(authState, incoming); - Assert.IsNotNullOrEmpty(result.AccessToken); - Assert.IsNotNullOrEmpty(result.RefreshToken); + Assert.That(result.AccessToken, Is.Not.Null.And.Not.Empty); + Assert.That(result.RefreshToken, Is.Not.Null.And.Not.Empty); }, server => { var request = server.ReadAuthorizationRequest(); + Assert.That(request, Is.Not.Null); server.ApproveAuthorizationRequest(request, ResourceOwnerUsername); - var tokenRequest = server.ReadAccessTokenRequest(); - IAccessTokenRequest accessTokenRequest = tokenRequest; - Assert.IsTrue(accessTokenRequest.ClientAuthenticated); - var tokenResponse = server.PrepareAccessTokenResponse(tokenRequest); - server.Channel.Respond(tokenResponse); + server.HandleTokenRequest().Respond(); }); coordinator.Run(); } - [TestCase] + [Test] public void ImplicitGrant() { var coordinatorClient = new UserAgentClient(AuthorizationServerDescription); var coordinator = new OAuth2Coordinator<UserAgentClient>( @@ -57,21 +54,22 @@ namespace DotNetOpenAuth.Test.OAuth2 { AuthorizationServerMock, coordinatorClient, client => { - var authState = new AuthorizationState { + var authState = new AuthorizationState(TestScopes) { Callback = ClientCallback, }; var request = client.PrepareRequestUserAuthorization(authState, implicitResponseType: true); - Assert.AreEqual(EndUserAuthorizationResponseType.AccessToken, request.ResponseType); + Assert.That(request.ResponseType, Is.EqualTo(EndUserAuthorizationResponseType.AccessToken)); client.Channel.Respond(request); var incoming = client.Channel.ReadFromRequest(); var result = client.ProcessUserAuthorization(authState, incoming); - Assert.IsNotNullOrEmpty(result.AccessToken); - Assert.IsNull(result.RefreshToken); + Assert.That(result.AccessToken, Is.Not.Null.And.Not.Empty); + Assert.That(result.RefreshToken, Is.Null); }, server => { var request = server.ReadAuthorizationRequest(); + Assert.That(request, Is.Not.Null); IAccessTokenRequest accessTokenRequest = (EndUserAuthorizationImplicitRequest)request; - Assert.IsFalse(accessTokenRequest.ClientAuthenticated); + Assert.That(accessTokenRequest.ClientAuthenticated, Is.False); server.ApproveAuthorizationRequest(request, ResourceOwnerUsername); }); diff --git a/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs b/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs index 1615f97..fe0abd2 100644 --- a/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs +++ b/src/DotNetOpenAuth.Test/OAuth2/WebServerClientAuthorizeTests.cs @@ -9,54 +9,73 @@ namespace DotNetOpenAuth.Test.OAuth2 { using System.Collections.Generic; using System.Linq; using System.Text; + using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth2; + using DotNetOpenAuth.OAuth2.ChannelElements; using DotNetOpenAuth.OAuth2.Messages; + using Moq; using NUnit.Framework; [TestFixture] public class WebServerClientAuthorizeTests : OAuth2TestBase { - [TestCase] + [Test] public void AuthorizationCodeGrant() { var coordinator = new OAuth2Coordinator<WebServerClient>( AuthorizationServerDescription, AuthorizationServerMock, new WebServerClient(AuthorizationServerDescription), client => { - var authState = new AuthorizationState { + var authState = new AuthorizationState(TestScopes) { Callback = ClientCallback, }; client.PrepareRequestUserAuthorization(authState).Respond(); var result = client.ProcessUserAuthorization(); - Assert.IsNotNullOrEmpty(result.AccessToken); - Assert.IsNotNullOrEmpty(result.RefreshToken); + Assert.That(result.AccessToken, Is.Not.Null.And.Not.Empty); + Assert.That(result.RefreshToken, Is.Not.Null.And.Not.Empty); }, server => { var request = server.ReadAuthorizationRequest(); + Assert.That(request, Is.Not.Null); server.ApproveAuthorizationRequest(request, ResourceOwnerUsername); - var tokenRequest = server.ReadAccessTokenRequest(); - IAccessTokenRequest accessTokenRequest = tokenRequest; - Assert.IsTrue(accessTokenRequest.ClientAuthenticated); - var tokenResponse = server.PrepareAccessTokenResponse(tokenRequest); - server.Channel.Respond(tokenResponse); + server.HandleTokenRequest().Respond(); }); coordinator.Run(); } - [TestCase] + [Test] public void ResourceOwnerPasswordCredentialGrant() { var coordinator = new OAuth2Coordinator<WebServerClient>( AuthorizationServerDescription, AuthorizationServerMock, new WebServerClient(AuthorizationServerDescription), client => { - var authState = client.ExchangeUserCredentialForToken(ResourceOwnerUsername, ResourceOwnerPassword); - Assert.IsNotNullOrEmpty(authState.AccessToken); - Assert.IsNotNullOrEmpty(authState.RefreshToken); + var authState = client.ExchangeUserCredentialForToken(ResourceOwnerUsername, ResourceOwnerPassword, TestScopes); + Assert.That(authState.AccessToken, Is.Not.Null.And.Not.Empty); + Assert.That(authState.RefreshToken, Is.Not.Null.And.Not.Empty); }, server => { - var request = server.ReadAccessTokenRequest(); - var response = server.PrepareAccessTokenResponse(request); - server.Channel.Respond(response); + server.HandleTokenRequest().Respond(); + }); + coordinator.Run(); + } + + [Test] + public void ClientCredentialGrant() { + var authServer = CreateAuthorizationServerMock(); + authServer.Setup( + a => a.IsAuthorizationValid(It.Is<IAuthorizationDescription>(d => d.User == null && d.ClientIdentifier == ClientId && MessagingUtilities.AreEquivalent(d.Scope, TestScopes)))) + .Returns(true); + var coordinator = new OAuth2Coordinator<WebServerClient>( + AuthorizationServerDescription, + authServer.Object, + new WebServerClient(AuthorizationServerDescription), + client => { + var authState = client.GetClientAccessToken(TestScopes); + Assert.That(authState.AccessToken, Is.Not.Null.And.Not.Empty); + Assert.That(authState.RefreshToken, Is.Null); + }, + server => { + server.HandleTokenRequest().Respond(); }); coordinator.Run(); } diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs index 6dace64..029447d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs @@ -21,12 +21,12 @@ namespace DotNetOpenAuth.Test.OpenId { base.SetUp(); } - [TestCase] + [Test] public void AssociateUnencrypted() { this.ParameterizedAssociationTest(new Uri("https://host")); } - [TestCase] + [Test] public void AssociateDiffieHellmanOverHttp() { this.ParameterizedAssociationTest(new Uri("http://host")); } @@ -38,7 +38,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Some OPs out there flatly refuse to do this, and the spec doesn't forbid /// putting the two together, so we verify that DNOI can handle it. /// </remarks> - [TestCase] + [Test] public void AssociateDiffieHellmanOverHttps() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -62,7 +62,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that the RP and OP can renegotiate an association type if the RP's /// initial request for an association is for a type the OP doesn't support. /// </summary> - [TestCase] + [Test] public void AssociateRenegotiateBitLength() { Protocol protocol = Protocol.V20; @@ -82,6 +82,7 @@ namespace DotNetOpenAuth.Test.OpenId { // Receive initial request for an HMAC-SHA256 association. AutoResponsiveRequest req = (AutoResponsiveRequest)op.GetRequest(); AssociateRequest associateRequest = (AssociateRequest)req.RequestMessage; + Assert.That(associateRequest, Is.Not.Null); Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType); // Ensure that the response is a suggestion that the RP try again with HMAC-SHA1 @@ -108,7 +109,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <remarks> /// Verifies OP's compliance with OpenID 2.0 section 8.4.1. /// </remarks> - [TestCase] + [Test] public void OPRejectsHttpNoEncryptionAssociateRequests() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -129,7 +130,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that the OP rejects an associate request /// when the HMAC and DH bit lengths do not match. /// </summary> - [TestCase] + [Test] public void OPRejectsMismatchingAssociationAndSessionTypes() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -152,7 +153,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies that the RP quietly rejects an OP that suggests an unknown association type. /// </summary> - [TestCase] + [Test] public void RPRejectsUnrecognizedAssociationType() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -179,7 +180,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <remarks> /// Verifies RP's compliance with OpenID 2.0 section 8.4.1. /// </remarks> - [TestCase] + [Test] public void RPRejectsUnencryptedSuggestion() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -204,7 +205,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that the RP rejects an associate renegotiate request /// when the HMAC and DH bit lengths do not match. /// </summary> - [TestCase] + [Test] public void RPRejectsMismatchingAssociationAndSessionBitLengths() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -229,7 +230,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that the RP cannot get caught in an infinite loop if a bad OP /// keeps sending it association retry messages. /// </summary> - [TestCase] + [Test] public void RPOnlyRenegotiatesOnce() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -262,7 +263,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies security settings limit RP's acceptance of OP's counter-suggestion /// </summary> - [TestCase] + [Test] public void AssociateRenegotiateLimitedByRPSecuritySettings() { Protocol protocol = Protocol.V20; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -282,7 +283,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that the RP can recover from an invalid or non-existent /// response from the OP, for example in the HTTP timeout case. /// </summary> - [TestCase] + [Test] public void AssociateQuietlyFailsAfterHttpError() { this.MockResponder.RegisterMockNotFound(OPUri); var rp = this.CreateRelyingParty(); diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs index 01b82fa..92173a7 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs @@ -35,21 +35,21 @@ namespace DotNetOpenAuth.Test.OpenId { this.sha1Secret2[1] = 0xcc; } - [TestCase] + [Test] public void Properties() { string handle = "somehandle"; TimeSpan lifetime = TimeSpan.FromMinutes(2); Association assoc = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, handle, this.sha1Secret, lifetime); Assert.IsFalse(assoc.IsExpired); - Assert.IsTrue(Math.Abs((DateTime.Now - assoc.Issued.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds); - Assert.IsTrue(Math.Abs((DateTime.Now.ToLocalTime() + lifetime - assoc.Expires.ToLocalTime()).TotalSeconds) < deltaDateTime.TotalSeconds); - Assert.AreEqual(handle, assoc.Handle); - Assert.IsTrue(Math.Abs(lifetime.TotalSeconds - assoc.SecondsTillExpiration) < deltaDateTime.TotalSeconds); - Assert.IsTrue(MessagingUtilities.AreEquivalent(this.sha1Secret, assoc.SecretKey)); - Assert.AreEqual(0, assoc.Issued.Millisecond, "No milliseconds because this can be cut off in conversions."); + Assert.That(assoc.Issued, Is.EqualTo(DateTime.UtcNow).Within(deltaDateTime)); + Assert.That(assoc.Expires, Is.EqualTo(DateTime.UtcNow + lifetime).Within(deltaDateTime)); + Assert.That(assoc.Handle, Is.EqualTo(handle)); + Assert.That(assoc.SecondsTillExpiration, Is.EqualTo(lifetime.TotalSeconds).Within(deltaDateTime.TotalSeconds)); + Assert.That(assoc.SecretKey, Is.EqualTo(this.sha1Secret)); + Assert.That(assoc.Issued.Millisecond, Is.EqualTo(0), "No milliseconds because this can be cut off in conversions."); } - [TestCase] + [Test] public void Sign() { Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2)); Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2)); @@ -58,21 +58,21 @@ namespace DotNetOpenAuth.Test.OpenId { // sign once and verify that it's sane byte[] signature1 = assoc1.Sign(data); - Assert.IsNotNull(signature1); - Assert.AreNotEqual(0, signature1.Length); + Assert.That(signature1, Is.Not.Null); + Assert.That(signature1.Length, Is.Not.EqualTo(0)); // sign again and make sure it's different byte[] signature2 = assoc2.Sign(data); - Assert.IsNotNull(signature2); - Assert.AreNotEqual(0, signature2.Length); - Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, signature2)); + Assert.That(signature2, Is.Not.Null); + Assert.That(signature2.Length, Is.Not.EqualTo(0)); + Assert.That(signature1, Is.Not.EqualTo(signature2)); // sign again with the same secret and make sure it's the same. - Assert.IsTrue(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data))); + Assert.That(assoc1.Sign(data), Is.EqualTo(signature1)); // now change the data and make sure signature changes data[1] = 0xee; - Assert.IsFalse(MessagingUtilities.AreEquivalent(signature1, assoc1.Sign(data))); + Assert.That(assoc1.Sign(data), Is.Not.EqualTo(signature1)); } } } diff --git a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs index 7d5a9db..6129ee7 100644 --- a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs @@ -23,7 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId { base.SetUp(); } - [TestCase] + [Test] public void SharedAssociationPositive() { this.ParameterizedAuthenticationTest(true, true, false); } @@ -31,17 +31,17 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies that a shared association protects against tampering. /// </summary> - [TestCase] + [Test] public void SharedAssociationTampered() { this.ParameterizedAuthenticationTest(true, true, true); } - [TestCase] + [Test] public void SharedAssociationNegative() { this.ParameterizedAuthenticationTest(true, false, false); } - [TestCase] + [Test] public void PrivateAssociationPositive() { this.ParameterizedAuthenticationTest(false, true, false); } @@ -49,17 +49,17 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies that a private association protects against tampering. /// </summary> - [TestCase] + [Test] public void PrivateAssociationTampered() { this.ParameterizedAuthenticationTest(false, true, true); } - [TestCase] + [Test] public void NoAssociationNegative() { this.ParameterizedAuthenticationTest(false, false, false); } - [TestCase] + [Test] public void UnsolicitedAssertion() { this.MockResponder.RegisterMockRPDiscovery(); OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Test.OpenId { coordinator.Run(); } - [TestCase] + [Test] public void UnsolicitedAssertionRejected() { this.MockResponder.RegisterMockRPDiscovery(); OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// Verifies that delegating identifiers are rejected in unsolicited assertions /// when the appropriate security setting is set. /// </summary> - [TestCase] + [Test] public void UnsolicitedDelegatingIdentifierRejection() { this.MockResponder.RegisterMockRPDiscovery(); OpenIdCoordinator coordinator = new OpenIdCoordinator( diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs index e2a5aef..849c796 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { this.request = new SignedResponseRequest(Protocol.Default.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate); } - [TestCase] + [Test] public void RoundTripFullStackTest() { IOpenIdMessageExtension request = new MockOpenIdExtension("requestPart", "requestData"); IOpenIdMessageExtension response = new MockOpenIdExtension("responsePart", "responseData"); @@ -47,12 +47,12 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { new IOpenIdMessageExtension[] { response }); } - [TestCase] + [Test] public void ExtensionFactory() { Assert.AreSame(this.factory, this.rpElement.ExtensionFactory); } - [TestCase] + [Test] public void PrepareMessageForSendingNull() { Assert.IsNull(this.rpElement.ProcessOutgoingMessage(null)); } @@ -60,13 +60,13 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that false is returned when a non-extendable message is sent. /// </summary> - [TestCase] + [Test] public void PrepareMessageForSendingNonExtendableMessage() { IProtocolMessage request = new AssociateDiffieHellmanRequest(Protocol.Default.Version, OpenIdTestBase.OPUri); Assert.IsNull(this.rpElement.ProcessOutgoingMessage(request)); } - [TestCase] + [Test] public void PrepareMessageForSending() { this.request.Extensions.Add(new MockOpenIdExtension("part", "extra")); Assert.IsNotNull(this.rpElement.ProcessOutgoingMessage(this.request)); @@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { Assert.AreEqual("extra", this.request.ExtraData["openid." + alias + ".data"]); } - [TestCase] + [Test] public void PrepareMessageForReceiving() { this.request.ExtraData["openid.ns.mock"] = MockOpenIdExtension.MockTypeUri; this.request.ExtraData["openid.mock.Part"] = "part"; @@ -91,7 +91,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that extension responses are included in the OP's signature. /// </summary> - [TestCase] + [Test] public void ExtensionResponsesAreSigned() { Protocol protocol = Protocol.Default; var op = this.CreateProvider(); @@ -113,7 +113,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that unsigned extension responses (where any or all fields are unsigned) are ignored. /// </summary> - [TestCase] + [Test] public void ExtensionsAreIdentifiedAsSignedOrUnsigned() { Protocol protocol = Protocol.Default; OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -144,7 +144,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// OpenID Authentication 2.0 section 12 states that /// "A namespace MUST NOT be assigned more than one alias in the same message". /// </remarks> - [TestCase] + [Test] public void TwoExtensionsSameTypeUri() { IOpenIdMessageExtension request1 = new MockOpenIdExtension("requestPart1", "requestData1"); IOpenIdMessageExtension request2 = new MockOpenIdExtension("requestPart2", "requestData2"); diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs index df0664e..bafabe6 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { Both = 0x3, } - [TestCase] + [Test] public void BasicEncodingTest() { byte[] kvfBytes = KeyValueFormEncoding.GetBytes(this.sampleData); string responseString = Encoding.UTF8.GetString(kvfBytes); @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { } } - [TestCase] + [Test] public void EncodeDecode() { this.KVDictTest(UTF8Encoding.UTF8.GetBytes(string.Empty), new Dictionary<string, string>(), TestMode.Both); @@ -133,7 +133,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { this.Illegal("x:b\n\n", KeyValueFormConformanceLevel.OpenId20); } - [TestCase] + [Test] public void EmptyLineLoose() { Dictionary<string, string> d = new Dictionary<string, string>(); d.Add("x", "b"); @@ -145,7 +145,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { this.Illegal("x:y\na:b", KeyValueFormConformanceLevel.OpenId11); } - [TestCase] + [Test] public void LastLineNotTerminatedLoose() { Dictionary<string, string> d = new Dictionary<string, string>(); d.Add("x", "y"); diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs index b767bef..f50137d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { this.channel.WebRequestHandler = this.webHandler; } - [TestCase] + [Test] public void Ctor() { // Verify that the channel stack includes the expected types. // While other binding elements may be substituted for these, we'd then have @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that the channel sends direct message requests as HTTP POST requests. /// </summary> - [TestCase] + [Test] public void DirectRequestsUsePost() { IDirectedProtocolMessage requestMessage = new Mocks.TestDirectedMessage(MessageTransport.Direct) { Recipient = new Uri("http://host"), @@ -71,7 +71,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// class is verified elsewhere. We're only checking that the KVF class is being used by the /// <see cref="OpenIdChannel.SendDirectMessageResponse"/> method. /// </remarks> - [TestCase] + [Test] public void DirectResponsesSentUsingKeyValueForm() { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); MessageDictionary messageFields = this.MessageDescriptions.GetAccessor(message); @@ -88,7 +88,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that direct message responses are read in using the Key Value Form decoder. /// </summary> - [TestCase] + [Test] public void DirectResponsesReceivedAsKeyValueForm() { var fields = new Dictionary<string, string> { { "var1", "value1" }, @@ -103,7 +103,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that messages asking for special HTTP status codes get them. /// </summary> - [TestCase] + [Test] public void SendDirectMessageResponseHonorsHttpStatusCodes() { IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired); OutgoingWebResponse directResponse = this.channel.PrepareDirectResponseTestHook(message); diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs index 7952765..17feaa8 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs @@ -23,7 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that the signatures generated match Known Good signatures. /// </summary> - [TestCase] + [Test] public void SignaturesMatchKnownGood() { Protocol protocol = Protocol.V20; var settings = new ProviderSecuritySettings(); @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements { /// <summary> /// Verifies that all parameters in ExtraData in signed responses are signed. /// </summary> - [TestCase] + [Test] public void SignedResponsesIncludeExtraDataInSignature() { Protocol protocol = Protocol.Default; SigningBindingElement sbe = new ProviderSigningBindingElement(new ProviderAssociationHandleEncoder(new MemoryCryptoKeyStore()), new ProviderSecuritySettings()); diff --git a/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs index 2a372d9..8512053 100644 --- a/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs @@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.OpenId { [TestFixture] public class DiffieHellmanTests : OpenIdTestBase { - [TestCase] + [Test] public void Test() { string s1 = Test1(); string s2 = Test1(); diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs index e28fcf6..c145e23 100644 --- a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { [TestFixture] public class UriDiscoveryServiceTests : OpenIdTestBase { - [TestCase] + [Test] public void DiscoveryWithRedirects() { Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, false); @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual(1, this.Discover(userSuppliedIdentifier).Count()); } - [TestCase] + [Test] public void DiscoverRequireSslWithSecureRedirects() { Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true); @@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { this.Discover(userSuppliedIdentifier); } - [TestCase] + [Test] public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() { var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false); Uri secureClaimedUri = new Uri("https://localhost/secureId"); @@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count()); } - [TestCase] + [Test] public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() { var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false); @@ -91,7 +91,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count()); } - [TestCase] + [Test] public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() { var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false); string html = string.Format( @@ -113,7 +113,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual(OPLocalIdentifiersSsl[1].AbsoluteUri, this.Discover(userSuppliedIdentifier).Single().ProviderLocalIdentifier.ToString()); } - [TestCase] + [Test] public void DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds() { var insecureEndpoint = GetServiceEndpoint(0, ProtocolVersion.V20, 10, false); var secureEndpoint = GetServiceEndpoint(1, ProtocolVersion.V20, 20, true); @@ -122,7 +122,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, this.Discover(secureClaimedId).Single().ProviderLocalIdentifier); } - [TestCase] + [Test] public void XrdsDirectDiscovery_10() { this.FailDiscoverXrds("xrds-irrelevant"); this.DiscoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b"); @@ -130,14 +130,14 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { this.DiscoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b"); } - [TestCase] + [Test] public void XrdsDirectDiscovery_20() { this.DiscoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b"); this.DiscoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b"); this.DiscoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b"); } - [TestCase] + [Test] public void HtmlDiscover_11() { this.DiscoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b"); this.DiscoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b"); @@ -151,7 +151,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { this.DiscoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b"); } - [TestCase] + [Test] public void HtmlDiscover_20() { this.DiscoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b"); this.DiscoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b"); @@ -164,13 +164,13 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { this.FailDiscoverHtml("html20relative"); } - [TestCase] + [Test] public void XrdsDiscoveryFromHead() { this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml")); this.DiscoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b"); } - [TestCase] + [Test] public void XrdsDiscoveryFromHttpHeader() { WebHeaderCollection headers = new WebHeaderCollection(); headers.Add("X-XRDS-Location", new Uri("http://localhost/xrds1020.xml").AbsoluteUri); @@ -181,7 +181,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { /// <summary> /// Verifies HTML discovery proceeds if an XRDS document is referenced that doesn't contain OpenID endpoints. /// </summary> - [TestCase] + [Test] public void HtmlDiscoveryProceedsIfXrdsIsEmpty() { this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds-irrelevant.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds-irrelevant.xml")); this.DiscoverHtml("html20provWithEmptyXrds", ProtocolVersion.V20, null, "http://a/b"); @@ -190,7 +190,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { /// <summary> /// Verifies HTML discovery proceeds if the XRDS that is referenced cannot be found. /// </summary> - [TestCase] + [Test] public void HtmlDiscoveryProceedsIfXrdsIsBadOrMissing() { this.DiscoverHtml("html20provWithBadXrds", ProtocolVersion.V20, null, "http://a/b"); } @@ -198,7 +198,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { /// <summary> /// Verifies that a dual identifier yields only one service endpoint by default. /// </summary> - [TestCase] + [Test] public void DualIdentifierOffByDefault() { this.MockResponder.RegisterMockResponse(VanityUri, "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds20dual.xml")); var results = this.Discover(VanityUri).ToList(); @@ -209,7 +209,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { /// <summary> /// Verifies that a dual identifier yields two service endpoints when that feature is turned on. /// </summary> - [TestCase] + [Test] public void DualIdentifier() { this.MockResponder.RegisterMockResponse(VanityUri, "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds20dual.xml")); var rp = this.CreateRelyingParty(true); diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs index 05a54c1..fe767ea 100644 --- a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs @@ -15,7 +15,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { [TestFixture] public class XriDiscoveryProxyServiceTests : OpenIdTestBase { - [TestCase] + [Test] public void Discover() { string xrds = @"<?xml version='1.0' encoding='UTF-8'?> <XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'> @@ -62,7 +62,7 @@ namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices { Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay); } - [TestCase] + [Test] public void DiscoverCommunityInameCanonicalIDs() { string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?> <XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'> @@ -292,7 +292,7 @@ uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24"); } - [TestCase] + [Test] public void DiscoveryCommunityInameDelegateWithoutCanonicalID() { this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> { { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?> diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs index cb76f95..ab0a10b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { private const string IncrementingAttribute = "http://incatt"; private int incrementingAttributeValue = 1; - [TestCase] + [Test] public void Fetch() { var request = new FetchRequest(); request.Attributes.Add(new AttributeRequest(NicknameTypeUri)); @@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { ExtensionTestUtilities.Roundtrip(Protocol.Default, new[] { request }, new[] { response }); } - [TestCase] + [Test] public void Store() { var request = new StoreRequest(); var newAttribute = new AttributeValues( diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs index 565ff57..337663e 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs @@ -12,7 +12,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { [TestFixture] public class AttributeRequestTests : OpenIdTestBase { - [TestCase] + [Test] public void CtorDefault() { AttributeRequest req = new AttributeRequest(); Assert.AreEqual(1, req.Count); @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { new AttributeRequest(WellKnownAttributes.Contact.Email, false, -1); } - [TestCase] + [Test] public void CtorFull() { var req = new AttributeRequest(WellKnownAttributes.Contact.Email, true, 5); Assert.AreEqual(WellKnownAttributes.Contact.Email, req.TypeUri); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { req.Count = -1; } - [TestCase] + [Test] public void EqualityTests() { var req1 = new AttributeRequest(); var req2 = new AttributeRequest(); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs index 5ba90d6..6b6edd8 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs @@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { [TestFixture] public class AttributeValuesTests : OpenIdTestBase { - [TestCase] + [Test] public void Ctor() { var att = new AttributeValues(); Assert.IsNull(att.TypeUri); @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the Equals method. /// </summary> - [TestCase] + [Test] public void EqualityTests() { var att1 = new AttributeValues(); var att2 = new AttributeValues(); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs index 970dae6..62f54a2 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs @@ -18,13 +18,13 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { new FetchRequest().Attributes.Add(null); } - [TestCase] + [Test] public void AddAttributeRequest() { var req = new FetchRequest(); req.Attributes.Add(new AttributeRequest() { TypeUri = "http://someUri" }); } - [TestCase] + [Test] public void AddAttributeRequestStrangeUri() { var req = new FetchRequest(); req.Attributes.Add(new AttributeRequest() { TypeUri = "=someUri*who*knows*but*this*is*legal" }); @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { req.Attributes.Add(new AttributeRequest() { TypeUri = "http://UriTwice" }); } - [TestCase] + [Test] public void RespondSimpleValue() { var req = new AttributeRequest(); req.TypeUri = "http://someType"; @@ -47,7 +47,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreEqual("value", resp.Values[0]); } - [TestCase] + [Test] public void RespondTwoValues() { var req = new AttributeRequest(); req.TypeUri = "http://someType"; @@ -75,7 +75,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { req.Respond(null); } - [TestCase] + [Test] public void EqualityTests() { var req1 = new FetchRequest(); var req2 = new FetchRequest(); @@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that the class is serializable. /// </summary> - [TestCase] + [Test] public void Serializable() { var fetch = new FetchRequest(); fetch.Attributes.AddRequired("http://someAttribute"); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs index b135675..53d1ef4 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs @@ -13,13 +13,13 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { [TestFixture] public class FetchResponseTests : OpenIdTestBase { - [TestCase] + [Test] public void AddAttribute() { var response = new FetchResponse(); response.Attributes.Add(new AttributeValues("http://someattribute", "Value1")); } - [TestCase] + [Test] public void AddTwoAttributes() { var response = new FetchResponse(); response.Attributes.Add(new AttributeValues("http://someattribute", "Value1")); @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { response.Attributes.Add(null); } - [TestCase] + [Test] public void GetAttributeValue() { var response = new FetchResponse(); @@ -55,7 +55,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreEqual("a", response.GetAttributeValue("http://someattribute3")); } - [TestCase] + [Test] public void EqualityTests() { var response1 = new FetchResponse(); var response2 = new FetchResponse(); @@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that the class is serializable. /// </summary> - [TestCase] + [Test] public void Serializable() { var fetch = new FetchResponse(); fetch.Attributes.Add("http://someAttribute", "val1", "val2"); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs index 2a491f6..9741be3 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs @@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the constructor behavior. /// </summary> - [TestCase] + [Test] public void Ctor() { var req = new StoreRequest(); Assert.IsFalse(req.Attributes.Any()); @@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the AddAttribute method. /// </summary> - [TestCase] + [Test] public void AddAttributeByValue() { var req = new StoreRequest(); AttributeValues value = new AttributeValues(); @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the AddAttribute method. /// </summary> - [TestCase] + [Test] public void AddAttributeByPrimitives() { var req = new StoreRequest(); req.Attributes.Add("http://att1", "value1", "value2"); @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the Equals method. /// </summary> - [TestCase] + [Test] public void EqualityTests() { var req1 = new StoreRequest(); var req2 = new StoreRequest(); @@ -71,7 +71,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies that the class is serializable. /// </summary> - [TestCase] + [Test] public void Serializable() { var store = new StoreRequest(); store.Attributes.Add("http://someAttribute", "val1", "val2"); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs index d0b4616..32682bd 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs @@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the constructor's behavior. /// </summary> - [TestCase] + [Test] public void Ctor() { var response = new StoreResponse(); Assert.IsTrue(response.Succeeded, "The default status should be Succeeded."); @@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies the Equals method. /// </summary> - [TestCase] + [Test] public void EqualityTests() { var response1 = new StoreResponse(); var response2 = new StoreResponse(); @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange { /// <summary> /// Verifies that the class is serializable. /// </summary> - [TestCase] + [Test] public void Serializable() { var store = new StoreResponse(); store.Succeeded = false; diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs index aca1d8e..9592605 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies no extensions appear as no extensions /// </summary> - [TestCase] + [Test] public void NoRequestedExtensions() { var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.request); Assert.IsNull(sreg); @@ -52,7 +52,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreSame(sregResponse, extensions.Single()); } - [TestCase] + [Test] public void NegativeResponse() { this.request.IsAuthenticated = false; ExtensionsInteropHelper.ConvertSregToMatchRequest(this.request); @@ -61,7 +61,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies sreg coming in is seen as sreg. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregWithSreg() { var sregInjected = new ClaimsRequest(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns) { Nickname = DemandLevel.Request, @@ -82,7 +82,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies AX coming in looks like sreg. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregWithAX() { this.ParameterizedAXTest(AXAttributeFormats.AXSchemaOrg); } @@ -90,7 +90,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies AX coming in looks like sreg. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregWithAXSchemaOpenIdNet() { this.ParameterizedAXTest(AXAttributeFormats.SchemaOpenIdNet); } @@ -98,7 +98,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies sreg and AX in one request has a preserved sreg request. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregWithBothSregAndAX() { var sregInjected = new ClaimsRequest(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns) { Nickname = DemandLevel.Request, diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs index 1d40c4a..b5bcd7b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs @@ -44,7 +44,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that without an Sreg extension to copy from, no AX extension request is added. /// </summary> - [TestCase] + [Test] public void SpreadSregToAXNoExtensions() { ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg); Assert.AreEqual(0, this.authReq.AppliedExtensions.Count()); @@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that Sreg requests are correctly copied to axschema.org AX requests. /// </summary> - [TestCase] + [Test] public void SpreadSregToAXBasic() { this.authReq.AddExtension(this.sreg); ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg); @@ -72,7 +72,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that sreg can spread to multiple AX schemas. /// </summary> - [TestCase] + [Test] public void SpreadSregToAxMultipleSchemas() { this.authReq.AddExtension(this.sreg); ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg | AXAttributeFormats.SchemaOpenIdNet); @@ -85,7 +85,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies no spread if the OP advertises sreg support. /// </summary> - [TestCase] + [Test] public void SpreadSregToAxNoOpIfOPSupportsSreg() { this.authReq.AddExtension(this.sreg); this.InjectAdvertisedTypeUri(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns); @@ -96,7 +96,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies a targeted AX request if the OP advertises a recognized type URI format. /// </summary> - [TestCase] + [Test] public void SpreadSregToAxTargetedAtOPFormat() { this.authReq.AddExtension(this.sreg); this.InjectAdvertisedTypeUri(WellKnownAttributes.Name.FullName); @@ -109,7 +109,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that TransformAXFormat correctly translates AX schema Type URIs. /// </summary> - [TestCase] + [Test] public void TransformAXFormatTest() { Assert.AreEqual(WellKnownAttributes.Name.Alias, ExtensionsInteropProviderHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.AXSchemaOrg)); Assert.AreEqual("http://schema.openid.net/namePerson/friendly", ExtensionsInteropProviderHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet)); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs index a5ce44a..b8ae42c 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that with no extensions present, UnifyExtensionsAsSreg returns an empty ClaimsResponse. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregNoExtensions() { var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.response, true); Assert.IsNotNull(sreg); @@ -44,7 +44,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies that with sreg and AX extensions present, the sreg extension is returned. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregWithSreg() { var sregInjected = new ClaimsResponse { Nickname = "andy", @@ -61,7 +61,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies UnifyExtensionsAsSreg correctly converts AX to sreg. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsAsSregFromAXSchemaOrg() { var axInjected = new FetchResponse(); axInjected.Attributes.Add(WellKnownAttributes.Name.Alias, "nate"); @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { /// <summary> /// Verifies UnifyExtensionsAsSreg correctly converts AX in a non-standard format to sreg. /// </summary> - [TestCase] + [Test] public void UnifyExtensionsasSregFromSchemaOpenIdNet() { var axInjected = new FetchResponse(); axInjected.Attributes.Add(ExtensionsInteropProviderHelper.TransformAXFormatTestHook(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet), "nate"); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs index c1b721e..cba54bf 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs @@ -13,14 +13,14 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { [TestFixture] public class PapeRoundTripTests : OpenIdTestBase { - [TestCase] + [Test] public void Trivial() { var request = new PolicyRequest(); var response = new PolicyResponse(); ExtensionTestUtilities.Roundtrip(Protocol.Default, new[] { request }, new[] { response }); } - [TestCase] + [Test] public void Full() { var request = new PolicyRequest(); request.MaximumAuthenticationAge = TimeSpan.FromMinutes(10); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs index b6191e5..0806754 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs @@ -17,7 +17,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { [TestFixture] public class PolicyRequestTests : OpenIdTestBase { - [TestCase] + [Test] public void Ctor() { PolicyRequest req = new PolicyRequest(); Assert.IsNull(req.MaximumAuthenticationAge); @@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(0, req.PreferredPolicies.Count); } - [TestCase] + [Test] public void MaximumAuthenticationAgeTest() { PolicyRequest req = new PolicyRequest(); req.MaximumAuthenticationAge = TimeSpan.FromHours(1); @@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.IsNull(req.MaximumAuthenticationAge); } - [TestCase] + [Test] public void AddPolicies() { PolicyRequest resp = new PolicyRequest(); resp.PreferredPolicies.Add(AuthenticationPolicies.MultiFactor); @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(AuthenticationPolicies.PhishingResistant, resp.PreferredPolicies[1]); } - [TestCase] + [Test] public void AddPolicyMultipleTimes() { // Although this isn't really the desired behavior (we'd prefer to see an // exception thrown), since we're using a List<string> internally we can't @@ -57,7 +57,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(2, resp.PreferredPolicies.Count); } - [TestCase] + [Test] public void AddAuthLevelTypes() { PolicyRequest req = new PolicyRequest(); req.PreferredAuthLevelTypes.Add(Constants.AssuranceLevels.NistTypeUri); @@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.IsTrue(req.PreferredAuthLevelTypes.Contains(Constants.AssuranceLevels.NistTypeUri)); } - [TestCase] + [Test] public void EqualsTest() { PolicyRequest req = new PolicyRequest(); PolicyRequest req2 = new PolicyRequest(); @@ -104,7 +104,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(req, req2); } - [TestCase] + [Test] public void Serialize() { PolicyRequest req = new PolicyRequest(); IMessageWithEvents reqEvents = req; diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs index be6244a..8126d65 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs @@ -20,7 +20,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { private static readonly DateTime someUtcTime = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc); private static readonly DateTime someUnspecifiedTime = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Unspecified); - [TestCase] + [Test] public void Ctor() { PolicyResponse resp = new PolicyResponse(); Assert.IsNotNull(resp.ActualPolicies); @@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.IsNull(resp.NistAssuranceLevel); } - [TestCase] + [Test] public void AddPolicies() { PolicyResponse resp = new PolicyResponse(); resp.ActualPolicies.Add(AuthenticationPolicies.MultiFactor); @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(AuthenticationPolicies.PhishingResistant, resp.ActualPolicies[1]); } - [TestCase] + [Test] public void AddPolicyMultipleTimes() { // Although this isn't really the desired behavior (we'd prefer to see an // exception thrown), since we're using a List<string> internally we can't @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(2, resp.ActualPolicies.Count); } - [TestCase] + [Test] public void AuthenticationTimeUtcConvertsToUtc() { PolicyResponse resp = new PolicyResponse(); resp.AuthenticationTimeUtc = someLocalTime; @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(someLocalTime.ToUniversalTime(), resp.AuthenticationTimeUtc.Value); } - [TestCase] + [Test] public void AuthenticationTimeUtcSetUtc() { PolicyResponse resp = new PolicyResponse(); resp.AuthenticationTimeUtc = someUtcTime; @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { resp.AuthenticationTimeUtc = someUnspecifiedTime; } - [TestCase] + [Test] public void AuthenticationTimeUtcSetNull() { PolicyResponse resp = new PolicyResponse(); resp.AuthenticationTimeUtc = null; @@ -84,7 +84,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.IsNull(resp.AuthenticationTimeUtc); } - [TestCase] + [Test] public void NistAssuranceLevelSetVarious() { PolicyResponse resp = new PolicyResponse(); resp.NistAssuranceLevel = NistAssuranceLevel.Level1; @@ -95,7 +95,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(NistAssuranceLevel.InsufficientForLevel1, resp.NistAssuranceLevel); } - [TestCase] + [Test] public void AssuranceLevels() { PolicyResponse resp = new PolicyResponse(); Assert.AreEqual(0, resp.AssuranceLevels.Count); @@ -108,7 +108,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.IsNull(resp.NistAssuranceLevel); } - [TestCase] + [Test] public void EqualsTest() { PolicyResponse resp = new PolicyResponse(); PolicyResponse resp2 = new PolicyResponse(); @@ -164,7 +164,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy { Assert.AreEqual(resp, resp2); } - [TestCase] + [Test] public void Serialize() { PolicyResponse resp = new PolicyResponse(); IMessageWithEvents respEvents = resp; diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs index 69ece9d..6be02e7 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs @@ -12,7 +12,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { [TestFixture] public class ClaimsRequestTests : OpenIdTestBase { - [TestCase] + [Test] public void CreateResponse() { // some unofficial type URIs... this.ParameterizedTypeUriPreservedTest("http://openid.net/sreg/1.0"); @@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { this.ParameterizedTypeUriPreservedTest("http://openid.net/extensions/sreg/1.1"); } - [TestCase] + [Test] public void RequiredOptionalLists() { ClaimsRequest req = new ClaimsRequest(); MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(req); @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreEqual("nickname,postcode", dictionary["required"]); } - [TestCase] + [Test] public void EqualityTests() { ClaimsRequest req1 = new ClaimsRequest(); ClaimsRequest req2 = new ClaimsRequest(); diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs index 365ba5d..1b2c2ec 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs @@ -17,7 +17,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { [TestFixture] public class ClaimsResponseTests { - [TestCase] + [Test] public void EmptyMailAddress() { ClaimsResponse response = new ClaimsResponse(Constants.sreg_ns); response.Email = string.Empty; @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreEqual(fields, fields2); } - [TestCase] + [Test] public void EqualityTest() { ClaimsResponse fields1 = this.GetFilledData(); @@ -96,7 +96,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { Assert.AreNotEqual(fields1, fields2); } - [TestCase] + [Test] public void Birthdates() { var response = new ClaimsResponse(); // Verify that they both start out as null @@ -131,7 +131,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions { response.BirthDateRaw = "2008"; } - [TestCase] + [Test] public void ResponseAlternateTypeUriTests() { var request = new ClaimsRequest(Constants.sreg_ns10); request.Email = DemandLevel.Require; diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs index a33dc09..97a8545 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs @@ -12,7 +12,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI { [TestFixture] public class UIRequestTests : OpenIdTestBase { - [TestCase] + [Test] public void Defaults() { var request = new UIRequest(); Assert.AreEqual("popup", request.Mode); @@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI { Assert.IsFalse(request.Icon.HasValue); } - [TestCase] + [Test] public void IconEncodingDecoding() { var request = new UIRequest(); @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI { Assert.AreEqual("true", dictionary["icon"]); } - [TestCase] + [Test] public void LanguagePreferenceEncodingDecoding() { var request = new UIRequest(); MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(request); @@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI { Assert.AreEqual(new CultureInfo("es-ES"), request.LanguagePreference[1]); } - [TestCase] + [Test] public void ModeEncoding() { var request = new UIRequest(); MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(request); diff --git a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs index f8b05db..ee9ad6b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs @@ -18,14 +18,14 @@ namespace DotNetOpenAuth.Test.OpenId { private string uriHttps = "https://www.yahoo.com/"; private string xri = "=arnott*andrew"; - [TestCase] + [Test] public void TryParseNoThrow() { Identifier id; Assert.IsFalse(Identifier.TryParse(null, out id)); Assert.IsFalse(Identifier.TryParse(string.Empty, out id)); } - [TestCase] + [Test] public void TryParse() { Identifier id; Assert.IsTrue(Identifier.TryParse("http://host/path", out id)); @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.AreEqual("=arnott", id.ToString()); } - [TestCase] + [Test] public void Parse() { Assert.IsInstanceOf<UriIdentifier>(Identifier.Parse(this.uri)); Assert.IsInstanceOf<XriIdentifier>(Identifier.Parse(this.xri)); @@ -43,7 +43,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Tests conformance with 2.0 spec section 7.2#2 /// </summary> - [TestCase] + [Test] public void ParseEndUserSuppliedXriIdentifer() { List<char> symbols = new List<char>(XriIdentifier.GlobalContextSymbols); symbols.Add('('); @@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies conformance with 2.0 spec section 7.2#3 /// </summary> - [TestCase] + [Test] public void ParseEndUserSuppliedUriIdentifier() { // verify a fully-qualified Uri var id = Identifier.Parse(this.uri); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs index b97a894..fd10b15 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs @@ -20,12 +20,12 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.request = new AssociateDiffieHellmanRequest(Protocol.V20.Version, Recipient); } - [TestCase] + [Test] public void Ctor() { Assert.AreEqual(Recipient, this.request.Recipient); } - [TestCase] + [Test] public void Mode() { Assert.AreEqual("associate", this.request.Mode); } diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs index 0c7a96a..72931c5 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs @@ -25,17 +25,17 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.request = new AssociateUnencryptedRequest(this.protocol.Version, this.secureRecipient); } - [TestCase] + [Test] public void ConstructorTest() { Assert.AreEqual(this.secureRecipient, this.request.Recipient); } - [TestCase] + [Test] public void Mode() { Assert.AreEqual(this.protocol.Args.Mode.associate, this.request.Mode); } - [TestCase] + [Test] public void MessagePartsTest() { this.request.AssociationType = this.protocol.Args.SignatureAlgorithm.HMAC_SHA1; this.request.SessionType = this.protocol.Args.SessionType.NoEncryption; @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual(this.protocol.Args.SessionType.NoEncryption, dict[this.protocol.openid.session_type]); } - [TestCase] + [Test] public void ValidMessageTest() { this.request = new AssociateUnencryptedRequest(Protocol.V20.Version, this.secureRecipient); this.request.AssociationType = this.protocol.Args.SignatureAlgorithm.HMAC_SHA1; @@ -65,12 +65,12 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.request.EnsureValidMessage(); // no-encryption only allowed for secure channels. } - [TestCase] + [Test] public void RequiredProtection() { Assert.AreEqual(MessageProtections.None, this.request.RequiredProtection); } - [TestCase] + [Test] public void Transport() { Assert.AreEqual(MessageTransport.Direct, this.request.Transport); } @@ -78,7 +78,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { /// <summary> /// Verifies security settings limit RP's initial associate request /// </summary> - [TestCase] + [Test] public void AssociateRequestDeterminedBySecuritySettings() { Protocol protocol = Protocol.V20; SecuritySettings securitySettings = new RelyingPartySecuritySettings(); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs index 3668333..99a0ed9 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs @@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.response = new AssociateUnencryptedResponse(request.Version, request); } - [TestCase] + [Test] public void ParameterNames() { this.response.AssociationHandle = "HANDLE"; this.response.AssociationType = "HMAC-SHA1"; @@ -38,12 +38,12 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual("50", fields["expires_in"]); } - [TestCase] + [Test] public void RequiredProtection() { Assert.AreEqual(MessageProtections.None, this.response.RequiredProtection); } - [TestCase] + [Test] public void Transport() { Assert.AreEqual(MessageTransport.Direct, this.response.Transport); } diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs index f5f5592..6b06dc8 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs @@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.response = new AssociateUnsuccessfulResponse(request.Version, request); } - [TestCase] + [Test] public void ParameterNames() { this.response.ErrorMessage = "Some Error"; this.response.AssociationType = "HMAC-SHA1"; diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs index f1bcc57..79723ff 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs @@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { /// and cause the authentication to inappropriately fail. /// Designed to verify fix to Trac #198. /// </remarks> - [TestCase] + [Test] public void ExactPositiveAssertionPreservation() { var rp = CreateRelyingParty(true); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs index 1ce97fe..b8adc1f 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs @@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { base.SetUp(); } - [TestCase] + [Test] public void IsValid() { Protocol protocol = Protocol.Default; var request = new CheckAuthenticationRequest(protocol.Version, OPUri); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs index 06ef82d..d5de6b2 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs @@ -24,7 +24,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.response = new DirectErrorResponse(request.Version, request); } - [TestCase] + [Test] public void ParameterNames() { this.response.ErrorMessage = "Some Error"; this.response.Contact = "Andrew Arnott"; @@ -42,7 +42,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { /// Verifies that error messages are created as HTTP 400 errors, /// per OpenID 2.0 section 5.1.2.2. /// </summary> - [TestCase] + [Test] public void ErrorMessagesAsHttp400() { var httpStatusMessage = (IHttpDirectResponse)this.response; Assert.AreEqual(HttpStatusCode.BadRequest, httpStatusMessage.HttpStatusCode); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs index 0e4ddae..fd4953a 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs @@ -23,12 +23,12 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.response = new IndirectErrorResponse(request); } - [TestCase] + [Test] public void Ctor() { Assert.AreEqual(RPUri, this.response.Recipient); } - [TestCase] + [Test] public void ParameterNames() { this.response.ErrorMessage = "Some Error"; this.response.Contact = "Andrew Arnott"; diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs index 1aceb17..ac49a14 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs @@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.unsolicited = new IndirectSignedResponse(this.protocol.Version, RPUri); } - [TestCase] + [Test] public void CtorFromRequest() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.response.Mode); Assert.AreEqual(this.request.Version, this.response.Version); @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.IsTrue(DateTime.UtcNow - ((ITamperResistantOpenIdMessage)this.response).UtcCreationDate < TimeSpan.FromSeconds(5)); } - [TestCase] + [Test] public void CtorUnsolicited() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.unsolicited.Mode); Assert.AreEqual(this.protocol.Version, this.unsolicited.Version); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual(OPUri, this.unsolicited.ProviderEndpoint); } - [TestCase] + [Test] public void ResponseNonceSetter() { const string HybridValue = CreationDateString + "UNIQUE"; IReplayProtectedProtocolMessage responseReplay = this.response; @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.IsNull(responseReplay.Nonce); } - [TestCase] + [Test] public void ResponseNonceGetter() { IReplayProtectedProtocolMessage responseReplay = this.response; responseReplay.Nonce = "UnIqUe"; @@ -84,7 +84,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate); } - [TestCase] + [Test] public void UtcCreationDateConvertsToUniversal() { IReplayProtectedProtocolMessage responseReplay = this.response; DateTime local = DateTime.Parse("1982-01-01", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal); @@ -107,7 +107,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual(this.creationDate.Hour, utcCreationDate.Hour, "The hour should match since both times are UTC time."); } - [TestCase] + [Test] public void ReturnToDoesNotMatchRecipient() { // Make sure its valid first, so we know that when it's invalid // it is due to our tampering. @@ -135,14 +135,14 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.response.GetReturnToArgument(string.Empty); } - [TestCase] + [Test] public void GetReturnToArgumentDoesNotReturnExtraArgs() { this.response.ExtraData["a"] = "b"; Assert.IsNull(this.response.GetReturnToArgument("a")); Assert.AreEqual(0, this.response.GetReturnToParameterNames().Count()); } - [TestCase] + [Test] public void GetReturnToArgumentAndNames() { UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo); returnToBuilder.AppendQueryArgs(new Dictionary<string, string> { { "a", "b" } }); diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs index 9fe2246..76178b0 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs @@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { base.SetUp(); } - [TestCase] + [Test] public void Mode() { var setupRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Setup); setupRequestV1.ReturnTo = RPUri; @@ -52,7 +52,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { new NegativeAssertionResponse(immediateRequestV1).EnsureValidMessage(); } - [TestCase] + [Test] public void UserSetupUrlSetForV1Immediate() { var immediateRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Immediate); immediateRequestV1.ReturnTo = RPUri; @@ -61,7 +61,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { response.EnsureValidMessage(); } - [TestCase] + [Test] public void UserSetupUrlNotRequiredInV1SetupOrV2() { var setupRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Setup); setupRequestV1.ReturnTo = RPUri; diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs index 3a4cffa..75a5daf 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs @@ -38,7 +38,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { this.unsolicited = new PositiveAssertionResponse(this.protocol.Version, RPUri); } - [TestCase] + [Test] public void CtorFromRequest() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.response.Mode); Assert.AreEqual(this.request.Version, this.response.Version); @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { Assert.AreEqual(OPUri, this.response.ProviderEndpoint); } - [TestCase] + [Test] public void CtorUnsolicited() { Assert.AreEqual(this.protocol.Args.Mode.id_res, this.unsolicited.Mode); Assert.AreEqual(this.protocol.Version, this.unsolicited.Version); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages { /// <summary> /// Verifies that local_id and claimed_id can either be null or specified. /// </summary> - [TestCase] + [Test] public void ClaimedIdAndLocalIdSpecifiedIsValid() { this.response.LocalIdentifier = "http://local"; this.response.ClaimedIdentifier = "http://claimedid"; diff --git a/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs b/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs index a14dd5c..393239b 100644 --- a/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs @@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Test.OpenId { [TestFixture] public class NonIdentityTests : OpenIdTestBase { - [TestCase] + [Test] public void ExtensionOnlyChannelLevel() { Protocol protocol = Protocol.V20; AuthenticationRequestMode mode = AuthenticationRequestMode.Setup; @@ -30,7 +30,7 @@ namespace DotNetOpenAuth.Test.OpenId { coordinator.Run(); } - [TestCase] + [Test] public void ExtensionOnlyFacadeLevel() { Protocol protocol = Protocol.V20; var coordinator = new OpenIdCoordinator( diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs index c6c368b..9b39522 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies that IsApproved controls which response message is returned. /// </summary> - [TestCase] + [Test] public void IsApprovedDeterminesReturnedMessage() { var op = CreateProvider(); Protocol protocol = Protocol.V20; diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs index b5cdc84..8cc7116 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs @@ -17,7 +17,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies the user_setup_url is set properly for immediate negative responses. /// </summary> - [TestCase] + [Test] public void UserSetupUrl() { // Construct a V1 immediate request Protocol protocol = Protocol.V11; @@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { Assert.IsNotNull(userSetupUrl); // Now construct a new request as if it had just come in. - HttpRequestInfo httpRequest = new HttpRequestInfo { UrlBeforeRewriting = userSetupUrl }; + HttpRequestInfo httpRequest = new HttpRequestInfo("GET", userSetupUrl); var setupRequest = (AuthenticationRequest)provider.GetRequest(httpRequest); var setupRequestMessage = (CheckIdRequest)setupRequest.RequestMessage; diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs index 56ec789..2e3e7ec 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs @@ -30,12 +30,12 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { this.request = new AuthenticationRequest(this.provider, this.checkIdRequest); } - [TestCase] + [Test] public void IsReturnUrlDiscoverableNoResponse() { Assert.AreEqual(RelyingPartyDiscoveryResult.NoServiceDocument, this.request.IsReturnUrlDiscoverable(this.provider.Channel.WebRequestHandler)); } - [TestCase] + [Test] public void IsReturnUrlDiscoverableValidResponse() { this.MockResponder.RegisterMockRPDiscovery(); this.request = new AuthenticationRequest(this.provider, this.checkIdRequest); @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// Verifies that when discovery would be performed over standard HTTP and RequireSsl /// is set, that discovery fails. /// </summary> - [TestCase] + [Test] public void IsReturnUrlDiscoverableNotSsl() { this.provider.SecuritySettings.RequireSsl = true; this.MockResponder.RegisterMockRPDiscovery(); @@ -56,7 +56,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies that when discovery would be performed over HTTPS that discovery succeeds. /// </summary> - [TestCase] + [Test] public void IsReturnUrlDiscoverableRequireSsl() { this.MockResponder.RegisterMockRPDiscovery(); this.checkIdRequest.Realm = RPRealmUriSsl; @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { Assert.AreEqual(RelyingPartyDiscoveryResult.Success, this.request.IsReturnUrlDiscoverable(this.provider.Channel.WebRequestHandler)); } - [TestCase] + [Test] public void IsReturnUrlDiscoverableValidButNoMatch() { this.MockResponder.RegisterMockRPDiscovery(); this.provider.SecuritySettings.RequireSsl = false; // reset for another failure test case diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs index ad37978..598aeb7 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs @@ -47,14 +47,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies the SecuritySettings property can be set to a new instance. /// </summary> - [TestCase] + [Test] public void SecuritySettings() { var newSettings = new ProviderSecuritySettings(); this.provider.SecuritySettings = newSettings; Assert.AreSame(newSettings, this.provider.SecuritySettings); } - [TestCase] + [Test] public void ExtensionFactories() { var factories = this.provider.ExtensionFactories; Assert.IsNotNull(factories); @@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies the Channel property. /// </summary> - [TestCase] + [Test] public void ChannelGetter() { Assert.IsNotNull(this.provider.Channel); } @@ -90,12 +90,11 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { /// <summary> /// Verifies that GetRequest correctly returns the right messages. /// </summary> - [TestCase] + [Test] public void GetRequest() { - HttpRequestInfo httpInfo = new HttpRequestInfo(); - httpInfo.UrlBeforeRewriting = new Uri("http://someUri"); + var httpInfo = new HttpRequestInfo("GET", new Uri("http://someUri")); Assert.IsNull(this.provider.GetRequest(httpInfo), "An irrelevant request should return null."); - var providerDescription = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version); + var providerDescription = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); // Test some non-empty request scenario. OpenIdCoordinator coordinator = new OpenIdCoordinator( @@ -110,7 +109,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { coordinator.Run(); } - [TestCase] + [Test] public void BadRequestsGenerateValidErrorResponses() { var coordinator = new OpenIdCoordinator( rp => { diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs index 5e8c28a..e2c719d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { this.provider = CreateProvider(); } - [TestCase] + [Test] public void AssociateDH() { var associateRequest = this.CreateAssociateRequest(OPUri); MeasurePerformance( @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { iterations: 1); } - [TestCase] + [Test] public void AssociateClearText() { var associateRequest = this.CreateAssociateRequest(OPUriSsl); // SSL will cause a plaintext association MeasurePerformance( @@ -59,14 +59,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { iterations: 1000); } - [TestCase] + [Test] public void CheckIdSharedHmacSha1Association() { Protocol protocol = Protocol.Default; string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA1; this.ParameterizedCheckIdTest(protocol, assocType); } - [TestCase] + [Test] public void CheckIdSharedHmacSha256Association() { Protocol protocol = Protocol.Default; string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA256; @@ -102,7 +102,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { ms.Position = 0; var headers = new WebHeaderCollection(); headers.Add(HttpRequestHeader.ContentType, Channel.HttpFormUrlEncoded); - var httpRequest = new HttpRequestInfo("POST", opEndpoint, opEndpoint.PathAndQuery, headers, ms); + var httpRequest = new HttpRequestInfo("POST", opEndpoint, headers, ms); return httpRequest; } @@ -122,8 +122,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider { Channel rpChannel = rp.Channel; UriBuilder receiver = new UriBuilder(OPUri); receiver.Query = MessagingUtilities.CreateQueryString(rpChannel.MessageDescriptions.GetAccessor(checkidMessage)); - var headers = new WebHeaderCollection(); - var httpRequest = new HttpRequestInfo("GET", receiver.Uri, receiver.Uri.PathAndQuery, headers, null); + var httpRequest = new HttpRequestInfo("GET", receiver.Uri); return httpRequest; } } diff --git a/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs b/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs index 8d328b1..783bf1f 100644 --- a/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs @@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.OpenId { [TestFixture] public class ProviderEndpointDescriptionTests : OpenIdTestBase { - [TestCase] + [Test] public void NonNullCapabilities() { var epd = new ProviderEndpointDescription(OPUri, Protocol.Default.Version); Assert.IsNotNull(epd.Capabilities); diff --git a/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs index 65d00ee..20f9fe2 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs @@ -11,7 +11,7 @@ namespace DotNetOpenAuth.Test { [TestFixture] public class RealmTests { - [TestCase] + [Test] public void ValidRealmsTest() { // Just create these. If any are determined to be invalid, // an exception should be thrown that would fail this test. @@ -26,67 +26,67 @@ namespace DotNetOpenAuth.Test { new Realm("http://*.guest.myopenid.com/"); } - [TestCase] + [Test] [ExpectedException(typeof(ArgumentNullException))] public void InvalidRealmNullString() { new Realm((string)null); } - [TestCase] + [Test] [ExpectedException(typeof(ArgumentNullException))] public void InvalidRealmNullUri() { new Realm((Uri)null); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmEmpty() { new Realm(string.Empty); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmBadProtocol() { new Realm("asdf://www.microsoft.com/"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmNoScheme() { new Realm("www.guy.com"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmBadWildcard1() { new Realm("http://*www.my.com"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmBadWildcard2() { new Realm("http://www.*.com"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmBadWildcard3() { new Realm("http://www.my.*/"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmTwoWildcards1() { new Realm("http://**.my.com"); } - [TestCase] + [Test] [ExpectedException(typeof(UriFormatException))] public void InvalidRealmTwoWildcards2() { new Realm("http://*.*.my.com"); } - [TestCase] + [Test] public void IsSaneTest() { Assert.IsTrue(new Realm("http://www.myopenid.com").IsSane); Assert.IsTrue(new Realm("http://myopenid.com").IsSane); @@ -98,7 +98,7 @@ namespace DotNetOpenAuth.Test { Assert.IsFalse(new Realm("http://*.co.uk").IsSane); } - [TestCase] + [Test] public void IsUrlWithinRealmTests() { /* * The openid.return_to URL MUST descend from the openid.trust_root, or the @@ -166,7 +166,7 @@ namespace DotNetOpenAuth.Test { Assert.IsFalse(new Realm("http://www.my.com/abc").Contains("http://www.my.com/ABC")); } - [TestCase] + [Test] public void ImplicitConversionFromStringTests() { Realm realm = "http://host"; Assert.AreEqual("host", realm.Host); @@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test { Assert.IsNull(realm); } - [TestCase] + [Test] public void ImplicitConversionToStringTests() { Realm realm = new Realm("http://host/"); string realmString = realm; @@ -184,7 +184,7 @@ namespace DotNetOpenAuth.Test { Assert.IsNull(realmString); } - [TestCase] + [Test] public void ImplicitConverstionFromUriTests() { Uri uri = new Uri("http://host"); Realm realm = uri; @@ -194,7 +194,7 @@ namespace DotNetOpenAuth.Test { Assert.IsNull(realm); } - [TestCase] + [Test] public void EqualsTest() { Realm testRealm1a = new Realm("http://www.yahoo.com"); Realm testRealm1b = new Realm("http://www.yahoo.com"); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs index 52bbded..b4113a6 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AssociationsTests.cs @@ -26,17 +26,17 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { this.assocs = new Associations(); } - [TestCase] + [Test] public void GetNonexistentHandle() { Assert.IsNull(this.assocs.Get("someinvalidhandle")); } - [TestCase] + [Test] public void RemoveNonexistentHandle() { Assert.IsFalse(this.assocs.Remove("someinvalidhandle")); } - [TestCase] + [Test] public void HandleLifecycle() { Association a = HmacShaAssociation.Create( Protocol.Default, @@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.IsFalse(this.assocs.Remove(a.Handle)); } - [TestCase] + [Test] public void Best() { Association a = HmacShaAssociation.Create( Protocol.Default, diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs index de53a36..a7e9144 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs @@ -36,7 +36,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies IsDirectedIdentity returns true when appropriate. /// </summary> - [TestCase] + [Test] public void IsDirectedIdentity() { var iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId); Assert.IsFalse(iauthRequest.IsDirectedIdentity); @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies ClaimedIdentifier behavior. /// </summary> - [TestCase] + [Test] public void ClaimedIdentifier() { var iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.delegatedLocalId); Assert.AreEqual(this.claimedId, iauthRequest.ClaimedIdentifier); @@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies ProviderVersion behavior. /// </summary> - [TestCase] + [Test] public void ProviderVersion() { var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId); Assert.AreEqual(this.protocol.Version, authRequest.DiscoveryResult.Version); @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies RedirectingResponse. /// </summary> - [TestCase] + [Test] public void CreateRequestMessage() { OpenIdCoordinator coordinator = new OpenIdCoordinator( rp => { @@ -107,7 +107,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that delegating authentication requests are filtered out when configured to do so. /// </summary> - [TestCase] + [Test] public void CreateFiltersDelegatingIdentifiers() { Identifier id = GetMockIdentifier(ProtocolVersion.V20, false, true); var rp = CreateRelyingParty(); @@ -123,7 +123,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies the Provider property returns non-null. /// </summary> - [TestCase] + [Test] public void Provider() { var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId); Assert.IsNotNull(authRequest.Provider); @@ -134,7 +134,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that AddCallbackArguments adds query arguments to the return_to URL of the message. /// </summary> - [TestCase] + [Test] public void AddCallbackArgument() { var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId); Assert.AreEqual(this.returnTo, authRequest.ReturnToUrl); @@ -148,7 +148,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that AddCallbackArguments replaces pre-existing parameter values /// rather than appending them. /// </summary> - [TestCase] + [Test] public void AddCallbackArgumentClearsPreviousArgument() { UriBuilder returnToWithArgs = new UriBuilder(this.returnTo); returnToWithArgs.AppendQueryArgs(new Dictionary<string, string> { { "p1", "v1" } }); @@ -163,7 +163,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies identity-less checkid_* request behavior. /// </summary> - [TestCase] + [Test] public void NonIdentityRequest() { var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId); authRequest.IsExtensionOnly = true; @@ -176,7 +176,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that discovery on identifiers that serve as OP identifiers and claimed identifiers /// only generate OP Identifier auth requests. /// </summary> - [TestCase] + [Test] public void DualIdentifierUsedOnlyAsOPIdentifierForAuthRequest() { var rp = this.CreateRelyingParty(true); var results = AuthenticationRequest.Create(GetMockDualIdentifier(), rp, this.realm, this.returnTo, false).ToList(); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs index d67a124..1b01b7e 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs @@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { new FailedAuthenticationResponse(null); } - [TestCase] + [Test] public void CommonProperties() { Assert.AreEqual(AuthenticationStatus.Failed, this.response.Status); Assert.AreSame(this.exception, this.response.Exception); @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.IsNull(this.response.FriendlyIdentifierForDisplay); } - [TestCase] + [Test] public void CommonMethods() { Assert.IsNull(this.response.GetExtension<ClaimsRequest>()); Assert.IsNull(this.response.GetExtension(typeof(ClaimsRequest))); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs index 8d2309a..929a0fb 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs @@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { base.SetUp(); } - [TestCase] + [Test] public void Ctor() { IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority); Assert.AreEqual(this.claimedId, se.ClaimedIdentifier); @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.AreEqual(this.servicePriority, se.ServicePriority); } - [TestCase] + [Test] public void CtorImpliedLocalIdentifier() { IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, null, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority); Assert.AreEqual(this.claimedId, se.ClaimedIdentifier); @@ -54,7 +54,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { CollectionAssert<string>.AreEquivalent(this.v20TypeUris, se.Capabilities); } - [TestCase] + [Test] public void ProtocolDetection() { IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority); Assert.AreSame(Protocol.V20, se.Protocol); @@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.AreSame(Protocol.V11, se.Protocol); } - [TestCase] + [Test] public void EqualsTests() { IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority); IdentifierDiscoveryResult se2 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), (int?)null, (int?)null); @@ -92,7 +92,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.IsTrue(list.Contains(se2)); } - [TestCase] + [Test] public void GetFriendlyIdentifierForDisplay() { Uri providerEndpoint = new Uri("http://someprovider"); Identifier localId = "someuser"; @@ -136,7 +136,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", se.FriendlyIdentifierForDisplay); } - [TestCase] + [Test] public void IsTypeUriPresent() { IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority); Assert.IsTrue(se.IsTypeUriPresent(Protocol.Default.ClaimedIdentifierServiceTypeURI)); @@ -179,7 +179,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { se.IsExtensionSupported((IOpenIdMessageExtension)null); } - [TestCase] + [Test] public void IsExtensionSupported() { var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null); Assert.IsFalse(se.IsExtensionSupported<ClaimsRequest>()); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs index e4e7c8e..60a7318 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs @@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that immediate/setup modes are correctly detected. /// </summary> - [TestCase] + [Test] public void ImmediateVsSetupModes() { this.responseMessage = new NegativeAssertionResponse(this.protocol.Version, RPUri, this.protocol.Args.Mode.cancel); this.response = new NegativeAuthenticationResponse(this.responseMessage); @@ -58,14 +58,14 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.AreEqual(UserSuppliedIdentifier, (string)this.response.UserSuppliedIdentifier); } - [TestCase] + [Test] public void CommonProperties() { Assert.IsNull(this.response.Exception); Assert.IsNull(this.response.ClaimedIdentifier); Assert.IsNull(this.response.FriendlyIdentifierForDisplay); } - [TestCase] + [Test] public void CommonMethods() { Assert.IsNull(this.response.GetExtension<ClaimsRequest>()); Assert.IsNull(this.response.GetExtension(typeof(ClaimsRequest))); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs index 1b03596..86dd68c 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs @@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { base.SetUp(); } - [TestCase] + [Test] public void CreateRequestDumbMode() { var rp = this.CreateRelyingParty(true); Identifier id = this.GetMockIdentifier(ProtocolVersion.V20); @@ -36,7 +36,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { rp.SecuritySettings = null; } - [TestCase] + [Test] public void ExtensionFactories() { var rp = new OpenIdRelyingParty(null); var factories = rp.ExtensionFactories; @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.IsInstanceOf<StandardOpenIdExtensionFactory>(factories[0]); } - [TestCase] + [Test] public void CreateRequest() { var rp = this.CreateRelyingParty(); StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1))); @@ -54,7 +54,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.IsNotNull(req); } - [TestCase] + [Test] public void CreateRequests() { var rp = this.CreateRelyingParty(); StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1))); @@ -63,7 +63,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { Assert.AreEqual(1, requests.Count()); } - [TestCase] + [Test] public void CreateRequestsWithEndpointFilter() { var rp = this.CreateRelyingParty(); StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1))); @@ -86,7 +86,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { rp.CreateRequest(nonOpenId, RPRealmUri, RPUri); } - [TestCase] + [Test] public void CreateRequestsOnNonOpenID() { Uri nonOpenId = new Uri("http://www.microsoft.com/"); var rp = this.CreateRelyingParty(); @@ -99,7 +99,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that incoming positive assertions throw errors if they come from /// OPs that are not approved by <see cref="OpenIdRelyingParty.EndpointFilter"/>. /// </summary> - [TestCase] + [Test] public void AssertionWithEndpointFilter() { var coordinator = new OpenIdCoordinator( rp => { diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs index 2a4f4c0..3c91b52 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs @@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that the Text and Identifier properties interact correctly. /// </summary> - [TestCase] + [Test] public void IdentifierTextInteraction() { var box = new OpenIdTextBox(); Assert.AreEqual(string.Empty, box.Text); diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs index 5544bf9..bacd97d 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs @@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that the Status property returns the correct value. /// </summary> - [TestCase] + [Test] public void CtorAndProperties() { var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo); var ext = new ClaimsResponse(); @@ -43,7 +43,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies the Provider property. /// </summary> - [TestCase] + [Test] public void ProviderTest() { var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo); responseMessage.ProviderEndpoint = OPUri; diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs index fff5f75..f71f4be 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs @@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies good, positive assertions are accepted. /// </summary> - [TestCase] + [Test] public void Valid() { PositiveAssertionResponse assertion = this.GetPositiveAssertion(); ClaimsResponse extension = new ClaimsResponse(); @@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that discovery verification of a positive assertion can match a dual identifier. /// </summary> - [TestCase] + [Test] public void DualIdentifierMatchesInAssertionVerification() { PositiveAssertionResponse assertion = this.GetPositiveAssertion(true); ClaimsResponse extension = new ClaimsResponse(); @@ -97,7 +97,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { var authResponse = new PositiveAuthenticationResponse(assertion, rp); } - [TestCase] + [Test] public void GetCallbackArguments() { PositiveAssertionResponse assertion = this.GetPositiveAssertion(); var rp = CreateRelyingParty(); @@ -123,7 +123,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// <summary> /// Verifies that certain problematic claimed identifiers pass through to the RP response correctly. /// </summary> - [TestCase] + [Test] public void ProblematicClaimedId() { var providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version); string claimed_id = BaseMockUri + "a./b."; diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs index e8e0476..75e0607 100644 --- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs @@ -23,7 +23,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { this.settings = new RelyingPartySecuritySettings(); } - [TestCase] + [Test] public void Defaults() { Assert.IsFalse(this.settings.RejectUnsolicitedAssertions); Assert.IsFalse(this.settings.RequireSsl, "Default should be to not require SSL."); @@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that the <see cref="RelyingPartySecuritySettings.RequireSsl"/> property /// getter/setter are implemented correctly. /// </summary> - [TestCase] + [Test] public void RequireSsl() { this.settings.RequireSsl = true; Assert.IsTrue(this.settings.RequireSsl); @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that the <see cref="RelyingPartySecuritySettings.RequireDirectedIdentity"/> /// property getter/setter are implemented correctly. /// </summary> - [TestCase] + [Test] public void RequireDirectedIdentity() { this.settings.RequireDirectedIdentity = true; Assert.IsTrue(this.settings.RequireDirectedIdentity); @@ -57,7 +57,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty { /// Verifies that the <see cref="RelyingPartySecuritySettings.RequireAssociation"/> /// property getter/setter are implemented correctly. /// </summary> - [TestCase] + [Test] public void RequireAssociation() { this.settings.RequireAssociation = true; Assert.IsTrue(this.settings.RequireAssociation); diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs index a3b4b9e..0c63113 100644 --- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs @@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId { new UriIdentifier(this.badUri); } - [TestCase] + [Test] public void CtorGoodUri() { var uri = new UriIdentifier(this.goodUri); Assert.AreEqual(new Uri(this.goodUri), uri.Uri); @@ -54,14 +54,14 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.IsFalse(uri.IsDiscoverySecureEndToEnd); } - [TestCase] + [Test] public void CtorStringNoSchemeSecure() { var uri = new UriIdentifier("host/path", true); Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri); Assert.IsTrue(uri.IsDiscoverySecureEndToEnd); } - [TestCase] + [Test] public void CtorStringHttpsSchemeSecure() { var uri = new UriIdentifier("https://host/path", true); Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri); @@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId { new UriIdentifier("http://host/path", true); } - [TestCase] + [Test] public void CtorUriHttpsSchemeSecure() { var uri = new UriIdentifier(new Uri("https://host/path"), true); Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri); @@ -93,21 +93,21 @@ namespace DotNetOpenAuth.Test.OpenId { /// they should NOT be stripped from claimed identifiers. So the UriIdentifier /// class, which serves both identifier types, must not do the stripping. /// </remarks> - [TestCase] + [Test] public void DoesNotStripFragment() { Uri original = new Uri("http://a/b#c"); UriIdentifier identifier = new UriIdentifier(original); Assert.AreEqual(original.Fragment, identifier.Uri.Fragment); } - [TestCase] + [Test] public void IsValid() { Assert.IsTrue(UriIdentifier.IsValidUri(this.goodUri)); Assert.IsFalse(UriIdentifier.IsValidUri(this.badUri)); Assert.IsTrue(UriIdentifier.IsValidUri(this.relativeUri), "URL lacking http:// prefix should have worked anyway."); } - [TestCase] + [Test] public void TrimFragment() { Identifier noFragment = UriIdentifier.Parse("http://a/b"); Identifier fragment = UriIdentifier.Parse("http://a/b#c"); @@ -123,7 +123,7 @@ namespace DotNetOpenAuth.Test.OpenId { }); } - [TestCase] + [Test] public void ToStringTest() { Assert.AreEqual(this.goodUri, new UriIdentifier(this.goodUri).ToString()); TestAsFullAndPartialTrust(fullTrust => { @@ -140,7 +140,7 @@ namespace DotNetOpenAuth.Test.OpenId { }); } - [TestCase] + [Test] public void EqualsTest() { TestAsFullAndPartialTrust(fulltrust => { Assert.AreEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri)); @@ -163,7 +163,7 @@ namespace DotNetOpenAuth.Test.OpenId { }); } - [TestCase] + [Test] public void UnicodeTest() { string unicodeUrl = "http://nerdbank.org/opaffirmative/崎村.aspx"; Assert.IsTrue(UriIdentifier.IsValidUri(unicodeUrl)); @@ -173,7 +173,7 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.AreEqual(Uri.EscapeUriString(unicodeUrl), id.ToString()); } - [TestCase] + [Test] public void NormalizeCase() { // only the host name can be normalized in casing safely. Identifier id = "http://HOST:80/PaTH?KeY=VaLUE#fRag"; @@ -191,7 +191,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// which may end with a period. The default .NET Uri parser trims off /// trailing periods, which breaks OpenID unless special precautions are taken. /// </remarks> - [TestCase] + [Test] public void TrailingPeriodsNotTrimmed() { TestAsFullAndPartialTrust(fullTrust => { string claimedIdentifier = "https://me.yahoo.com/a/AsDf.#asdf"; @@ -228,7 +228,7 @@ namespace DotNetOpenAuth.Test.OpenId { }); } - [TestCase] + [Test] public void HttpSchemePrepended() { UriIdentifier id = new UriIdentifier("www.yahoo.com"); Assert.AreEqual("http://www.yahoo.com/", id.ToString()); @@ -242,7 +242,7 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.IsTrue(id.SchemeImplicitlyPrepended); } - [TestCase] + [Test] public void TryRequireSslAdjustsIdentifier() { Identifier secureId; // Try Parse and ctor without explicit scheme @@ -275,7 +275,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies that unicode hostnames are handled. /// </summary> - [TestCase] + [Test] public void UnicodeHostSupport() { var id = new UriIdentifier("http://server崎/村"); Assert.AreEqual("server崎", id.Uri.Host); @@ -284,7 +284,7 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies SimpleUri behavior /// </summary> - [TestCase] + [Test] public void SimpleUri() { Assert.AreEqual("http://abc/D./e.?Qq#Ff", new UriIdentifier.SimpleUri("HTTP://ABC/D./e.?Qq#Ff").ToString()); Assert.AreEqual("http://abc/D./e.?Qq", new UriIdentifier.SimpleUri("HTTP://ABC/D./e.?Qq").ToString()); diff --git a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs index 0614f60..e6871f8 100644 --- a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs @@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId { new XriIdentifier(this.badXri); } - [TestCase] + [Test] public void CtorGoodXri() { var xri = new XriIdentifier(this.goodXri); Assert.AreEqual(this.goodXri, xri.OriginalXri); @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.IsFalse(xri.IsDiscoverySecureEndToEnd); } - [TestCase] + [Test] public void CtorGoodXriSecure() { var xri = new XriIdentifier(this.goodXri, true); Assert.AreEqual(this.goodXri, xri.OriginalXri); @@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.IsTrue(xri.IsDiscoverySecureEndToEnd); } - [TestCase] + [Test] public void IsValid() { Assert.IsTrue(XriIdentifier.IsValidXri(this.goodXri)); Assert.IsFalse(XriIdentifier.IsValidXri(this.badXri)); @@ -62,25 +62,25 @@ namespace DotNetOpenAuth.Test.OpenId { /// <summary> /// Verifies 2.0 spec section 7.2#1 /// </summary> - [TestCase] + [Test] public void StripXriScheme() { var xri = new XriIdentifier("xri://" + this.goodXri); Assert.AreEqual("xri://" + this.goodXri, xri.OriginalXri); Assert.AreEqual(this.goodXri, xri.CanonicalXri); } - [TestCase] + [Test] public void TrimFragment() { Identifier xri = new XriIdentifier(this.goodXri); Assert.AreSame(xri, xri.TrimFragment()); } - [TestCase] + [Test] public void ToStringTest() { Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri).ToString()); } - [TestCase] + [Test] public void EqualsTest() { Assert.AreEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri)); Assert.AreNotEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri + "a")); diff --git a/src/DotNetOpenAuth.Test/Settings.StyleCop b/src/DotNetOpenAuth.Test/Settings.StyleCop index ae8997c..2e6f7e3 100644 --- a/src/DotNetOpenAuth.Test/Settings.StyleCop +++ b/src/DotNetOpenAuth.Test/Settings.StyleCop @@ -1,6 +1,6 @@ <StyleCopSettings Version="4.3"> <Analyzers> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.DocumentationRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules"> <Rules> <Rule Name="ElementsMustBeDocumented"> <RuleSettings> @@ -15,7 +15,7 @@ </Rules> <AnalyzerSettings /> </Analyzer> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.LayoutRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules"> <Rules> <Rule Name="SingleLineCommentMustBePrecededByBlankLine"> <RuleSettings> @@ -25,7 +25,7 @@ </Rules> <AnalyzerSettings /> </Analyzer> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.NamingRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules"> <AnalyzerSettings> <CollectionProperty Name="Hungarian"> <Value>op</Value> @@ -34,7 +34,7 @@ </CollectionProperty> </AnalyzerSettings> </Analyzer> - <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.MaintainabilityRules"> + <Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules"> <Rules> <Rule Name="FieldsMustBePrivate"> <RuleSettings> diff --git a/src/DotNetOpenAuth.Test/UriUtilTests.cs b/src/DotNetOpenAuth.Test/UriUtilTests.cs index 4aa7cd1..1e5451e 100644 --- a/src/DotNetOpenAuth.Test/UriUtilTests.cs +++ b/src/DotNetOpenAuth.Test/UriUtilTests.cs @@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Test { [TestFixture] public class UriUtilTests { - [TestCase] + [Test] public void QueryStringContainPrefixedParametersNull() { Assert.IsFalse(UriUtil.QueryStringContainPrefixedParameters(null, "prefix.")); } diff --git a/src/DotNetOpenAuth.Test/UtilTests.cs b/src/DotNetOpenAuth.Test/UtilTests.cs index 5f36b83..96fc254 100644 --- a/src/DotNetOpenAuth.Test/UtilTests.cs +++ b/src/DotNetOpenAuth.Test/UtilTests.cs @@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Test { /// <summary> /// Verifies ToStringDeferred generates a reasonable string for an empty, multi-line list. /// </summary> - [TestCase] + [Test] public void ToStringDeferredEmptyMultiLine() { Assert.AreEqual("[]", Util.ToStringDeferred(Enumerable.Empty<string>(), true).ToString()); } diff --git a/src/DotNetOpenAuth.bak b/src/DotNetOpenAuth.bak new file mode 100644 index 0000000..73e27f8 --- /dev/null +++ b/src/DotNetOpenAuth.bak @@ -0,0 +1,640 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20B5E173-C3C4-49F8-BD25-E69044075B4D}" + ProjectSection(SolutionItems) = preProject + ..\build.proj = ..\build.proj + ..\projecttemplates\DotNetOpenAuth Starter Kits.vscontent = ..\projecttemplates\DotNetOpenAuth Starter Kits.vscontent + ..\LICENSE.txt = ..\LICENSE.txt + ..\doc\README.Bin.html = ..\doc\README.Bin.html + ..\doc\README.html = ..\doc\README.html + ..\samples\README.html = ..\samples\README.html + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}" + ProjectSection(SolutionItems) = preProject + ..\doc\specs\draft-ietf-oauth-v2-23.txt = ..\doc\specs\draft-ietf-oauth-v2-23.txt + ..\doc\specs\draft-ietf-oauth-v2-bearer.htm = ..\doc\specs\draft-ietf-oauth-v2-bearer.htm + ..\doc\specs\draft-jones-json-web-token.htm = ..\doc\specs\draft-jones-json-web-token.htm + ..\doc\specs\ICAM_OpenID20Profile.pdf = ..\doc\specs\ICAM_OpenID20Profile.pdf + ..\doc\specs\OAuth Core 1.0.htm = ..\doc\specs\OAuth Core 1.0.htm + ..\doc\specs\OAuth Core 1.0a (Draft 3).htm = ..\doc\specs\OAuth Core 1.0a (Draft 3).htm + ..\doc\specs\OpenID OAuth Extension.htm = ..\doc\specs\OpenID OAuth Extension.htm + ..\doc\specs\openid-attribute-exchange-1_0.html = ..\doc\specs\openid-attribute-exchange-1_0.html + ..\doc\specs\openid-authentication-1_1.html = ..\doc\specs\openid-authentication-1_1.html + ..\doc\specs\openid-authentication-2_0.html = ..\doc\specs\openid-authentication-2_0.html + ..\doc\specs\openid-provider-authentication-policy-extension-1_0-02.html = ..\doc\specs\openid-provider-authentication-policy-extension-1_0-02.html + ..\doc\specs\openid-simple-registration-extension-1_0.html = ..\doc\specs\openid-simple-registration-extension-1_0.html + ..\doc\specs\openid_ui_extension_draft01.html = ..\doc\specs\openid_ui_extension_draft01.html + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B4C6F647-C046-4B54-BE12-7701C4119EE7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenID", "OpenID", "{034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth2", "OAuth2", "{1E2CBAA5-60A3-4AED-912E-541F5753CDC6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InfoCard", "InfoCard", "{8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{E9ED920D-1F83-48C0-9A4B-09CCE505FE6D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project Templates", "Project Templates", "{B9EB8729-4B54-4453-B089-FE6761BA3057}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Test", "DotNetOpenAuth.Test\DotNetOpenAuth.Test.csproj", "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.ApplicationBlock", "..\samples\DotNetOpenAuth.ApplicationBlock\DotNetOpenAuth.ApplicationBlock.csproj", "{AA78D112-D889-414B-A7D4-467B34C7B663}" +EndProject +Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "DotNetOpenAuth.TestWeb", "DotNetOpenAuth.TestWeb\", "{47A84EF7-68C3-4D47-926A-9CCEA6518531}" + ProjectSection(WebsiteProperties) = preProject + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + ProjectReferences = "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}|DotNetOpenAuth.Test.dll;{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{A288FCC8-6FCF-46DA-A45E-5F9281556361}|DotNetOpenAuth.OAuth.dll;{3896A32A-E876-4C23-B9B8-78E17D134CD3}|DotNetOpenAuth.OpenId.dll;{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}|DotNetOpenAuth.OAuth2.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}|DotNetOpenAuth.OAuth.Consumer.dll;{FED1923A-6D70-49B5-A37A-FB744FEC1C86}|DotNetOpenAuth.OAuth.ServiceProvider.dll;{99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}|DotNetOpenAuth.OAuth2.AuthorizationServer.dll;{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}|DotNetOpenAuth.OAuth2.Client.dll;{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}|DotNetOpenAuth.OAuth2.Client.UI.dll;{A1A3150A-7B0E-4A34-8E35-045296CD3C76}|DotNetOpenAuth.OAuth2.ResourceServer.dll;{F8284738-3B5D-4733-A511-38C23F4A763F}|DotNetOpenAuth.OpenId.Provider.dll;{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}|DotNetOpenAuth.OpenId.RelyingParty.dll;{9D0F8866-2131-4C2A-BC0E-16FEA5B50828}|DotNetOpenAuth.OpenId.Provider.UI.dll;{75E13AAE-7D51-4421-ABFD-3F3DC91F576E}|DotNetOpenAuth.OpenId.UI.dll;{1ED8D424-F8AB-4050-ACEB-F27F4F909484}|DotNetOpenAuth.OpenId.RelyingParty.UI.dll;{115217C5-22CD-415C-A292-0DD0238CDD89}|DotNetOpenAuth.OAuth.Common.dll;" + Debug.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + Debug.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.Updateable = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + Release.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.Updateable = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.Debug = "False" + VWDPort = "5073" + DefaultWebSiteLanguage = "Visual C#" + StartServerOnDebug = "false" + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderWebForms", "..\samples\OpenIdProviderWebForms\OpenIdProviderWebForms.csproj", "{2A59DE0A-B76A-4B42-9A33-04D34548353D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderMvc", "..\samples\OpenIdProviderMvc\OpenIdProviderMvc.csproj", "{AEA29D4D-396F-47F6-BC81-B58D4B855245}" +EndProject +Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InfoCardRelyingParty", "..\samples\InfoCardRelyingParty\", "{6EB90284-BD15-461C-BBF2-131CF55F7C8B}" + ProjectSection(WebsiteProperties) = preProject + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + ProjectReferences = "{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;" + Debug.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + Debug.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + Release.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.Debug = "False" + VWDPort = "59719" + DefaultWebSiteLanguage = "Visual Basic" + StartServerOnDebug = "false" + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdRelyingPartyMvc", "..\samples\OpenIdRelyingPartyMvc\OpenIdRelyingPartyMvc.csproj", "{07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdRelyingPartyWebForms", "..\samples\OpenIdRelyingPartyWebForms\OpenIdRelyingPartyWebForms.csproj", "{1E8AEA89-BF69-47A1-B290-E8B0FE588700}" +EndProject +Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAsp", "..\samples\OpenIdRelyingPartyClassicAsp\", "{BBACD972-014D-478F-9B07-56B9E1D4CC73}" + ProjectSection(WebsiteProperties) = preProject + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + Debug.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + Debug.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + Release.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.Debug = "False" + VWDPort = "10318" + StartServerOnDebug = "false" + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumerWpf", "..\samples\OAuthConsumerWpf\OAuthConsumerWpf.csproj", "{6EC36418-DBC5-4AD1-A402-413604AA7A08}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdOfflineProvider", "..\samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj", "{5C65603B-235F-47E6-B536-06385C60DE7F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFormsRelyingParty", "..\projecttemplates\WebFormsRelyingParty\WebFormsRelyingParty.csproj", "{A78F8FC6-7B03-4230-BE41-761E400D6810}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelyingPartyLogic", "..\projecttemplates\RelyingPartyLogic\RelyingPartyLogic.csproj", "{17932639-1F50-48AF-B0A5-E2BF832F82CC}" + ProjectSection(ProjectDependencies) = postProject + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} + EndProjectSection +EndProject +Project("{C8D11400-126E-41CD-887F-60BD40844F9E}") = "RelyingPartyDatabase", "..\projecttemplates\RelyingPartyDatabase\RelyingPartyDatabase.dbproj", "{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcRelyingParty", "..\projecttemplates\MvcRelyingParty\MvcRelyingParty.csproj", "{152B7BAB-E884-4A59-8067-440971A682B3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoRelyingParty", "..\samples\OpenIdWebRingSsoRelyingParty\OpenIdWebRingSsoRelyingParty.csproj", "{B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoProvider", "..\samples\OpenIdWebRingSsoProvider\OpenIdWebRingSsoProvider.csproj", "{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "OpenIdRelyingPartyWebFormsVB", "..\samples\OpenIdRelyingPartyWebFormsVB\OpenIdRelyingPartyWebFormsVB.vbproj", "{F289B925-4307-4BEC-B411-885CE70E3379}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthClient", "..\samples\OAuthClient\OAuthClient.csproj", "{9529606E-AF76-4387-BFB7-3D10A5B399AA}" + ProjectSection(ProjectDependencies) = postProject + {E135F455-0669-49F8-9207-07FCA8C8FC79} = {E135F455-0669-49F8-9207-07FCA8C8FC79} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthResourceServer", "..\samples\OAuthResourceServer\OAuthResourceServer.csproj", "{E135F455-0669-49F8-9207-07FCA8C8FC79}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthAuthorizationServer", "..\samples\OAuthAuthorizationServer\OAuthAuthorizationServer.csproj", "{C78E8235-1D46-43EB-A912-80B522C4E9AE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Core", "DotNetOpenAuth.Core\DotNetOpenAuth.Core.csproj", "{60426312-6AE5-4835-8667-37EDEA670222}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId", "DotNetOpenAuth.OpenId\DotNetOpenAuth.OpenId.csproj", "{3896A32A-E876-4C23-B9B8-78E17D134CD3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth", "DotNetOpenAuth.OAuth\DotNetOpenAuth.OAuth.csproj", "{A288FCC8-6FCF-46DA-A45E-5F9281556361}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.InfoCard", "DotNetOpenAuth.InfoCard\DotNetOpenAuth.InfoCard.csproj", "{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2", "DotNetOpenAuth.OAuth2\DotNetOpenAuth.OAuth2.csproj", "{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId.Provider", "DotNetOpenAuth.OpenId.Provider\DotNetOpenAuth.OpenId.Provider.csproj", "{F8284738-3B5D-4733-A511-38C23F4A763F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId.RelyingParty", "DotNetOpenAuth.OpenId.RelyingParty\DotNetOpenAuth.OpenId.RelyingParty.csproj", "{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Math", "Mono.Math\Mono.Math.csproj", "{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Org.Mentalis.Security.Cryptography", "Org.Mentalis.Security.Cryptography\Org.Mentalis.Security.Cryptography.csproj", "{26DC877F-5987-48DD-9DDB-E62F2DE0E150}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId.RelyingParty.UI", "DotNetOpenAuth.OpenId.RelyingParty.UI\DotNetOpenAuth.OpenId.RelyingParty.UI.csproj", "{1ED8D424-F8AB-4050-ACEB-F27F4F909484}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId.Provider.UI", "DotNetOpenAuth.OpenId.Provider.UI\DotNetOpenAuth.OpenId.Provider.UI.csproj", "{9D0F8866-2131-4C2A-BC0E-16FEA5B50828}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenId.UI", "DotNetOpenAuth.OpenId.UI\DotNetOpenAuth.OpenId.UI.csproj", "{75E13AAE-7D51-4421-ABFD-3F3DC91F576E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Core.UI", "DotNetOpenAuth.Core.UI\DotNetOpenAuth.Core.UI.csproj", "{173E7B8D-E751-46E2-A133-F72297C0D2F4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Product", "Product", "{8D4236F7-C49B-49D3-BA71-6B86C9514BDE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenID", "OpenID", "{C7EF1823-3AA7-477E-8476-28929F5C05D2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth", "OAuth", "{9AF74F53-10F5-49A2-B747-87B97CD559D3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InfoCard", "InfoCard", "{529B4262-6B5A-4EF9-BD3B-1D29A2597B67}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.InfoCard.UI", "DotNetOpenAuth.InfoCard.UI\DotNetOpenAuth.InfoCard.UI.csproj", "{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth2", "OAuth2", "{238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth.Consumer", "DotNetOpenAuth.OAuth.Consumer\DotNetOpenAuth.OAuth.Consumer.csproj", "{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth.ServiceProvider", "DotNetOpenAuth.OAuth.ServiceProvider\DotNetOpenAuth.OAuth.ServiceProvider.csproj", "{FED1923A-6D70-49B5-A37A-FB744FEC1C86}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2.AuthorizationServer", "DotNetOpenAuth.OAuth2.AuthorizationServer\DotNetOpenAuth.OAuth2.AuthorizationServer.csproj", "{99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2.Client", "DotNetOpenAuth.OAuth2.Client\DotNetOpenAuth.OAuth2.Client.csproj", "{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2.ResourceServer", "DotNetOpenAuth.OAuth2.ResourceServer\DotNetOpenAuth.OAuth2.ResourceServer.csproj", "{A1A3150A-7B0E-4A34-8E35-045296CD3C76}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth2.Client.UI", "DotNetOpenAuth.OAuth2.Client.UI\DotNetOpenAuth.OAuth2.Client.UI.csproj", "{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Combinations", "Combinations", "{57A7DD35-666C-4FA3-9A1B-38961E50CA27}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenIdInfoCard.UI", "DotNetOpenAuth.OpenIdInfoCard.UI\DotNetOpenAuth.OpenIdInfoCard.UI.csproj", "{3A8347E8-59A5-4092-8842-95C75D7D2F36}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth1", "OAuth1", "{2DA24D4F-6918-43CF-973C-BC9D818F8E90}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumer", "..\samples\OAuthConsumer\OAuthConsumer.csproj", "{2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthServiceProvider", "..\samples\OAuthServiceProvider\OAuthServiceProvider.csproj", "{CAA2408C-6918-4902-A512-58BCD62216C3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenIdOAuth", "DotNetOpenAuth.OpenIdOAuth\DotNetOpenAuth.OpenIdOAuth.csproj", "{4BFAA336-5DF3-4F27-82D3-06D13240E8AB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.AspNet", "DotNetOpenAuth.AspNet\DotNetOpenAuth.AspNet.csproj", "{51835086-9611-4C53-819B-F2D5C9320873}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.AspNet.Test", "DotNetOpenAuth.AspNet.Test\DotNetOpenAuth.AspNet.Test.csproj", "{C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth.Common", "DotNetOpenAuth.OAuth.Common\DotNetOpenAuth.OAuth.Common.csproj", "{115217C5-22CD-415C-A292-0DD0238CDD89}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + CodeAnalysis|Any CPU = CodeAnalysis|Any CPU + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + ReleaseNoUI|Any CPU = ReleaseNoUI|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.Release|Any CPU.Build.0 = Release|Any CPU + {4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.Release|Any CPU.Build.0 = Release|Any CPU + {AA78D112-D889-414B-A7D4-467B34C7B663}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.Release|Any CPU.Build.0 = Debug|Any CPU + {47A84EF7-68C3-4D47-926A-9CCEA6518531}.ReleaseNoUI|Any CPU.ActiveCfg = Debug|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.Release|Any CPU.Build.0 = Release|Any CPU + {2A59DE0A-B76A-4B42-9A33-04D34548353D}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.Release|Any CPU.Build.0 = Release|Any CPU + {AEA29D4D-396F-47F6-BC81-B58D4B855245}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.Release|Any CPU.Build.0 = Debug|Any CPU + {6EB90284-BD15-461C-BBF2-131CF55F7C8B}.ReleaseNoUI|Any CPU.ActiveCfg = Debug|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.Release|Any CPU.Build.0 = Release|Any CPU + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.Release|Any CPU.Build.0 = Release|Any CPU + {1E8AEA89-BF69-47A1-B290-E8B0FE588700}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Release|Any CPU.Build.0 = Debug|Any CPU + {BBACD972-014D-478F-9B07-56B9E1D4CC73}.ReleaseNoUI|Any CPU.ActiveCfg = Debug|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.Release|Any CPU.Build.0 = Release|Any CPU + {6EC36418-DBC5-4AD1-A402-413604AA7A08}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.Release|Any CPU.Build.0 = Release|Any CPU + {5C65603B-235F-47E6-B536-06385C60DE7F}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.Release|Any CPU.Build.0 = Release|Any CPU + {A78F8FC6-7B03-4230-BE41-761E400D6810}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.Release|Any CPU.Build.0 = Release|Any CPU + {17932639-1F50-48AF-B0A5-E2BF832F82CC}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.CodeAnalysis|Any CPU.Deploy.0 = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Build.0 = Release|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.Release|Any CPU.Build.0 = Release|Any CPU + {152B7BAB-E884-4A59-8067-440971A682B3}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Release|Any CPU.Build.0 = Release|Any CPU + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.Build.0 = Release|Any CPU + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.Build.0 = Release|Any CPU + {F289B925-4307-4BEC-B411-885CE70E3379}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Release|Any CPU.Build.0 = Release|Any CPU + {9529606E-AF76-4387-BFB7-3D10A5B399AA}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.Release|Any CPU.Build.0 = Release|Any CPU + {E135F455-0669-49F8-9207-07FCA8C8FC79}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.Release|Any CPU.Build.0 = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {C78E8235-1D46-43EB-A912-80B522C4E9AE}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.Release|Any CPU.Build.0 = Release|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {60426312-6AE5-4835-8667-37EDEA670222}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.Release|Any CPU.Build.0 = Release|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {3896A32A-E876-4C23-B9B8-78E17D134CD3}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.Release|Any CPU.Build.0 = Release|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {A288FCC8-6FCF-46DA-A45E-5F9281556361}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.Release|Any CPU.Build.0 = Release|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.Release|Any CPU.Build.0 = Release|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.Release|Any CPU.Build.0 = Release|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {F8284738-3B5D-4733-A511-38C23F4A763F}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.Release|Any CPU.Build.0 = Release|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.Release|Any CPU.Build.0 = Release|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.Debug|Any CPU.Build.0 = Debug|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.Release|Any CPU.ActiveCfg = Release|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.Release|Any CPU.Build.0 = Release|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {26DC877F-5987-48DD-9DDB-E62F2DE0E150}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.Release|Any CPU.Build.0 = Release|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {1ED8D424-F8AB-4050-ACEB-F27F4F909484}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.Release|Any CPU.Build.0 = Release|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.Release|Any CPU.Build.0 = Release|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.Release|Any CPU.Build.0 = Release|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {173E7B8D-E751-46E2-A133-F72297C0D2F4}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.Release|Any CPU.Build.0 = Release|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.Release|Any CPU.Build.0 = Release|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.Release|Any CPU.Build.0 = Release|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {FED1923A-6D70-49B5-A37A-FB744FEC1C86}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.Release|Any CPU.Build.0 = Release|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.Release|Any CPU.Build.0 = Release|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.Release|Any CPU.Build.0 = Release|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {A1A3150A-7B0E-4A34-8E35-045296CD3C76}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.Release|Any CPU.Build.0 = Release|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.Release|Any CPU.Build.0 = Release|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {3A8347E8-59A5-4092-8842-95C75D7D2F36}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.Release|Any CPU.Build.0 = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.Release|Any CPU.Build.0 = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {CAA2408C-6918-4902-A512-58BCD62216C3}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Release|Any CPU.Build.0 = Release|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.Debug|Any CPU.Build.0 = Debug|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.Release|Any CPU.ActiveCfg = Release|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.Release|Any CPU.Build.0 = Release|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {115217C5-22CD-415C-A292-0DD0238CDD89}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CD57219F-24F4-4136-8741-6063D0D7A031} = {20B5E173-C3C4-49F8-BD25-E69044075B4D} + {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {AA78D112-D889-414B-A7D4-467B34C7B663} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {2DA24D4F-6918-43CF-973C-BC9D818F8E90} = {B4C6F647-C046-4B54-BE12-7701C4119EE7} + {2A59DE0A-B76A-4B42-9A33-04D34548353D} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {AEA29D4D-396F-47F6-BC81-B58D4B855245} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {07B193F1-68AD-4E9C-98AF-BEFB5E9403CB} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {1E8AEA89-BF69-47A1-B290-E8B0FE588700} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {BBACD972-014D-478F-9B07-56B9E1D4CC73} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {F289B925-4307-4BEC-B411-885CE70E3379} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} + {6EC36418-DBC5-4AD1-A402-413604AA7A08} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} + {9529606E-AF76-4387-BFB7-3D10A5B399AA} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} + {E135F455-0669-49F8-9207-07FCA8C8FC79} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} + {C78E8235-1D46-43EB-A912-80B522C4E9AE} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6} + {6EB90284-BD15-461C-BBF2-131CF55F7C8B} = {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277} + {5C65603B-235F-47E6-B536-06385C60DE7F} = {E9ED920D-1F83-48C0-9A4B-09CCE505FE6D} + {A78F8FC6-7B03-4230-BE41-761E400D6810} = {B9EB8729-4B54-4453-B089-FE6761BA3057} + {17932639-1F50-48AF-B0A5-E2BF832F82CC} = {B9EB8729-4B54-4453-B089-FE6761BA3057} + {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {B9EB8729-4B54-4453-B089-FE6761BA3057} + {152B7BAB-E884-4A59-8067-440971A682B3} = {B9EB8729-4B54-4453-B089-FE6761BA3057} + {C7EF1823-3AA7-477E-8476-28929F5C05D2} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {9AF74F53-10F5-49A2-B747-87B97CD559D3} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {529B4262-6B5A-4EF9-BD3B-1D29A2597B67} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {173E7B8D-E751-46E2-A133-F72297C0D2F4} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {60426312-6AE5-4835-8667-37EDEA670222} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {57A7DD35-666C-4FA3-9A1B-38961E50CA27} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {115217C5-22CD-415C-A292-0DD0238CDD89} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {51835086-9611-4C53-819B-F2D5C9320873} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} + {F8284738-3B5D-4733-A511-38C23F4A763F} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {F458AB60-BA1C-43D9-8CEF-EC01B50BE87B} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {F4CD3C04-6037-4946-B7A5-34BFC96A75D2} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {26DC877F-5987-48DD-9DDB-E62F2DE0E150} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {1ED8D424-F8AB-4050-ACEB-F27F4F909484} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {9D0F8866-2131-4C2A-BC0E-16FEA5B50828} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {75E13AAE-7D51-4421-ABFD-3F3DC91F576E} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {3896A32A-E876-4C23-B9B8-78E17D134CD3} = {C7EF1823-3AA7-477E-8476-28929F5C05D2} + {A288FCC8-6FCF-46DA-A45E-5F9281556361} = {9AF74F53-10F5-49A2-B747-87B97CD559D3} + {B202E40D-4663-4A2B-ACDA-865F88FF7CAA} = {9AF74F53-10F5-49A2-B747-87B97CD559D3} + {FED1923A-6D70-49B5-A37A-FB744FEC1C86} = {9AF74F53-10F5-49A2-B747-87B97CD559D3} + {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C} = {529B4262-6B5A-4EF9-BD3B-1D29A2597B67} + {E040EB58-B4D2-457B-A023-AE6EF3BD34DE} = {529B4262-6B5A-4EF9-BD3B-1D29A2597B67} + {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} + {99BB7543-EA16-43EE-A7BC-D7A25A3B22F6} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} + {CDEDD439-7F35-4E6E-8605-4E70BDC4CC99} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} + {A1A3150A-7B0E-4A34-8E35-045296CD3C76} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} + {ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} + {3A8347E8-59A5-4092-8842-95C75D7D2F36} = {57A7DD35-666C-4FA3-9A1B-38961E50CA27} + {4BFAA336-5DF3-4F27-82D3-06D13240E8AB} = {57A7DD35-666C-4FA3-9A1B-38961E50CA27} + {2BF1FFD1-607E-40D0-8AB5-EDA677EF932D} = {2DA24D4F-6918-43CF-973C-BC9D818F8E90} + {CAA2408C-6918-4902-A512-58BCD62216C3} = {2DA24D4F-6918-43CF-973C-BC9D818F8E90} + EndGlobalSection +EndGlobal diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln index c9fd6dd..45d6fd2 100644 --- a/src/DotNetOpenAuth.sln +++ b/src/DotNetOpenAuth.sln @@ -101,6 +101,48 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "DotNetOpenAuth.TestWeb", "D TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" VWDPort = "5073" EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.Updateable = "false" + Debug.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + DefaultWebSiteLanguage = "Visual C#" + ProjectReferences = "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}|DotNetOpenAuth.Test.dll;{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{A288FCC8-6FCF-46DA-A45E-5F9281556361}|DotNetOpenAuth.OAuth.dll;{3896A32A-E876-4C23-B9B8-78E17D134CD3}|DotNetOpenAuth.OpenId.dll;{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}|DotNetOpenAuth.OAuth2.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}|DotNetOpenAuth.OAuth.Consumer.dll;{FED1923A-6D70-49B5-A37A-FB744FEC1C86}|DotNetOpenAuth.OAuth.ServiceProvider.dll;{99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}|DotNetOpenAuth.OAuth2.AuthorizationServer.dll;{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}|DotNetOpenAuth.OAuth2.Client.dll;{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}|DotNetOpenAuth.OAuth2.Client.UI.dll;{A1A3150A-7B0E-4A34-8E35-045296CD3C76}|DotNetOpenAuth.OAuth2.ResourceServer.dll;{F8284738-3B5D-4733-A511-38C23F4A763F}|DotNetOpenAuth.OpenId.Provider.dll;{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}|DotNetOpenAuth.OpenId.RelyingParty.dll;{9D0F8866-2131-4C2A-BC0E-16FEA5B50828}|DotNetOpenAuth.OpenId.Provider.UI.dll;{75E13AAE-7D51-4421-ABFD-3F3DC91F576E}|DotNetOpenAuth.OpenId.UI.dll;{1ED8D424-F8AB-4050-ACEB-F27F4F909484}|DotNetOpenAuth.OpenId.RelyingParty.UI.dll;{115217C5-22CD-415C-A292-0DD0238CDD89}|DotNetOpenAuth.OAuth.Common.dll;" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.Updateable = "false" + Release.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "5073" + EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Debug.AspNetCompiler.Updateable = "false" + Debug.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + DefaultWebSiteLanguage = "Visual C#" + ProjectReferences = "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}|DotNetOpenAuth.Test.dll;{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{A288FCC8-6FCF-46DA-A45E-5F9281556361}|DotNetOpenAuth.OAuth.dll;{3896A32A-E876-4C23-B9B8-78E17D134CD3}|DotNetOpenAuth.OpenId.dll;{56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}|DotNetOpenAuth.OAuth2.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;{B202E40D-4663-4A2B-ACDA-865F88FF7CAA}|DotNetOpenAuth.OAuth.Consumer.dll;{FED1923A-6D70-49B5-A37A-FB744FEC1C86}|DotNetOpenAuth.OAuth.ServiceProvider.dll;{99BB7543-EA16-43EE-A7BC-D7A25A3B22F6}|DotNetOpenAuth.OAuth2.AuthorizationServer.dll;{CDEDD439-7F35-4E6E-8605-4E70BDC4CC99}|DotNetOpenAuth.OAuth2.Client.dll;{ADC2CC8C-541E-4F86-ACB1-DD504A36FA4B}|DotNetOpenAuth.OAuth2.Client.UI.dll;{A1A3150A-7B0E-4A34-8E35-045296CD3C76}|DotNetOpenAuth.OAuth2.ResourceServer.dll;{F8284738-3B5D-4733-A511-38C23F4A763F}|DotNetOpenAuth.OpenId.Provider.dll;{F458AB60-BA1C-43D9-8CEF-EC01B50BE87B}|DotNetOpenAuth.OpenId.RelyingParty.dll;{9D0F8866-2131-4C2A-BC0E-16FEA5B50828}|DotNetOpenAuth.OpenId.Provider.UI.dll;{75E13AAE-7D51-4421-ABFD-3F3DC91F576E}|DotNetOpenAuth.OpenId.UI.dll;{1ED8D424-F8AB-4050-ACEB-F27F4F909484}|DotNetOpenAuth.OpenId.RelyingParty.UI.dll;{115217C5-22CD-415C-A292-0DD0238CDD89}|DotNetOpenAuth.OAuth.Common.dll;" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\DotNetOpenAuth.TestWeb\" + Release.AspNetCompiler.Updateable = "false" + Release.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "5073" + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderWebForms", "..\samples\OpenIdProviderWebForms\OpenIdProviderWebForms.csproj", "{2A59DE0A-B76A-4B42-9A33-04D34548353D}" EndProject @@ -149,6 +191,48 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InfoCardRelyingParty", "..\ TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" VWDPort = "59719" EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + DefaultWebSiteLanguage = "Visual Basic" + ProjectReferences = "{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "59719" + EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + DefaultWebSiteLanguage = "Visual Basic" + ProjectReferences = "{408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C}|DotNetOpenAuth.InfoCard.dll;{60426312-6AE5-4835-8667-37EDEA670222}|DotNetOpenAuth.Core.dll;{173E7B8D-E751-46E2-A133-F72297C0D2F4}|DotNetOpenAuth.Core.UI.dll;{26DC877F-5987-48DD-9DDB-E62F2DE0E150}|Org.Mentalis.Security.Cryptography.dll;{F4CD3C04-6037-4946-B7A5-34BFC96A75D2}|Mono.Math.dll;{E040EB58-B4D2-457B-A023-AE6EF3BD34DE}|DotNetOpenAuth.InfoCard.UI.dll;" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\InfoCardRelyingParty\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "59719" + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdRelyingPartyMvc", "..\samples\OpenIdRelyingPartyMvc\OpenIdRelyingPartyMvc.csproj", "{07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}" EndProject @@ -193,6 +277,44 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAs TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" VWDPort = "10318" EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "10318" + EndProjectSection + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + Release.AspNetCompiler.Debug = "False" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp" + StartServerOnDebug = "false" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5" + VWDPort = "10318" + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumerWpf", "..\samples\OAuthConsumerWpf\OAuthConsumerWpf.csproj", "{6EC36418-DBC5-4AD1-A402-413604AA7A08}" EndProject @@ -272,6 +394,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthServiceProvider", "..\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OpenIdOAuth", "DotNetOpenAuth.OpenIdOAuth\DotNetOpenAuth.OpenIdOAuth.csproj", "{4BFAA336-5DF3-4F27-82D3-06D13240E8AB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.AspNet", "DotNetOpenAuth.AspNet\DotNetOpenAuth.AspNet.csproj", "{51835086-9611-4C53-819B-F2D5C9320873}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.AspNet.Test", "DotNetOpenAuth.AspNet.Test\DotNetOpenAuth.AspNet.Test.csproj", "{C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.OAuth.Common", "DotNetOpenAuth.OAuth.Common\DotNetOpenAuth.OAuth.Common.csproj", "{115217C5-22CD-415C-A292-0DD0238CDD89}" EndProject Global @@ -430,6 +556,14 @@ Global {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {4BFAA336-5DF3-4F27-82D3-06D13240E8AB}.Release|Any CPU.Build.0 = Release|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51835086-9611-4C53-819B-F2D5C9320873}.Release|Any CPU.Build.0 = Release|Any CPU {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.CodeAnalysis|Any CPU.ActiveCfg = CodeAnalysis|Any CPU {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.CodeAnalysis|Any CPU.Build.0 = CodeAnalysis|Any CPU {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -574,6 +708,14 @@ Global {BBACD972-014D-478F-9B07-56B9E1D4CC73}.ReleaseNoUI|Any CPU.Build.0 = Debug|Any CPU {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Release|Any CPU.ActiveCfg = Debug|Any CPU {BBACD972-014D-478F-9B07-56B9E1D4CC73}.Release|Any CPU.Build.0 = Debug|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.ReleaseNoUI|Any CPU.ActiveCfg = Release|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.ReleaseNoUI|Any CPU.Build.0 = Release|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C23B217B-4D35-4A72-A1F7-FAEB4F39CB91}.Release|Any CPU.Build.0 = Release|Any CPU {C78E8235-1D46-43EB-A912-80B522C4E9AE}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU {C78E8235-1D46-43EB-A912-80B522C4E9AE}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU {C78E8235-1D46-43EB-A912-80B522C4E9AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -679,6 +821,7 @@ Global {3A8347E8-59A5-4092-8842-95C75D7D2F36} = {57A7DD35-666C-4FA3-9A1B-38961E50CA27} {408D10B8-34BA-4CBD-B7AA-FEB1907ABA4C} = {529B4262-6B5A-4EF9-BD3B-1D29A2597B67} {4BFAA336-5DF3-4F27-82D3-06D13240E8AB} = {57A7DD35-666C-4FA3-9A1B-38961E50CA27} + {51835086-9611-4C53-819B-F2D5C9320873} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} {529B4262-6B5A-4EF9-BD3B-1D29A2597B67} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} {56459A6C-6BA2-4BAC-A9C0-27E3BD961FA6} = {238B6BA8-AD99-43C9-B8E2-D2BCE6CE04DC} {57A7DD35-666C-4FA3-9A1B-38961E50CA27} = {8D4236F7-C49B-49D3-BA71-6B86C9514BDE} diff --git a/src/DotNetOpenAuth.sln.DotSettings b/src/DotNetOpenAuth.sln.DotSettings new file mode 100644 index 0000000..f4e5570 --- /dev/null +++ b/src/DotNetOpenAuth.sln.DotSettings @@ -0,0 +1,42 @@ +<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/AutoCompleteBasicCompletion/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeEditing/Intellisense/LookupWindow/ShowSummary/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeEditing/Localization/CSharpLocalizationOptions/DontAnalyseVerbatimStrings/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER/@EntryValue">False</s:Boolean> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">NEXT_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FIXED_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOR_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_FOREACH_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_IFELSE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_USING_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/FORCE_WHILE_BRACES_STYLE/@EntryValue">ALWAYS_ADD</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INITIALIZER_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INVOCABLE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64> + <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue">1</s:Int64> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/OTHER_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">False</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/REDUNDANT_THIS_QUALIFIER_STYLE/@EntryValue">ALWAYS_USE</s:String> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/STICK_COMMENT/@EntryValue">False</s:Boolean> + <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/TYPE_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String> + <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/JavaScriptFormatOther/ALIGN_MULTIPLE_DECLARATION/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/AddImportsToDeepestScope/@EntryValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean> + <s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">//-----------------------------------------------------------------------
 +// <copyright file="$FILENAME$" company="Outercurve Foundation">
 +// Copyright (c) Outercurve Foundation. All rights reserved.
 +// </copyright>
 +//-----------------------------------------------------------------------
 +</s:String> + <s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean> + <s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=WrapInRegion/@EntryIndexedValue">True</s:String> + <s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=XmlDocumentation/@EntryIndexedValue">True</s:String> + <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String> + <s:String x:Key="/Default/CodeStyle/Naming/VBNaming/EventHandlerPatternLong/@EntryValue">$object$_On$event$</s:String></wpf:ResourceDictionary>
\ No newline at end of file diff --git a/src/version.txt b/src/version.txt index fcdb2e1..4a3f2c3 100644 --- a/src/version.txt +++ b/src/version.txt @@ -1 +1,3 @@ 4.0.0 + +0.23.0-draft |