summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore2
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs5
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs9
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs17
-rw-r--r--src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs9
-rw-r--r--src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs20
-rw-r--r--src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs53
-rw-r--r--src/DotNetOpenAuth.AspNet/UriHelper.cs3
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.proj15
-rw-r--r--src/DotNetOpenAuth/Properties/AssemblyInfo.cs55
-rw-r--r--src/DotNetOpenAuth/Stub.csproj35
11 files changed, 196 insertions, 27 deletions
diff --git a/src/.gitignore b/src/.gitignore
index ad0e465..420748a 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -1,6 +1,6 @@
Backup*
_UpgradeReport_Files
-UpgradeLog.XML
+UpgradeLog*.XML
PrecompiledWeb
_ReSharper.*
*.suo
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs
index a58549a..2ec988b 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/AuthenticationOnlyCookieOAuthTokenManager.cs
@@ -86,7 +86,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
/// <param name="requestToken">The request token.</param>
/// <param name="requestTokenSecret">The request token secret.</param>
public void StoreRequestToken(string requestToken, string requestTokenSecret) {
- var cookie = new HttpCookie(TokenCookieKey);
+ var cookie = new HttpCookie(TokenCookieKey) {
+ HttpOnly = true
+ };
+
if (FormsAuthentication.RequireSSL) {
cookie.Secure = true;
}
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
index ac8186d..26bc88d 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/LinkedInClient.cs
@@ -89,7 +89,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
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)";
+ const string ProfileRequestUrl = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,industry,summary)";
string accessToken = response.AccessToken;
@@ -99,7 +99,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
try {
using (WebResponse profileResponse = request.GetResponse()) {
using (Stream responseStream = profileResponse.GetResponseStream()) {
- XDocument document = XDocument.Load(responseStream);
+ XDocument document = LoadXDocumentFromStream(responseStream);
string userId = document.Root.Element("id").Value;
string firstName = document.Root.Element("first-name").Value;
@@ -117,11 +117,12 @@ namespace DotNetOpenAuth.AspNet.Clients {
isSuccessful: true, provider: this.ProviderName, providerUserId: userId, userName: userName, extraData: extraData);
}
}
- } catch (Exception exception) {
+ }
+ catch (Exception exception) {
return new AuthenticationResult(exception);
}
}
#endregion
}
-}
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
index 3f9e85a..9a9f40d 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/OAuthClient.cs
@@ -8,7 +8,10 @@ namespace DotNetOpenAuth.AspNet.Clients {
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
+ using System.IO;
using System.Web;
+ using System.Xml;
+ using System.Xml.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
@@ -154,6 +157,20 @@ namespace DotNetOpenAuth.AspNet.Clients {
#region Methods
/// <summary>
+ /// Helper method to load an XDocument from an input stream.
+ /// </summary>
+ /// <param name="stream">The input stream from which to load the document.</param>
+ /// <returns>The XML document.</returns>
+ internal static XDocument LoadXDocumentFromStream(Stream stream) {
+ const int MaxChars = 0x10000; // 64k
+
+ XmlReaderSettings settings = new XmlReaderSettings() {
+ MaxCharactersInDocument = MaxChars
+ };
+ return XDocument.Load(XmlReader.Create(stream, settings));
+ }
+
+ /// <summary>
/// Check if authentication succeeded after user is redirected back from the service provider.
/// </summary>
/// <param name="response">
diff --git a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
index 96c1701..886917a 100644
--- a/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
+++ b/src/DotNetOpenAuth.AspNet/Clients/OAuth/TwitterClient.cs
@@ -92,7 +92,7 @@ namespace DotNetOpenAuth.AspNet.Clients {
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="
+ var profileRequestUrl = new Uri("https://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);
@@ -102,14 +102,15 @@ namespace DotNetOpenAuth.AspNet.Clients {
try {
using (WebResponse profileResponse = request.GetResponse()) {
using (Stream responseStream = profileResponse.GetResponseStream()) {
- XDocument document = XDocument.Load(responseStream);
+ XDocument document = LoadXDocumentFromStream(responseStream);
extraData.AddDataIfNotEmpty(document, "name");
extraData.AddDataIfNotEmpty(document, "location");
extraData.AddDataIfNotEmpty(document, "description");
extraData.AddDataIfNotEmpty(document, "url");
}
}
- } catch (Exception) {
+ }
+ 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.
@@ -121,4 +122,4 @@ namespace DotNetOpenAuth.AspNet.Clients {
#endregion
}
-}
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs b/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs
index f5c8547..eb2020b 100644
--- a/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs
+++ b/src/DotNetOpenAuth.AspNet/MachineKeyUtil.cs
@@ -10,8 +10,10 @@ namespace DotNetOpenAuth.AspNet {
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
+ using System.Reflection;
using System.Security.Cryptography;
using System.Text;
+ using System.Web;
using System.Web.Security;
/// <summary>
@@ -84,12 +86,20 @@ namespace DotNetOpenAuth.AspNet {
/// </summary>
/// <returns>The machine key implementation</returns>
private static IMachineKey GetMachineKeyImpl() {
- ProtectUnprotect protectThunk = (ProtectUnprotect)Delegate.CreateDelegate(typeof(ProtectUnprotect), typeof(MachineKey), "Protect", ignoreCase: false, throwOnBindFailure: false);
- ProtectUnprotect unprotectThunk = (ProtectUnprotect)Delegate.CreateDelegate(typeof(ProtectUnprotect), typeof(MachineKey), "Unprotect", ignoreCase: false, throwOnBindFailure: false);
+ // Late bind to the MachineKey.Protect / Unprotect methods only if <httpRuntime targetFramework="4.5" />.
+ // This helps ensure that round-tripping the payloads continues to work even if the application is
+ // deployed to a mixed 4.0 / 4.5 farm environment.
+ PropertyInfo targetFrameworkProperty = typeof(HttpRuntime).GetProperty("TargetFramework", typeof(Version));
+ Version targetFramework = (targetFrameworkProperty != null) ? targetFrameworkProperty.GetValue(null, null) as Version : null;
+ if (targetFramework != null && targetFramework >= new Version(4, 5)) {
+ ProtectUnprotect protectThunk = (ProtectUnprotect)Delegate.CreateDelegate(typeof(ProtectUnprotect), typeof(MachineKey), "Protect", ignoreCase: false, throwOnBindFailure: false);
+ ProtectUnprotect unprotectThunk = (ProtectUnprotect)Delegate.CreateDelegate(typeof(ProtectUnprotect), typeof(MachineKey), "Unprotect", ignoreCase: false, throwOnBindFailure: false);
+ if (protectThunk != null && unprotectThunk != null) {
+ return new MachineKey45(protectThunk, unprotectThunk); // ASP.NET 4.5
+ }
+ }
- return (protectThunk != null && unprotectThunk != null)
- ? (IMachineKey)new MachineKey45(protectThunk, unprotectThunk) // ASP.NET 4.5
- : (IMachineKey)new MachineKey40(); // ASP.NET 4.0
+ return new MachineKey40(); // ASP.NET 4.0
}
/// <summary>
diff --git a/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
index d33913a..6a898a1 100644
--- a/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
+++ b/src/DotNetOpenAuth.AspNet/OpenAuthSecurityManager.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.AspNet {
using System;
using System.Diagnostics.CodeAnalysis;
+ using System.Text;
using System.Web;
using System.Web.Security;
using DotNetOpenAuth.AspNet.Clients;
@@ -19,6 +20,11 @@ namespace DotNetOpenAuth.AspNet {
#region Constants and Fields
/// <summary>
+ /// Purposes string used for protecting the anti-XSRF token.
+ /// </summary>
+ private const string AntiXsrfPurposeString = "DotNetOpenAuth.AspNet.AntiXsrfToken.v1";
+
+ /// <summary>
/// The provider query string name.
/// </summary>
private const string ProviderQueryStringName = "__provider__";
@@ -166,7 +172,10 @@ namespace DotNetOpenAuth.AspNet {
string sessionId = Guid.NewGuid().ToString("N");
uri = uri.AttachQueryStringParameter(SessionIdQueryStringName, sessionId);
- var xsrfCookie = new HttpCookie(SessionIdCookieName, sessionId) {
+ // The cookie value will be the current username secured against the session id we just created.
+ byte[] encryptedCookieBytes = MachineKeyUtil.Protect(Encoding.UTF8.GetBytes(GetUsername(this.requestContext)), AntiXsrfPurposeString, "Token: " + sessionId);
+
+ var xsrfCookie = new HttpCookie(SessionIdCookieName, HttpServerUtility.UrlTokenEncode(encryptedCookieBytes)) {
HttpOnly = true
};
if (FormsAuthentication.RequireSSL) {
@@ -245,6 +254,19 @@ namespace DotNetOpenAuth.AspNet {
}
/// <summary>
+ /// Returns the username of the current logged-in user.
+ /// </summary>
+ /// <param name="context">The HTTP request context.</param>
+ /// <returns>The username, or String.Empty if anonymous.</returns>
+ private static string GetUsername(HttpContextBase context) {
+ string username = null;
+ if (context.User.Identity.IsAuthenticated) {
+ username = context.User.Identity.Name;
+ }
+ return username ?? string.Empty;
+ }
+
+ /// <summary>
/// Validates the request against XSRF attack.
/// </summary>
/// <param name="sessionId">The session id embedded in the query string.</param>
@@ -252,24 +274,45 @@ namespace DotNetOpenAuth.AspNet {
/// <c>true</c> if the request is safe. Otherwise, <c>false</c>.
/// </returns>
private bool ValidateRequestAgainstXsrfAttack(out string sessionId) {
+ sessionId = null;
+
// get the session id query string parameter
string queryStringSessionId = this.requestContext.Request.QueryString[SessionIdQueryStringName];
// verify that the query string value is a valid guid
Guid guid;
if (!Guid.TryParse(queryStringSessionId, out guid)) {
- sessionId = null;
return false;
}
- // get the cookie id query string parameter
+ // the cookie value should be the current username secured against this guid
var cookie = this.requestContext.Request.Cookies[SessionIdCookieName];
+ if (cookie == null || string.IsNullOrEmpty(cookie.Value)) {
+ return false;
+ }
+
+ // extract the username embedded within the cookie
+ // if there is any error at all (crypto, malformed, etc.), fail gracefully
+ string usernameInCookie = null;
+ try {
+ byte[] encryptedCookieBytes = HttpServerUtility.UrlTokenDecode(cookie.Value);
+ byte[] decryptedCookieBytes = MachineKeyUtil.Unprotect(encryptedCookieBytes, AntiXsrfPurposeString, "Token: " + queryStringSessionId);
+ usernameInCookie = Encoding.UTF8.GetString(decryptedCookieBytes);
+ }
+ catch {
+ return false;
+ }
- bool successful = cookie != null && queryStringSessionId == cookie.Value;
+ string currentUsername = GetUsername(this.requestContext);
+ bool successful = string.Equals(currentUsername, usernameInCookie, StringComparison.OrdinalIgnoreCase);
if (successful) {
// be a good citizen, clean up cookie when the authentication succeeds
- this.requestContext.Response.Cookies.Remove(SessionIdCookieName);
+ var xsrfCookie = new HttpCookie(SessionIdCookieName, string.Empty) {
+ HttpOnly = true,
+ Expires = DateTime.Now.AddYears(-1)
+ };
+ this.requestContext.Response.Cookies.Set(xsrfCookie);
}
sessionId = queryStringSessionId;
diff --git a/src/DotNetOpenAuth.AspNet/UriHelper.cs b/src/DotNetOpenAuth.AspNet/UriHelper.cs
index 602f00c..bdf2ed0 100644
--- a/src/DotNetOpenAuth.AspNet/UriHelper.cs
+++ b/src/DotNetOpenAuth.AspNet/UriHelper.cs
@@ -21,7 +21,8 @@ namespace DotNetOpenAuth.AspNet {
/// The url.
/// </param>
/// <param name="parameterName">
- /// The parameter name.
+ /// The parameter name. This value should not be provided by an end user; the caller should
+ /// ensure that this value comes only from a literal string.
/// </param>
/// <param name="parameterValue">
/// The parameter value.
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.proj b/src/DotNetOpenAuth/DotNetOpenAuth.proj
index 1116119..8c9610d 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.proj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.proj
@@ -17,7 +17,7 @@
</PropertyGroup>
<ItemGroup>
- <ProjectReference Include="@(ProductProjects)">
+ <ProjectReference Include="stub.csproj;@(ProductProjects)">
<PrimaryProductOutput Condition=" '%(MergeIntoUnifiedAssembly)' != 'false' ">true</PrimaryProductOutput>
</ProjectReference>
<SignDependsOn Include="BuildUnifiedProduct" />
@@ -58,16 +58,19 @@
<MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" />
<Message Text="Merging $(ILMergeOutputAssembly)" Importance="high" />
- <!-- Arrange for DNOA.Core to appear *last* in the input assemblies list so that its assembly attributes overrides the rest. -->
+ <!-- Arrange for DNOA.Core to appear *last* in the input assemblies list so that its assembly attributes overrides the rest.
+ Also, this project's output must appear *first* in the list so that ILMerge will use its PE Header as the final one,
+ allowing file Properties in Windows Explorer to show DotNetOpenAuth.dll as the "Original Filename" along with other properties. -->
<ItemGroup>
- <ILMergeProductInputCoreAssembly Include="@(ILMergeProductInputAssemblies)" Condition=" '%(Filename)' == 'DotNetOpenAuth.Core' " />
- <ILMergeProductInputAssemblies Remove="@(ILMergeProductInputCoreAssembly)" />
- <ILMergeProductInputAssemblies Include="@(ILMergeProductInputCoreAssembly)" />
+ <OrderedMergeInputAssemblies Include="@(ILMergeProductInputAssemblies)" Condition=" '%(ILMergeProductInputAssemblies.FileName)' == 'DotNetOpenAuth' " />
+ <OrderedMergeInputAssemblies Include="@(ILMergeProductInputAssemblies)" Condition=" '%(ILMergeProductInputAssemblies.FileName)' != 'DotNetOpenAuth.Core' and '%(ILMergeProductInputAssemblies.FileName)' != 'DotNetOpenAuth' " />
+ <OrderedMergeInputAssemblies Include="@(ILMergeInputAssemblies)" />
+ <OrderedMergeInputAssemblies Include="@(ILMergeProductInputAssemblies)" Condition=" '%(ILMergeProductInputAssemblies.FileName)' == 'DotNetOpenAuth.Core' " />
</ItemGroup>
<ILMerge
ExcludeFile="$(ProjectRoot)ILMergeInternalizeExceptions.txt"
- InputAssemblies="@(ILMergeInputAssemblies);@(ILMergeProductInputAssemblies)"
+ InputAssemblies="@(OrderedMergeInputAssemblies)"
OutputFile="$(ILMergeOutputAssembly)"
SearchDirectories="@(ILMergeSearchDirectories)"
KeyFile="$(PublicKeyFile)"
diff --git a/src/DotNetOpenAuth/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..eb429c2
--- /dev/null
+++ b/src/DotNetOpenAuth/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------
+// <copyright file="AssemblyInfo.cs" company="Outercurve Foundation">
+// Copyright (c) Outercurve Foundation. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// We DON'T put an AssemblyVersionAttribute in here because it is generated in the build.
+
+using System;
+using System.Net;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Web.UI;
+
+// 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")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("DotNetOpenAuth")]
+[assembly: AssemblyCopyright("Copyright © 2011 Outercurve Foundation")]
+[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("AB72ED33-1B74-4433-B524-982101D353A1")]
+
+#if StrongNameSigned
+// See comment at top of this file. We need this so that strong-naming doesn't
+// keep this assembly from being useful to shared host (medium trust) web sites.
+[assembly: AllowPartiallyTrustedCallers]
+
+[assembly: InternalsVisibleTo("DotNetOpenAuth.Test, 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")]
+[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet.Test")]
+[assembly: InternalsVisibleTo("DotNetOpenAuth.AspNet")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
+#endif
diff --git a/src/DotNetOpenAuth/Stub.csproj b/src/DotNetOpenAuth/Stub.csproj
new file mode 100644
index 0000000..713639e
--- /dev/null
+++ b/src/DotNetOpenAuth/Stub.csproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))\EnlistmentInfo.props" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.props))' != '' " />
+
+ <PropertyGroup>
+ <SuppressBuildTarget>true</SuppressBuildTarget>
+ <AddContractsAssemblyForDelaySigning>false</AddContractsAssemblyForDelaySigning>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ </PropertyGroup>
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" />
+ <PropertyGroup>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7BAB551D-768A-4C34-9D9D-8299DEDFF778}</ProjectGuid>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <AssemblyName>DotNetOpenAuth</AssemblyName>
+ <OutputPath>$(IntermediatePath)\stub\</OutputPath>
+ <NoCodeContracts>true</NoCodeContracts>
+ </PropertyGroup>
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.Product.props" />
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </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