summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2011-06-09 17:14:03 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2011-06-09 17:14:03 -0700
commita921328045f5711fa4136a1f57d5db4745117905 (patch)
treefe2d7cfa663bdd22d4a85f3b19f9a66636610763 /src
parent2751e08721af51437ae5738e2da23dd460df6cc8 (diff)
parentd916633668329aa07f0b6f2ee952268a5dff8069 (diff)
downloadDotNetOpenAuth-a921328045f5711fa4136a1f57d5db4745117905.zip
DotNetOpenAuth-a921328045f5711fa4136a1f57d5db4745117905.tar.gz
DotNetOpenAuth-a921328045f5711fa4136a1f57d5db4745117905.tar.bz2
Merge branch 'v3.4' into sample2legged
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj6
-rw-r--r--src/DotNetOpenAuth.Test/Logging.config17
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs20
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs53
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs83
-rw-r--r--src/DotNetOpenAuth.Test/Performance/CodeTimers.cs401
-rw-r--r--src/DotNetOpenAuth.Test/Performance/HighPerformance.cs178
-rw-r--r--src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs56
-rw-r--r--src/DotNetOpenAuth.Test/TestBase.cs40
-rw-r--r--src/DotNetOpenAuth.sln1
-rw-r--r--src/DotNetOpenAuth/ComponentModel/ConverterBase.cs1
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd56
-rw-r--r--src/DotNetOpenAuth/Configuration/MessagingElement.cs28
-rw-r--r--src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs20
-rw-r--r--src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs74
-rw-r--r--src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs35
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj13
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs109
-rw-r--r--src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs1
-rw-r--r--src/DotNetOpenAuth/InfoCard/Token/Token.cs27
-rw-r--r--src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs25
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs34
-rw-r--r--src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs40
-rw-r--r--src/DotNetOpenAuth/Messaging/MessageSerializer.cs6
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs11
-rw-r--r--src/DotNetOpenAuth/Messaging/MultipartPostPart.cs43
-rw-r--r--src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs1
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs3
-rw-r--r--src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset1
-rw-r--r--src/DotNetOpenAuth/Mvc/OpenIdHelper.cs268
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs19
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Protocol.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ServiceProvider.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs33
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs11
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs36
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs36
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs62
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx22
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs261
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs62
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/UriIdentifier.cs2
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsDocument.cs2
-rw-r--r--src/DotNetOpenAuth/XrdsPublisher.cs2
-rw-r--r--src/version.txt2
65 files changed, 1786 insertions, 541 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 5e80f2c..2067ede 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -74,6 +74,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -111,6 +112,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -150,6 +152,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net" />
@@ -301,6 +304,9 @@
<Compile Include="OpenId\RelyingParty\IdentifierDiscoveryResultTests.cs" />
<Compile Include="OpenId\UriIdentifierTests.cs" />
<Compile Include="OpenId\XriIdentifierTests.cs" />
+ <Compile Include="Performance\CodeTimers.cs" />
+ <Compile Include="Performance\HighPerformance.cs" />
+ <Compile Include="Performance\PerformanceTestUtilities.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Messaging\ResponseTests.cs" />
<Compile Include="OAuth\AppendixScenarios.cs" />
diff --git a/src/DotNetOpenAuth.Test/Logging.config b/src/DotNetOpenAuth.Test/Logging.config
index 87da027..a32badd 100644
--- a/src/DotNetOpenAuth.Test/Logging.config
+++ b/src/DotNetOpenAuth.Test/Logging.config
@@ -17,6 +17,23 @@
<conversionPattern value="[%thread] %-5level - %message%newline" />
</layout>
</appender>
+ <appender name="StdOutAppender" type="log4net.Appender.ConsoleAppender">
+ <immediateFlush value="true" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
+ </layout>
+ </appender>
+ <appender name="StdErrAppender" type="log4net.Appender.ConsoleAppender">
+ <immediateFlush value="true" />
+ <target value="Console.Error" />
+ <filter type="log4net.Filter.LevelRangeFilter">
+ <param name="LevelMin" value="ERROR"/>
+ <param name="LevelMax" value="FATAL"/>
+ </filter>
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
+ </layout>
+ </appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="Info" />
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
index e862ca6..74e23bd 100644
--- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
@@ -24,29 +24,29 @@ namespace DotNetOpenAuth.Test.Mocks {
/// <summary>
/// Initializes a new instance of the <see cref="CoordinatingOAuthChannel"/> class for Consumers.
/// </summary>
- /// <param name="signingBindingElement">
- /// The signing element for the Consumer to use. Null for the Service Provider.
- /// </param>
+ /// <param name="signingBindingElement">The signing element for the Consumer to use. Null for the Service Provider.</param>
/// <param name="tokenManager">The token manager to use.</param>
- internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IConsumerTokenManager tokenManager)
+ /// <param name="securitySettings">The security settings.</param>
+ internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IConsumerTokenManager tokenManager, DotNetOpenAuth.OAuth.ConsumerSecuritySettings securitySettings)
: base(
signingBindingElement,
new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge),
- tokenManager) {
+ tokenManager,
+ securitySettings) {
}
/// <summary>
/// Initializes a new instance of the <see cref="CoordinatingOAuthChannel"/> class for Consumers.
/// </summary>
- /// <param name="signingBindingElement">
- /// The signing element for the Consumer to use. Null for the Service Provider.
- /// </param>
+ /// <param name="signingBindingElement">The signing element for the Consumer to use. Null for the Service Provider.</param>
/// <param name="tokenManager">The token manager to use.</param>
- internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IServiceProviderTokenManager tokenManager)
+ /// <param name="securitySettings">The security settings.</param>
+ internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IServiceProviderTokenManager tokenManager, DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings securitySettings)
: base(
signingBindingElement,
new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge),
- tokenManager) {
+ tokenManager,
+ securitySettings) {
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
index 479375a..34cc3a4 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -27,6 +27,8 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
private TestWebRequestHandler webRequestHandler;
private SigningBindingElementBase signingElement;
private INonceStore nonceStore;
+ private DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings serviceProviderSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.CreateSecuritySettings();
+ private DotNetOpenAuth.OAuth.ConsumerSecuritySettings consumerSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.Consumer.SecuritySettings.CreateSecuritySettings();
[SetUp]
public override void SetUp() {
@@ -35,33 +37,33 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
this.webRequestHandler = new TestWebRequestHandler();
this.signingElement = new RsaSha1SigningBindingElement(new InMemoryTokenManager());
this.nonceStore = new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge);
- this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory());
+ this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), this.serviceProviderSecuritySettings, new TestMessageFactory());
this.channel.WebRequestHandler = this.webRequestHandler;
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullSigner() {
- new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory());
+ new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullStore() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), null, new InMemoryTokenManager(), new TestMessageFactory());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), null, new InMemoryTokenManager(), this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullTokenManager() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, new TestMessageFactory());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase]
public void CtorSimpleConsumer() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager(), this.consumerSecuritySettings);
}
[TestCase]
public void CtorSimpleServiceProvider() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager(), this.serviceProviderSecuritySettings);
}
[TestCase]
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
index 2ef7e9a..83d5feb 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
@@ -5,6 +5,8 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth;
@@ -52,6 +54,15 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
"GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F",
SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+ // Test for when oauth_version isn't explicitly included in the message by the consumer.
+ message = CreateTestRequestTokenMessageNoOAuthVersion(
+ this.MessageDescriptions,
+ new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/", HttpDeliveryMethods.GetRequest));
+ message.ExtraData.Remove("scope"); // remove it from ExtraData since we put it in the URL
+ Assert.AreEqual(
+ "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F",
+ SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+
// This is a simulation of receiving the message, where the query string is still in the URL,
// but has been read into ExtraData, so parameters in the query string appear twice.
message = CreateTestRequestTokenMessage(
@@ -62,6 +73,42 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
}
+ [TestCase]
+ 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";
+ message.AccessToken = "tokenpublic";
+
+ var signedMessage = (ITamperResistantOAuthMessage)message;
+ signedMessage.HttpMethod = "GET";
+ signedMessage.SignatureMethod = "HMAC-SHA1";
+
+ MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(message);
+ dictionary["oauth_timestamp"] = "1302716502";
+ dictionary["oauth_nonce"] = "2U5YsZvL";
+
+ Assert.AreEqual(
+ "GET&http%3A%2F%2Ftom.test.wishpot.com%2Frestapi%2FList%2FSearch&List.LastName%3Dciccotosto%26oauth_consumer_key%3Dpublic%26oauth_nonce%3D2U5YsZvL%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1302716502%26oauth_token%3Dtokenpublic%26oauth_version%3D1.0",
+ SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+ }
+
+ internal static UnauthorizedTokenRequest CreateTestRequestTokenMessageNoOAuthVersion(MessageDescriptionCollection messageDescriptions, MessageReceivingEndpoint endpoint) {
+ endpoint = endpoint ?? new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
+ var parts = new Dictionary<string, string>();
+ parts["oauth_consumer_key"] = "nerdbank.org";
+ parts["oauth_timestamp"] = "1222665749";
+ parts["oauth_nonce"] = "fe4045a3f0efdd1e019fa8f8ae3f5c38";
+ parts["scope"] = "http://www.google.com/m8/feeds/";
+ parts["oauth_signature_method"] = "HMAC-SHA1";
+ parts["oauth_signature"] = "anything non-empty";
+
+ UnauthorizedTokenRequest message = new UnauthorizedTokenRequest(endpoint, Protocol.V10.Version);
+ MessageDictionary dictionary = messageDescriptions.GetAccessor(message);
+ MessageSerializer.Get(typeof(UnauthorizedTokenRequest)).Deserialize(parts, dictionary);
+
+ return message;
+ }
+
internal static UnauthorizedTokenRequest CreateTestRequestTokenMessage(MessageDescriptionCollection messageDescriptions, MessageReceivingEndpoint endpoint) {
endpoint = endpoint ?? new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
UnauthorizedTokenRequest message = new UnauthorizedTokenRequest(endpoint, Protocol.V10.Version);
@@ -76,5 +123,11 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
dictionary["scope"] = "http://www.google.com/m8/feeds/";
return message;
}
+
+ internal AccessProtectedResourceRequest CreateResourceRequest(MessageReceivingEndpoint endpoint) {
+ Contract.Requires(endpoint != null);
+ var message = new AccessProtectedResourceRequest(endpoint, Protocol.V10.Version);
+ return message;
+ }
}
}
diff --git a/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
index 972dd2a..6bcc583 100644
--- a/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
@@ -19,6 +19,8 @@ namespace DotNetOpenAuth.Test.OAuth {
internal class OAuthCoordinator : CoordinatorBase<WebConsumer, ServiceProvider> {
private ConsumerDescription consumerDescription;
private ServiceProviderDescription serviceDescription;
+ private DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings serviceProviderSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.CreateSecuritySettings();
+ private DotNetOpenAuth.OAuth.ConsumerSecuritySettings consumerSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.Consumer.SecuritySettings.CreateSecuritySettings();
/// <summary>Initializes a new instance of the <see cref="OAuthCoordinator"/> class.</summary>
/// <param name="consumerDescription">The description of the consumer.</param>
@@ -50,8 +52,8 @@ namespace DotNetOpenAuth.Test.OAuth {
serviceTokenManager.AddConsumer(this.consumerDescription);
// Prepare channels that will pass messages directly back and forth.
- CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, (IConsumerTokenManager)consumerTokenManager);
- CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, (IServiceProviderTokenManager)serviceTokenManager);
+ CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, (IConsumerTokenManager)consumerTokenManager, this.consumerSecuritySettings);
+ CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, (IServiceProviderTokenManager)serviceTokenManager, this.serviceProviderSecuritySettings);
consumerChannel.RemoteChannel = serviceProviderChannel;
serviceProviderChannel.RemoteChannel = consumerChannel;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
index 7984b58..4530982 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
@@ -18,6 +18,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
+ using DotNetOpenAuth.Test.Performance;
using NUnit.Framework;
[TestFixture, Category("Performance")]
@@ -29,73 +30,50 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
[SetUp]
public override void SetUp() {
base.SetUp();
- SuspendLogging();
this.provider = CreateProvider();
}
- [TearDown]
- public override void Cleanup() {
- ResumeLogging();
- base.Cleanup();
- }
-
[TestCase]
public void AssociateDH() {
var associateRequest = this.CreateAssociateRequest(OPUri);
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- IRequest request = this.provider.GetRequest(associateRequest);
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
- Assert.IsTrue(executionsPerSecond >= 2, "Too slow ({0} >= 2 executions per second required.)", executionsPerSecond);
+ MeasurePerformance(
+ () => {
+ IRequest request = this.provider.GetRequest(associateRequest);
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 3.5e6f,
+ iterations: 1);
}
[TestCase]
public void AssociateClearText() {
var associateRequest = this.CreateAssociateRequest(OPUriSsl); // SSL will cause a plaintext association
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- IRequest request = this.provider.GetRequest(associateRequest);
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 1000, "Too slow ({0} > 1000 executions per second required.)", executionsPerSecond);
+ MeasurePerformance(
+ () => {
+ IRequest request = this.provider.GetRequest(associateRequest);
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 1.5e4f,
+ iterations: 1000);
}
[TestCase]
public void CheckIdSharedHmacSha1Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA1;
- double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 500, "Too slow ({0} > 500 executions per second required.)", executionsPerSecond);
+ this.ParameterizedCheckIdTest(protocol, assocType);
}
[TestCase]
public void CheckIdSharedHmacSha256Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA256;
- double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 400, "Too slow ({0} > 400 executions per second required.)", executionsPerSecond);
+ this.ParameterizedCheckIdTest(protocol, assocType);
}
- private static double GetExecutionsPerSecond(int iterations, Stopwatch timer) {
- return (double)iterations / (timer.ElapsedMilliseconds / 1000);
- }
-
- private double ParameterizedCheckIdTest(Protocol protocol, string assocType) {
+ private void ParameterizedCheckIdTest(Protocol protocol, string assocType) {
Association assoc = HmacShaAssociation.Create(
protocol,
assocType,
@@ -103,19 +81,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
this.provider.SecuritySettings);
this.provider.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, assoc);
var checkidRequest = this.CreateCheckIdRequest(true);
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
- request.IsAuthenticated = true;
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<PositiveAssertionResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
- return executionsPerSecond;
+ MeasurePerformance(
+ () => {
+ var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
+ request.IsAuthenticated = true;
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<PositiveAssertionResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 6.8e4f);
}
private HttpRequestInfo CreateAssociateRequest(Uri opEndpoint) {
diff --git a/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs
new file mode 100644
index 0000000..85fa83d
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs
@@ -0,0 +1,401 @@
+// <auto-generated/> // well, imported. But this gets StyleCop off our back
+//-----------------------------------------------------------------------
+// <copyright file="CodeTimers.cs" company="Microsoft Corporation">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+// <author>Vance Morrison</author>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ /// <summary>
+ /// Stats represents a list of samples (floating point values) This class can calculate the standard
+ /// statistics on this list (Mean, Median, StandardDeviation ...)
+ /// </summary>
+ internal class Stats : IEnumerable<float> {
+ private List<float> data;
+ private float minimum;
+ private float maximum;
+ private float median;
+ private float mean;
+ private float standardDeviation;
+ private bool statsComputed;
+
+ public Stats() { data = new List<float>(); }
+
+ public void Add(float dataItem) {
+ statsComputed = false;
+ data.Add(dataItem);
+ }
+ public void RemoveRange(int index, int count) {
+ data.RemoveRange(index, count);
+ statsComputed = false;
+ }
+ internal void Adjust(float delta) {
+ statsComputed = false;
+ for (int i = 0; i < data.Count; i++)
+ data[i] += delta;
+ }
+ internal void AdjustForScale(float scale) {
+ statsComputed = false;
+ for (int i = 0; i < data.Count; i++)
+ data[i] /= scale;
+ }
+ public int Count { get { return data.Count; } }
+ public float this[int idx] { get { return data[idx]; } }
+ public IEnumerator<float> GetEnumerator() { return data.GetEnumerator(); }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return data.GetEnumerator(); }
+
+ public float Minimum {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return minimum;
+ }
+ }
+ public float Maximum {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return maximum;
+ }
+ }
+ public float Median {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return median;
+ }
+ }
+
+ public float Mean {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return mean;
+ }
+ }
+
+ public float StandardDeviation {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return standardDeviation;
+ }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String"/> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String"/> that represents this instance.
+ /// </returns>
+ public override string ToString() {
+ if (!statsComputed) {
+ ComputeStats();
+ }
+
+ return "mean=" + mean.ToString("f3") + " median=" + median.ToString("f3") +
+ " min=" + minimum.ToString("f3") + " max=" + maximum.ToString("f3") +
+ " sdtdev=" + standardDeviation.ToString("f3") + " samples=" + Count.ToString();
+ }
+
+ private void ComputeStats() {
+ minimum = float.MaxValue;
+ maximum = float.MinValue;
+ median = 0.0F;
+ mean = 0.0F;
+ standardDeviation = 0.0F;
+
+ double total = 0;
+ foreach (float dataPoint in this) {
+ if (dataPoint < minimum)
+ minimum = dataPoint;
+ if (dataPoint > maximum)
+ maximum = dataPoint;
+ total += dataPoint;
+ }
+
+ if (Count > 0) {
+ data.Sort();
+ if (Count % 2 == 1)
+ median = this[Count / 2];
+ else
+ median = (this[(Count / 2) - 1] + this[Count / 2]) / 2;
+ mean = (float)(total / Count);
+
+ double squares = 0.0;
+ foreach (float dataPoint in this) {
+ double diffFromMean = dataPoint - mean;
+ squares += diffFromMean * diffFromMean;
+ }
+ standardDeviation = (float)Math.Sqrt(squares / Count);
+ }
+
+ statsComputed = true;
+ }
+ };
+
+ /// <summary>
+ /// The CodeTimer class only times one invocation of the code. Often, you want to collect many samples so
+ /// that you can determine how noisy the resulting data is. This is what MultiSampleCodeTimer does.
+ /// </summary>
+ internal class MultiSampleCodeTimer {
+ public MultiSampleCodeTimer() : this(1) { }
+ public MultiSampleCodeTimer(int sampleCount) : this(sampleCount, 1) { }
+ public MultiSampleCodeTimer(int sampleCount, int iterationCount) {
+ SampleCount = sampleCount;
+ timer = new CodeTimer(iterationCount);
+ timer.Prime = false; // We will do the priming (or not).
+ Prime = true;
+ }
+ public MultiSampleCodeTimer(MultiSampleCodeTimer template)
+ : this(template.SampleCount, template.IterationCount) {
+ OnMeasure = template.OnMeasure;
+ }
+
+ /// <summary>
+ /// If true (the default), the benchmark is run once before the actual measurement to
+ /// insure that any 'first time' initialization is complete.
+ /// </summary>
+ public bool Prime;
+ /// <summary>
+ /// The number of times the benchmark is run in a loop for a single measument.
+ /// </summary>
+ public int IterationCount { get { return timer.IterationCount; } set { timer.IterationCount = value; } }
+ /// <summary>
+ /// The number of measurments to make for a single benchmark.
+ /// </summary>
+ public int SampleCount;
+ /// <summary>
+ /// The smallest time (in microseconds) that can be resolved by the timer).
+ /// </summary>
+ public static float ResolutionUsec { get { return 1000000.0F / Stopwatch.Frequency; } }
+
+ public delegate void MeasureCallback(string name, int iterationCount, float scale, Stats sample);
+ /// <summary>
+ /// OnMeasure is signaled every time a Measure() is called.
+ /// </summary>
+ public event MeasureCallback OnMeasure;
+
+ public Stats Measure(string name, Action action) {
+ return Measure(name, 1, action, null);
+ }
+ /// <summary>
+ /// The main measurment routine. Calling this will cause code:OnMeasure event to be
+ /// raised.
+ /// </summary>
+ /// <param name="name">name of the benchmark</param>
+ /// <param name="scale">The number of times the benchmark is cloned in 'action' (typically 1)</param>
+ /// <param name="action">The actual code to measure.</param>
+ /// <returns>A Stats object representing the measurements (in usec)</returns>
+ public Stats Measure(string name, float scale, Action action) {
+ return Measure(name, scale, action, null);
+ }
+ /// <summary>
+ /// The main measurment routine. Calling this will cause code:OnMeasure event to be
+ /// raised.
+ /// </summary>
+ /// <param name="name">name of the benchmark</param>
+ /// <param name="scale">The number of times the benchmark is cloned in 'action' (typically 1)</param>
+ /// <param name="action">The actual code to measure.</param>
+ /// <param name="reset">Code that will be called before 'action' to reset the state of the benchmark.</param>
+ /// <returns>A Stats object representing the measurements (in usec)</returns>
+ public Stats Measure(string name, float scale, Action action, Action reset) {
+ if (reset != null && IterationCount != 1)
+ throw new ApplicationException("Reset can only be used on timers with an iteration count of 1");
+ Stats statsUSec = new Stats();
+ if (Prime) {
+ if (reset != null)
+ reset();
+ action();
+ }
+ for (int i = 0; i < SampleCount; i++) {
+ if (reset != null)
+ reset();
+ statsUSec.Add(timer.Measure(name, scale, action));
+ }
+
+ if (OnMeasure != null)
+ OnMeasure(name, IterationCount, scale, statsUSec);
+ return statsUSec;
+ }
+
+ /// <summary>
+ /// Prints the mean, median, min, max, and stdDev and count of the samples to the Console
+ /// Useful as a target for OnMeasure
+ /// </summary>
+ public static MeasureCallback PrintStats = delegate(string name, int iterationCount, float scale, Stats sample) {
+ Console.WriteLine(name + ": " + sample.ToString());
+ };
+ /// <summary>
+ /// Prints the mean with a error bound (2 standard deviations, which imply a you have
+ /// 95% confidence that a sampleUsec will be with the bounds (for a normal distribution).
+ /// This is a good default target for OnMeasure.
+ /// </summary>
+ public static MeasureCallback Print = delegate(string name, int iterationCount, float scale, Stats sample) {
+ // +- two standard deviations covers 95% of all samples in a normal distribution
+ float errorPercent = (sample.StandardDeviation * 2 * 100) / Math.Abs(sample.Mean);
+ string errorString = ">400%";
+ if (errorPercent < 400)
+ errorString = (errorPercent.ToString("f0") + "%").PadRight(5);
+ string countString = "";
+ if (iterationCount != 1)
+ countString = "count: " + iterationCount.ToString() + " ";
+ Console.WriteLine(name + ": " + countString + sample.Mean.ToString("f3").PadLeft(8) + " +- " + errorString + " msec");
+ };
+
+ #region privates
+ CodeTimer timer;
+ #endregion
+ };
+
+ /// <summary>
+ /// CodeTimer is a simple wrapper that uses System.Diagnostics.StopWatch
+ /// to time the body of some code (given by a delegate), to high precision.
+ /// </summary>
+ public class CodeTimer {
+ public CodeTimer() : this(1) { }
+ public CodeTimer(int iterationCount) {
+ this.iterationCount = iterationCount;
+ Prime = true;
+
+ // Spin the CPU for a while. This should help insure that the CPU gets out of any low power
+ // mode so so that we get more stable results.
+ // TODO: see if this is true, and if there is a better way of doing it.
+ Stopwatch sw = Stopwatch.StartNew();
+ while (sw.ElapsedMilliseconds < 32) {
+ }
+ }
+ /// <summary>
+ /// The number of times the benchmark is run in a loop for a single measument.
+ /// </summary>
+ public int IterationCount {
+ get { return iterationCount; }
+ set {
+ iterationCount = value;
+ overheadValid = false;
+ }
+ }
+ /// <summary>
+ /// By default CodeTimer will run the action once before doing a
+ /// measurement run. This insures one-time actions like JIT
+ /// compilation are not being measured. However if the benchmark is
+ /// not idempotent, this can be a problem. Setting Prime=false
+ /// insures that this Priming does not happen.
+ /// </summary>
+ public bool Prime;
+ public delegate void MeasureCallback(string name, int iterationCount, float sample);
+ /// <summary>
+ /// OnMeasure is signaled every time a Measure() is called.
+ /// </summary>
+ public event MeasureCallback OnMeasure;
+ /// <summary>
+ /// The smallest time (in microseconds) that can be resolved by the timer).
+ /// </summary>
+ public static float ResolutionUsec { get { return 1000000.0F / Stopwatch.Frequency; } }
+ /// <summary>
+ /// Returns the number of microsecond it took to run 'action', 'count' times.
+ /// </summary>
+ public float Measure(string name, Action action) {
+ return Measure(name, 1, action);
+ }
+ /// <summary>
+ /// Returns the number of microseconds it to to run action 'count' times divided by 'scale'.
+ /// Scaling is useful if you want to normalize to a single iteration for example.
+ /// </summary>
+ public float Measure(string name, float scale, Action action) {
+ Stopwatch sw = new Stopwatch();
+
+ // Run the action once to do any JITTing that might happen.
+ if (Prime)
+ action();
+ float overheadUsec = GetOverheadUsec(action);
+
+ sw.Reset();
+ sw.Start();
+ for (int j = 0; j < iterationCount; j++)
+ action();
+ sw.Stop();
+
+ float sampleUsec = (float)((sw.Elapsed.TotalMilliseconds * 1000.0F - overheadUsec) / scale / iterationCount);
+ if (!computingOverhead && OnMeasure != null)
+ OnMeasure(name, iterationCount, sampleUsec);
+ return sampleUsec;
+ }
+ /// <summary>
+ /// Prints the result of a CodeTimer to standard output.
+ /// This is a good default target for OnMeasure.
+ /// </summary>
+ public static MeasureCallback Print = delegate(string name, int iterationCount, float sample) {
+ Console.WriteLine("{0}: count={1} time={2:f3} msec ", name, iterationCount, sample);
+ };
+ #region privates
+
+ /// <summary>
+ /// Time the overheadUsec of the harness that does nothing so we can subtract it out.
+ ///
+ /// Because calling delegates on static methods is more expensive than caling delegates on
+ /// instance methods we need the action to determine the overheadUsec.
+ /// </summary>
+ /// <returns></returns>
+ float GetOverheadUsec(Action action) {
+ if (!overheadValid) {
+ if (computingOverhead)
+ return 0.0F;
+ computingOverhead = true;
+
+ // Compute the overheads of calling differnet types of delegates.
+ Action emptyInstanceAction = new Action(this.emptyMethod);
+ // Prime the actions (JIT them)
+ Measure(null, emptyInstanceAction);
+ // Compute the min over 5 runs (figuring better not to go negative)
+ instanceOverheadUsec = float.MaxValue;
+ for (int i = 0; i < 5; i++) {
+ // We multiply by iteration count because we don't want this scaled by the
+ // count but 'Measure' does it by whether we want it or not.
+ instanceOverheadUsec = Math.Min(Measure(null, emptyInstanceAction) * IterationCount, instanceOverheadUsec);
+ }
+
+ Action emptyStaticAction = new Action(emptyStaticMethod);
+ Measure(null, emptyStaticAction);
+ staticOverheadUsec = float.MaxValue;
+ for (int i = 0; i < 5; i++)
+ staticOverheadUsec = Math.Min(Measure(null, emptyStaticAction) * IterationCount, staticOverheadUsec);
+
+ computingOverhead = false;
+ overheadValid = true;
+ }
+
+ if (action.Target == null)
+ return staticOverheadUsec;
+ else
+ return instanceOverheadUsec;
+ }
+
+ static private void emptyStaticMethod() { }
+ private void emptyMethod() { }
+
+ bool overheadValid;
+ bool computingOverhead;
+ int iterationCount;
+ float staticOverheadUsec;
+ float instanceOverheadUsec;
+
+ #endregion
+ };
+}
+
diff --git a/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs
new file mode 100644
index 0000000..695aeda
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs
@@ -0,0 +1,178 @@
+//-----------------------------------------------------------------------
+// <copyright file="HighPerformance.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using log4net;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Suppresses logging and forces the CPU into a high performance mode.
+ /// </summary>
+ internal class HighPerformance : IDisposable {
+ private readonly log4net.Core.Level originalLoggerThreshold;
+ private readonly PowerManagment.PowerSetting powerSetting;
+ private readonly ProcessPriorityClass originalProcessPriority;
+
+#pragma warning disable 0618
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HighPerformance"/> class.
+ /// </summary>
+ internal HighPerformance() {
+ ////if (!WaitForQuietCpu()) {
+ //// Assert.Inconclusive("Timed out waiting for a quiet CPU in which to perform perf tests.");
+ ////}
+
+ this.originalLoggerThreshold = LogManager.GetLoggerRepository().Threshold;
+ LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"];
+ this.powerSetting = new PowerManagment.PowerSetting(PowerManagment.PowerProfiles.HighPerformance);
+ this.originalProcessPriority = Process.GetCurrentProcess().PriorityClass;
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
+ Thread.CurrentThread.Priority = ThreadPriority.Highest;
+ SpinCpu();
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose() {
+ Thread.CurrentThread.Priority = ThreadPriority.Normal;
+ Process.GetCurrentProcess().PriorityClass = this.originalProcessPriority;
+ this.powerSetting.Dispose(); // restores original power setting.
+ LogManager.GetLoggerRepository().Threshold = this.originalLoggerThreshold;
+ }
+#pragma warning restore 0618
+
+ /// <summary>
+ /// Runs the CPU in a tight loop to get it out of any low power state.
+ /// </summary>
+ private static void SpinCpu() {
+ int dummy;
+ new MultiSampleCodeTimer(10, 1000).Measure(
+ "Loop 1K times",
+ 1,
+ delegate {
+ int k = 0;
+ while (k < 1000) {
+ k++; // still in danger of being optimized.
+ }
+
+ dummy = k; // avoid optimization.
+ });
+ }
+
+ private static bool WaitForQuietCpu(float maxCpuSpike = 25, int minSecondsOfQuiet = 2, int maxSecondsBeforeGiveUp = 30) {
+ using (var pc = new System.Diagnostics.PerformanceCounter()) {
+ pc.CategoryName = "Processor";
+ pc.CounterName = "% Processor Time";
+ pc.InstanceName = "_Total";
+
+ TimeSpan samplingInterval = TimeSpan.FromMilliseconds(1000);
+ TimeSpan minimumQuietTime = TimeSpan.FromSeconds(minSecondsOfQuiet);
+ TimeSpan maximumTimeBeforeBail = TimeSpan.FromSeconds(maxSecondsBeforeGiveUp);
+ DateTime startTryingStamp = DateTime.Now;
+ int hitsRequired = (int)(minimumQuietTime.TotalMilliseconds / samplingInterval.TotalMilliseconds);
+ while (DateTime.Now - startTryingStamp < maximumTimeBeforeBail) {
+ int hits;
+ for (hits = 0; hits < hitsRequired; hits++) {
+ float currentCpuUtilization = pc.NextValue();
+ if (currentCpuUtilization > maxCpuSpike) {
+ ////Console.WriteLine("Miss: CPU at {0}% utilization", currentCpuUtilization);
+ break;
+ }
+
+ ////Console.WriteLine("Hit: CPU at {0}% utilization", currentCpuUtilization);
+ Thread.Sleep(samplingInterval);
+ }
+
+ if (hits == hitsRequired) {
+ return true;
+ }
+
+ Thread.Sleep(samplingInterval);
+ }
+
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// PowerManagement allows you to access the funtionality of the Control Panel -> Power Options
+ /// dialog in windows. (Currently we only use VISTA APIs).
+ /// </summary>
+ private static class PowerManagment {
+ internal static unsafe Guid CurrentPolicy {
+ get {
+ Guid* retPolicy = null;
+ Guid ret = Guid.Empty;
+ try {
+ int callRet = PowerGetActiveScheme(IntPtr.Zero, ref retPolicy);
+ if (callRet == 0) {
+ ret = *retPolicy;
+ Marshal.FreeHGlobal((IntPtr)retPolicy);
+ }
+ } catch (Exception) {
+ }
+ return ret;
+ }
+
+ set {
+ Guid newPolicy = value;
+ int result = PowerSetActiveScheme(IntPtr.Zero, ref newPolicy);
+ if (result != 0) {
+ TestUtilities.TestLogger.ErrorFormat("Unable to set power management policy. Error code: {0}", result);
+ ////throw new Win32Exception(result);
+ }
+ }
+ }
+
+ [DllImport("powrprof.dll")]
+ private static unsafe extern int PowerGetActiveScheme(IntPtr reservedZero, ref Guid* policyGuidRet);
+
+ [DllImport("powrprof.dll")]
+ private static extern int PowerSetActiveScheme(IntPtr reservedZero, ref Guid policyGuid);
+
+ internal static class PowerProfiles {
+ internal static Guid HighPerformance = new Guid(0x8c5e7fda, 0xe8bf, 0x4a96, 0x9a, 0x85, 0xa6, 0xe2, 0x3a, 0x8c, 0x63, 0x5c);
+
+ internal static Guid Balanced = new Guid(0x381b4222, 0xf694, 0x41f0, 0x96, 0x85, 0xff, 0x5b, 0xb2, 0x60, 0xdf, 0x2e);
+
+ internal static Guid PowerSaver = new Guid(0xa1841308, 0x3541, 0x4fab, 0xbc, 0x81, 0xf7, 0x15, 0x56, 0xf2, 0x0b, 0x4a);
+ }
+
+ internal class PowerSetting : IDisposable {
+ /// <summary>
+ /// The power policy in effect when this instance was constructed.
+ /// </summary>
+ private Guid previousPolicy;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PowerSetting"/> class.
+ /// </summary>
+ /// <param name="powerProfile">The power profile.</param>
+ internal PowerSetting(Guid powerProfile) {
+ this.previousPolicy = PowerManagment.CurrentPolicy;
+ if (this.previousPolicy != powerProfile) {
+ PowerManagment.CurrentPolicy = powerProfile;
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose() {
+ if (this.previousPolicy != PowerManagment.CurrentPolicy) {
+ PowerManagment.CurrentPolicy = this.previousPolicy;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs
new file mode 100644
index 0000000..5e28732
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="PerformanceTestUtilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Threading;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using NUnit.Framework;
+
+ internal static class PerformanceTestUtilities {
+ internal static Stats Baseline;
+
+ static PerformanceTestUtilities() {
+ Baseline = CollectBaseline();
+ TestUtilities.TestLogger.InfoFormat(
+ "Scaled where EmptyStaticFunction = 1.0 ({0:f1} nsec = 1.0 units)",
+ Baseline.Median * 1000);
+ }
+
+ internal static bool IsOptimized(Assembly assembly) {
+ DebuggableAttribute debugAttribute = (DebuggableAttribute)System.Attribute.GetCustomAttribute(assembly, typeof(System.Diagnostics.DebuggableAttribute));
+ return debugAttribute == null || !debugAttribute.IsJITOptimizerDisabled;
+ }
+
+ private static Stats CollectBaseline() {
+ using (new HighPerformance()) {
+ return new MultiSampleCodeTimer(10, 1000).Measure(
+ "MethodCalls: EmptyStaticFunction()",
+ 10,
+ delegate {
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ });
+ }
+ }
+
+ private class Class {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static void EmptyStaticFunction() {
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/TestBase.cs b/src/DotNetOpenAuth.Test/TestBase.cs
index 8aeca2d..4a6eaca 100644
--- a/src/DotNetOpenAuth.Test/TestBase.cs
+++ b/src/DotNetOpenAuth.Test/TestBase.cs
@@ -11,6 +11,8 @@ namespace DotNetOpenAuth.Test {
using System.Web;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth.Messages;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Performance;
using log4net;
using NUnit.Framework;
@@ -65,6 +67,34 @@ namespace DotNetOpenAuth.Test {
log4net.LogManager.Shutdown();
}
+ internal static Stats MeasurePerformance(Action action, float maximumAllowedUnitTime, int samples = 10, int iterations = 100, string name = null) {
+ if (!PerformanceTestUtilities.IsOptimized(typeof(OpenIdRelyingParty).Assembly)) {
+ Assert.Inconclusive("Unoptimized code.");
+ }
+
+ var timer = new MultiSampleCodeTimer(samples, iterations);
+ Stats stats;
+ using (new HighPerformance()) {
+ stats = timer.Measure(name ?? TestContext.CurrentContext.Test.FullName, action);
+ }
+
+ stats.AdjustForScale(PerformanceTestUtilities.Baseline.Median);
+
+ TestUtilities.TestLogger.InfoFormat(
+ "Performance counters: median {0}, mean {1}, min {2}, max {3}, stddev {4} ({5}%).",
+ stats.Median,
+ stats.Mean,
+ stats.Minimum,
+ stats.Maximum,
+ stats.StandardDeviation,
+ stats.StandardDeviation / stats.Median * 100);
+
+ Assert.IsTrue(stats.Mean < maximumAllowedUnitTime, "The mean time of {0} exceeded the maximum allowable of {1}.", stats.Mean, maximumAllowedUnitTime);
+ TestUtilities.TestLogger.InfoFormat("Within {0}% of the maximum allowed time of {1}.", Math.Round((maximumAllowedUnitTime - stats.Mean) / maximumAllowedUnitTime * 100, 1), maximumAllowedUnitTime);
+
+ return stats;
+ }
+
/// <summary>
/// Sets HttpContext.Current to some empty (but non-null!) value.
/// </summary>
@@ -73,15 +103,5 @@ namespace DotNetOpenAuth.Test {
new HttpRequest("mock", "http://mock", "mock"),
new HttpResponse(new StringWriter()));
}
-
-#pragma warning disable 0618
- protected internal static void SuspendLogging() {
- LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"];
- }
-
- protected internal static void ResumeLogging() {
- LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["ALL"];
- }
-#pragma warning restore 0618
}
}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 2cef1b2..cf7f97e 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\doc\README.Bin.html = ..\doc\README.Bin.html
..\doc\README.html = ..\doc\README.html
..\samples\README.html = ..\samples\README.html
+ ..\nuget\content\web.config.transform = ..\nuget\content\web.config.transform
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
diff --git a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
index 980d90f..c41ac47 100644
--- a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
+++ b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
@@ -143,6 +143,7 @@ using System.Reflection;
/// <exception cref="T:System.NotSupportedException">
/// The conversion cannot be performed.
/// </exception>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
Contract.Assume(destinationType != null, "Missing contract.");
if (destinationType.IsInstanceOfType(value)) {
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
index 9c0ab77..0b27948 100644
--- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
@@ -218,6 +218,16 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="maximumIndirectMessageUrlLength" type="xs:int" default="2048">
+ <xs:annotation>
+ <xs:documentation>
+ The maximum allowable size for a 301 Redirect response before we send
+ a 200 OK response with a scripted form POST with the parameters instead
+ in order to ensure successfully sending a large payload to another server
+ that might have a maximum allowable size restriction on its GET request.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="openid">
@@ -243,6 +253,44 @@
</xs:documentation>
</xs:annotation>
<xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="trustedProviders">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="endpoint" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The OpenID Provider Endpoint (aka "OP Endpoint") that this relying party trusts.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="endpoint" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="clear">
+ <xs:complexType>
+ <!--tag is empty-->
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="rejectAssertionsFromUntrustedProviders" type="xs:boolean" default="false">
+ <xs:annotation>
+ <xs:documentation>
+ A value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ is true, all assertions are rejected.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
<xs:attribute name="requireSsl" type="xs:boolean" default="false">
<xs:annotation>
<xs:documentation>
@@ -269,7 +317,7 @@
<xs:attribute name="minimumHashBitLength" type="xs:int">
<xs:annotation>
<xs:documentation>
- Shared associations with OpenID Providers will only be formed or used if they
+ Shared associations with OpenID Providers will only be formed or used if they
are willing to form associations equal to or greater than a given level of protection.
</xs:documentation>
</xs:annotation>
@@ -524,7 +572,7 @@
so security is comparable to OpenID 2.0 relying parties.
</xs:documentation>
</xs:annotation>
- </xs:attribute>
+ </xs:attribute>
<xs:attribute name="unsolicitedAssertionVerification">
<xs:annotation>
<xs:documentation>
@@ -735,7 +783,7 @@
</xs:documentation>
</xs:annotation>
<xs:complexType>
-
+
</xs:complexType>
</xs:element>
</xs:choice>
@@ -856,7 +904,7 @@
<xs:attribute name="includeEventStatistics" type="xs:boolean" default="true">
<xs:annotation>
<xs:documentation>
- Whether a set of counters that track how often certain events (such as an
+ Whether a set of counters that track how often certain events (such as an
successful or failed authentication) is included in the report.
</xs:documentation>
</xs:annotation>
diff --git a/src/DotNetOpenAuth/Configuration/MessagingElement.cs b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
index f130dbc..28b34a3 100644
--- a/src/DotNetOpenAuth/Configuration/MessagingElement.cs
+++ b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
@@ -37,6 +37,20 @@ namespace DotNetOpenAuth.Configuration {
private const string StrictConfigName = "strict";
/// <summary>
+ /// The default value for the <see cref="MaximumIndirectMessageUrlLength"/> property.
+ /// </summary>
+ /// <value>
+ /// 2KB, recommended by OpenID group
+ /// </value>
+ private const int DefaultMaximumIndirectMessageUrlLength = 2 * 1024;
+
+ /// <summary>
+ /// The name of the attribute that controls the maximum length of a URL before it is converted
+ /// to a POST payload.
+ /// </summary>
+ private const string MaximumIndirectMessageUrlLengthConfigName = "maximumIndirectMessageUrlLength";
+
+ /// <summary>
/// Gets the actual maximum message lifetime that a program should allow.
/// </summary>
/// <value>The sum of the <see cref="MaximumMessageLifetime"/> and
@@ -114,5 +128,19 @@ namespace DotNetOpenAuth.Configuration {
get { return (UntrustedWebRequestElement)this[UntrustedWebRequestElementName] ?? new UntrustedWebRequestElement(); }
set { this[UntrustedWebRequestElementName] = value; }
}
+
+ /// <summary>
+ /// Gets or sets the maximum allowable size for a 301 Redirect response before we send
+ /// a 200 OK response with a scripted form POST with the parameters instead
+ /// in order to ensure successfully sending a large payload to another server
+ /// that might have a maximum allowable size restriction on its GET request.
+ /// </summary>
+ /// <value>The default value is 2048.</value>
+ [ConfigurationProperty(MaximumIndirectMessageUrlLengthConfigName, DefaultValue = DefaultMaximumIndirectMessageUrlLength)]
+ [IntegerValidator(MinValue = 500, MaxValue = 4096)]
+ internal int MaximumIndirectMessageUrlLength {
+ get { return (int)this[MaximumIndirectMessageUrlLengthConfigName]; }
+ set { this[MaximumIndirectMessageUrlLengthConfigName] = value; }
+ }
}
}
diff --git a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
index 1bf2ebc..4347e2c 100644
--- a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
@@ -81,6 +81,11 @@ namespace DotNetOpenAuth.Configuration {
private const string ProtectDownlevelReplayAttacksConfigName = "protectDownlevelReplayAttacks";
/// <summary>
+ /// The name of the &lt;trustedProviders&gt; sub-element.
+ /// </summary>
+ private const string TrustedProvidersElementName = "trustedProviders";
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartySecuritySettingsElement"/> class.
/// </summary>
public OpenIdRelyingPartySecuritySettingsElement() {
@@ -235,6 +240,16 @@ namespace DotNetOpenAuth.Configuration {
}
/// <summary>
+ /// Gets or sets the set of trusted OpenID Provider Endpoints.
+ /// </summary>
+ [ConfigurationProperty(TrustedProvidersElementName, IsDefaultCollection = false)]
+ [ConfigurationCollection(typeof(TrustedProviderConfigurationCollection))]
+ public TrustedProviderConfigurationCollection TrustedProviders {
+ get { return (TrustedProviderConfigurationCollection)this[TrustedProvidersElementName] ?? new TrustedProviderConfigurationCollection(); }
+ set { this[TrustedProvidersElementName] = value; }
+ }
+
+ /// <summary>
/// Initializes a programmatically manipulatable bag of these security settings with the settings from the config file.
/// </summary>
/// <returns>The newly created security settings object.</returns>
@@ -256,6 +271,11 @@ namespace DotNetOpenAuth.Configuration {
settings.AllowApproximateIdentifierDiscovery = this.AllowApproximateIdentifierDiscovery;
settings.ProtectDownlevelReplayAttacks = this.ProtectDownlevelReplayAttacks;
+ settings.RejectAssertionsFromUntrustedProviders = this.TrustedProviders.RejectAssertionsFromUntrustedProviders;
+ foreach (TrustedProviderEndpointConfigurationElement opEndpoint in this.TrustedProviders) {
+ settings.TrustedProviderEndpoints.Add(opEndpoint.ProviderEndpoint);
+ }
+
return settings;
}
}
diff --git a/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs b/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs
new file mode 100644
index 0000000..f5e62f4
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs
@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------
+// <copyright file="TrustedProviderConfigurationCollection.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Configuration {
+ using System;
+ using System.Collections.Generic;
+ using System.Configuration;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// A configuration collection of trusted OP Endpoints.
+ /// </summary>
+ internal class TrustedProviderConfigurationCollection : ConfigurationElementCollection {
+ /// <summary>
+ /// The name of the "rejectAssertionsFromUntrustedProviders" element.
+ /// </summary>
+ private const string RejectAssertionsFromUntrustedProvidersConfigName = "rejectAssertionsFromUntrustedProviders";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderConfigurationCollection"/> class.
+ /// </summary>
+ internal TrustedProviderConfigurationCollection() {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderConfigurationCollection"/> class.
+ /// </summary>
+ /// <param name="elements">The elements to initialize the collection with.</param>
+ [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "Seems unavoidable")]
+ internal TrustedProviderConfigurationCollection(IEnumerable<TrustedProviderEndpointConfigurationElement> elements) {
+ Contract.Requires<ArgumentNullException>(elements != null);
+
+ foreach (TrustedProviderEndpointConfigurationElement element in elements) {
+ this.BaseAdd(element);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ /// whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ /// is true, all assertions are rejected.
+ /// </summary>
+ [ConfigurationProperty(RejectAssertionsFromUntrustedProvidersConfigName, DefaultValue = false)]
+ internal bool RejectAssertionsFromUntrustedProviders {
+ get { return (bool)this[RejectAssertionsFromUntrustedProvidersConfigName]; }
+ set { this[RejectAssertionsFromUntrustedProvidersConfigName] = value; }
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </summary>
+ /// <returns>
+ /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override ConfigurationElement CreateNewElement() {
+ return new TrustedProviderEndpointConfigurationElement();
+ }
+
+ /// <summary>
+ /// Gets the element key for a specified configuration element when overridden in a derived class.
+ /// </summary>
+ /// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for.</param>
+ /// <returns>
+ /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override object GetElementKey(ConfigurationElement element) {
+ return ((TrustedProviderEndpointConfigurationElement)element).ProviderEndpoint;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs b/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs
new file mode 100644
index 0000000..2576eb0
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs
@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------
+// <copyright file="TrustedProviderEndpointConfigurationElement.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Configuration {
+ using System;
+ using System.Configuration;
+
+ /// <summary>
+ /// A configuration element that records a trusted Provider Endpoint.
+ /// </summary>
+ internal class TrustedProviderEndpointConfigurationElement : ConfigurationElement {
+ /// <summary>
+ /// The name of the attribute that stores the <see cref="ProviderEndpoint"/> value.
+ /// </summary>
+ private const string ProviderEndpointConfigName = "endpoint";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderEndpointConfigurationElement"/> class.
+ /// </summary>
+ public TrustedProviderEndpointConfigurationElement() {
+ }
+
+ /// <summary>
+ /// Gets or sets the OpenID Provider Endpoint (aka "OP Endpoint") that this relying party trusts.
+ /// </summary>
+ [ConfigurationProperty(ProviderEndpointConfigName, IsRequired = true, IsKey = true)]
+ public Uri ProviderEndpoint {
+ get { return (Uri)this[ProviderEndpointConfigName]; }
+ set { this[ProviderEndpointConfigName] = value; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 488e092..52930af 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -84,7 +84,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
<CodeContractsExtraRewriteOptions />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -125,7 +125,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
<CodeContractsExtraRewriteOptions />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoUI|AnyCPU'">
@@ -165,6 +165,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
<CodeContractsExtraRewriteOptions />
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -181,7 +182,7 @@ http://opensource.org/licenses/ms-pl.html
</CodeContractsCustomRewriterAssembly>
<CodeContractsCustomRewriterClass>
</CodeContractsCustomRewriterClass>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsRuntimeCheckingLevel>Preconditions</CodeContractsRuntimeCheckingLevel>
<CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
<CodeContractsBuildReferenceAssembly>True</CodeContractsBuildReferenceAssembly>
<CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
@@ -295,6 +296,8 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Configuration\OpenIdRelyingPartyElement.cs" />
<Compile Include="Configuration\OpenIdRelyingPartySecuritySettingsElement.cs" />
<Compile Include="Configuration\ReportingElement.cs" />
+ <Compile Include="Configuration\TrustedProviderConfigurationCollection.cs" />
+ <Compile Include="Configuration\TrustedProviderEndpointConfigurationElement.cs" />
<Compile Include="Configuration\TypeConfigurationCollection.cs" />
<Compile Include="Configuration\TypeConfigurationElement.cs" />
<Compile Include="Configuration\UntrustedWebRequestElement.cs" />
@@ -316,6 +319,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="InfoCard\WellKnownIssuers.cs" />
<Compile Include="Messaging\CachedDirectWebResponse.cs" />
<Compile Include="Messaging\ChannelContract.cs" />
+ <Compile Include="Messaging\IMessageOriginalPayload.cs" />
<Compile Include="Messaging\DirectWebRequestOptions.cs" />
<Compile Include="Messaging\EnumerableCache.cs" />
<Compile Include="Messaging\HostErrorException.cs" />
@@ -795,10 +799,11 @@ http://opensource.org/licenses/ms-pl.html
OutputFile="$(ILMergeOutputAssembly)"
KeyFile="$(PublicKeyFile)"
DelaySign="true"
+ ToolPath="$(ProjectRoot)tools\ILMerge"
TargetPlatformVersion="$(ClrVersion).0"
TargetPlatformDirectory="$(ILMergeTargetPlatformDirectory)" />
</Target>
<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
+</Project>
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index 9b1bcfa..8539422 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -9,54 +9,61 @@
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hmac", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rsa", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Diffie-Hellman", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "checkInput", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#Initialize(Mono.Math.BigInteger,Mono.Math.BigInteger,Mono.Math.BigInteger,System.Int32,System.Boolean)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Int32,System.Int32,Org.Mentalis.Security.Cryptography.DHKeyGeneration)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Int32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Byte[])")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellman.#FromXmlString(System.String)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "PostTrialDivisionTest", Scope = "member", Target = "Mono.Math.Prime.Generator.SequentialSearchPrimeGeneratorBase.#GenerateNewPrime(System.Int32,System.Object)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.Prime.PrimalityTests.#GetSPPRounds(Mono.Math.BigInteger,Mono.Math.Prime.ConfidenceFactor)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger+ModulusRing.#BarrettReduction(Mono.Math.BigInteger)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger.#op_Multiply(Mono.Math.BigInteger,Mono.Math.BigInteger)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sign", Scope = "member", Target = "Mono.Math.BigInteger.#.ctor(Mono.Math.BigInteger+Sign,System.UInt32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "notUsed", Scope = "member", Target = "Mono.Math.BigInteger.#isProbablePrime(System.Int32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "returnto", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "openid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "claimedid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Scope = "type", Target = "DotNetOpenAuth.OpenId.XriIdentifier")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "yyyy-MM-dd", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "usersetupurl", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "birthdate", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "rehydrated", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Bindings")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.ChannelElements")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.SimpleRegistration")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Messages")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "We sign it when producing drops.")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.OAuth")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.UI")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Reflection")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "oauthverifier", Scope = "resource", Target = "DotNetOpenAuth.OAuth.OAuthStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "whitelist", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "icam", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "idmanagement", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "no-pii", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "req", Scope = "member", Target = "DotNetOpenAuth.OpenId.Provider.IAuthenticationRequestContract.#DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest.ClaimedIdentifier")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "runat", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationRequest)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnIncomingPositiveAssertion(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationResponse)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.RelyingParty.RelyingPartySecuritySettings)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnOutgoingResponse(DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnIncomingRequest(DotNetOpenAuth.OpenId.Provider.IRequest)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.Provider.ProviderSecuritySettings)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mvc", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hmac", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rsa", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Diffie-Hellman", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "checkInput", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#Initialize(Mono.Math.BigInteger,Mono.Math.BigInteger,Mono.Math.BigInteger,System.Int32,System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Int32,System.Int32,Org.Mentalis.Security.Cryptography.DHKeyGeneration)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Byte[])")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellman.#FromXmlString(System.String)")]
+[assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "PostTrialDivisionTest", Scope = "member", Target = "Mono.Math.Prime.Generator.SequentialSearchPrimeGeneratorBase.#GenerateNewPrime(System.Int32,System.Object)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.Prime.PrimalityTests.#GetSPPRounds(Mono.Math.BigInteger,Mono.Math.Prime.ConfidenceFactor)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger+ModulusRing.#BarrettReduction(Mono.Math.BigInteger)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger.#op_Multiply(Mono.Math.BigInteger,Mono.Math.BigInteger)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sign", Scope = "member", Target = "Mono.Math.BigInteger.#.ctor(Mono.Math.BigInteger+Sign,System.UInt32)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "notUsed", Scope = "member", Target = "Mono.Math.BigInteger.#isProbablePrime(System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "returnto", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "openid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "claimedid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Scope = "type", Target = "DotNetOpenAuth.OpenId.XriIdentifier")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "yyyy-MM-dd", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "usersetupurl", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "birthdate", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "rehydrated", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Bindings")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.ChannelElements")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.SimpleRegistration")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Messages")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy")]
+[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "We sign it when producing drops.")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.OAuth")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.UI")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Reflection")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "oauthverifier", Scope = "resource", Target = "DotNetOpenAuth.OAuth.OAuthStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "whitelist", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "icam", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "idmanagement", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "no-pii", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "req", Scope = "member", Target = "DotNetOpenAuth.OpenId.Provider.IAuthenticationRequestContract.#DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest.ClaimedIdentifier")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "runat", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnIncomingPositiveAssertion(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationResponse)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.RelyingParty.RelyingPartySecuritySettings)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnOutgoingResponse(DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnIncomingRequest(DotNetOpenAuth.OpenId.Provider.IRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.Provider.ProviderSecuritySettings)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mvc", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
+[assembly: SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "DotNetOpenAuth.OpenId.DiffieHellmanUtilities.#.cctor()")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Scope = "member", Target = "DotNetOpenAuth.OAuth.Messages.SignedMessageBase.#DotNetOpenAuth.Messaging.IMessageOriginalPayload.OriginalPayload")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "iframe", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Sig", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", MessageId = "DSig", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
diff --git a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
index 2ac2b7e..3dd892a 100644
--- a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
+++ b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
@@ -71,6 +71,7 @@ namespace DotNetOpenAuth.InfoCard {
/// Adds an X.509 certificate with a private key that may be used to decrypt the incoming token.
/// </summary>
/// <param name="certificate">The certificate.</param>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
public void AddDecryptingToken(X509Certificate2 certificate) {
Contract.Requires<ArgumentNullException>(certificate != null);
Contract.Requires<ArgumentException>(certificate.HasPrivateKey);
diff --git a/src/DotNetOpenAuth/InfoCard/Token/Token.cs b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
index 89fa3a3..3b6f573 100644
--- a/src/DotNetOpenAuth/InfoCard/Token/Token.cs
+++ b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
@@ -41,6 +41,7 @@ namespace DotNetOpenAuth.InfoCard {
/// <param name="audience">The audience. May be <c>null</c> to avoid audience checking.</param>
/// <param name="decryptor">The decryptor to use to decrypt the token, if necessary..</param>
/// <exception cref="InformationCardException">Thrown for any problem decoding or decrypting the token.</exception>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type."), SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
private Token(string tokenXml, Uri audience, TokenDecryptor decryptor) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(tokenXml));
Contract.Requires<ArgumentException>(decryptor != null || !IsEncrypted(tokenXml));
@@ -64,7 +65,14 @@ namespace DotNetOpenAuth.InfoCard {
}
}
- this.Xml = new XPathDocument(new StringReader(decryptedString)).CreateNavigator();
+ var stringReader = new StringReader(decryptedString);
+ try {
+ this.Xml = new XPathDocument(stringReader).CreateNavigator();
+ } catch {
+ stringReader.Dispose();
+ throw;
+ }
+
Logger.InfoCard.DebugFormat("Incoming SAML token, after any decryption: {0}", this.Xml.InnerXml);
this.AuthorizationContext = TokenUtility.AuthenticateToken(this.Xml.ReadSubtree(), audience);
}
@@ -191,13 +199,26 @@ namespace DotNetOpenAuth.InfoCard {
/// <returns>
/// <c>true</c> if the specified token XML is encrypted; otherwise, <c>false</c>.
/// </returns>
- [Pure]
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive"), Pure]
internal static bool IsEncrypted(string tokenXml) {
Contract.Requires<ArgumentNullException>(tokenXml != null);
- using (XmlReader tokenReader = XmlReader.Create(new StringReader(tokenXml))) {
+ var stringReader = new StringReader(tokenXml);
+ XmlReader tokenReader;
+ try {
+ tokenReader = XmlReader.Create(stringReader);
+ } catch {
+ stringReader.Dispose();
+ throw;
+ }
+
+ try {
Contract.Assume(tokenReader != null); // CC missing for XmlReader.Create
return IsEncrypted(tokenReader);
+ } catch {
+ IDisposable disposableReader = tokenReader;
+ disposableReader.Dispose();
+ throw;
}
}
diff --git a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
index c9bc1d3..111d636 100644
--- a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.Messaging {
using System;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.IO;
using System.Net;
@@ -156,6 +157,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="response">The response whose stream is to be cloned.</param>
/// <param name="maximumBytesToRead">The maximum bytes to cache.</param>
/// <returns>The seekable Stream instance that contains a copy of what was returned in the HTTP response.</returns>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
private static MemoryStream CacheNetworkStreamAndClose(HttpWebResponse response, int maximumBytesToRead) {
Contract.Requires<ArgumentNullException>(response != null);
Contract.Ensures(Contract.Result<MemoryStream>() != null);
@@ -163,15 +165,20 @@ namespace DotNetOpenAuth.Messaging {
// Now read and cache the network stream
Stream networkStream = response.GetResponseStream();
MemoryStream cachedStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : Math.Min((int)response.ContentLength, maximumBytesToRead));
- Contract.Assume(networkStream.CanRead, "HttpWebResponse.GetResponseStream() always returns a readable stream."); // CC missing
- Contract.Assume(cachedStream.CanWrite, "This is a MemoryStream -- it's always writable."); // CC missing
- networkStream.CopyTo(cachedStream);
- cachedStream.Seek(0, SeekOrigin.Begin);
-
- networkStream.Dispose();
- response.Close();
-
- return cachedStream;
+ try {
+ Contract.Assume(networkStream.CanRead, "HttpWebResponse.GetResponseStream() always returns a readable stream."); // CC missing
+ Contract.Assume(cachedStream.CanWrite, "This is a MemoryStream -- it's always writable."); // CC missing
+ networkStream.CopyTo(cachedStream);
+ cachedStream.Seek(0, SeekOrigin.Begin);
+
+ networkStream.Dispose();
+ response.Close();
+
+ return cachedStream;
+ } catch {
+ cachedStream.Dispose();
+ throw;
+ }
}
}
}
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index 84dbe3c..0abdcfa 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -25,6 +25,7 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Manages sending direct messages to a remote party and receiving responses.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable.")]
[ContractVerification(true)]
[ContractClass(typeof(ChannelContract))]
public abstract class Channel : IDisposable {
@@ -47,14 +48,6 @@ namespace DotNetOpenAuth.Messaging {
protected internal static readonly ContentType HttpFormUrlEncodedContentType = new ContentType(HttpFormUrlEncoded) { CharSet = PostEntityEncoding.WebName };
/// <summary>
- /// The maximum allowable size for a 301 Redirect response before we send
- /// a 200 OK response with a scripted form POST with the parameters instead
- /// in order to ensure successfully sending a large payload to another server
- /// that might have a maximum allowable size restriction on its GET request.
- /// </summary>
- private const int IndirectMessageGetToPostThreshold = 2 * 1024; // 2KB, recommended by OpenID group
-
- /// <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>
@@ -120,6 +113,11 @@ namespace DotNetOpenAuth.Messaging {
private RequestCachePolicy cachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
/// <summary>
+ /// Backing field for the <see cref="MaximumIndirectMessageUrlLength"/> property.
+ /// </summary>
+ private int maximumIndirectMessageUrlLength = Configuration.DotNetOpenAuthSection.Configuration.Messaging.MaximumIndirectMessageUrlLength;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="Channel"/> class.
/// </summary>
/// <param name="messageTypeProvider">
@@ -157,6 +155,24 @@ namespace DotNetOpenAuth.Messaging {
public IDirectWebRequestHandler WebRequestHandler { get; set; }
/// <summary>
+ /// Gets or sets the maximum allowable size for a 301 Redirect response before we send
+ /// a 200 OK response with a scripted form POST with the parameters instead
+ /// in order to ensure successfully sending a large payload to another server
+ /// that might have a maximum allowable size restriction on its GET request.
+ /// </summary>
+ /// <value>The default value is 2048.</value>
+ public int MaximumIndirectMessageUrlLength {
+ get {
+ return this.maximumIndirectMessageUrlLength;
+ }
+
+ set {
+ Contract.Requires<ArgumentOutOfRangeException>(value >= 500 && value <= 4096);
+ this.maximumIndirectMessageUrlLength = value;
+ }
+ }
+
+ /// <summary>
/// Gets or sets the message descriptions.
/// </summary>
internal MessageDescriptionCollection MessageDescriptions {
@@ -730,7 +746,7 @@ namespace DotNetOpenAuth.Messaging {
// First try creating a 301 redirect, and fallback to a form POST
// if the message is too big.
OutgoingWebResponse response = this.Create301RedirectResponse(message, fields);
- if (response.Headers[HttpResponseHeader.Location].Length > IndirectMessageGetToPostThreshold) {
+ if (response.Headers[HttpResponseHeader.Location].Length > this.MaximumIndirectMessageUrlLength) {
response = this.CreateFormPostResponse(message, fields);
}
diff --git a/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs b/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs
new file mode 100644
index 0000000..d18be20
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessageOriginalPayload.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+
+ /// <summary>
+ /// An interface that appears on messages that need to retain a description of
+ /// what their literal payload was when they were deserialized.
+ /// </summary>
+ [ContractClass(typeof(IMessageOriginalPayloadContract))]
+ public interface IMessageOriginalPayload {
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")]
+ IDictionary<string, string> OriginalPayload { get; set; }
+ }
+
+ /// <summary>
+ /// Code contract for the <see cref="IMessageOriginalPayload"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IMessageOriginalPayload))]
+ internal abstract class IMessageOriginalPayloadContract : IMessageOriginalPayload {
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ IDictionary<string, string> IMessageOriginalPayload.OriginalPayload {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/MessageSerializer.cs b/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
index ccda5d5..e1625b9 100644
--- a/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
@@ -106,7 +106,13 @@ namespace DotNetOpenAuth.Messaging {
} catch (ArgumentException ex) {
throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name);
}
+
messageDictionary.Message.EnsureValidMessage();
+
+ var originalPayloadMessage = messageDictionary.Message as IMessageOriginalPayload;
+ if (originalPayloadMessage != null) {
+ originalPayloadMessage.OriginalPayload = fields;
+ }
}
#if CONTRACTS_FULL
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 85ba9a9..4b20ab8 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -444,9 +444,14 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(copyFrom.CanRead);
MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024);
- copyFrom.CopyTo(copyTo);
- copyTo.Position = 0;
- return copyTo;
+ try {
+ copyFrom.CopyTo(copyTo);
+ copyTo.Position = 0;
+ return copyTo;
+ } catch {
+ copyTo.Dispose();
+ throw;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
index f9a5988..eff40dd 100644
--- a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
+++ b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
@@ -40,10 +40,10 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Gets the content disposition.
+ /// Gets or sets the content disposition.
/// </summary>
/// <value>The content disposition.</value>
- public string ContentDisposition { get; private set; }
+ public string ContentDisposition { get; set; }
/// <summary>
/// Gets the key=value attributes that appear on the same line as the Content-Disposition.
@@ -103,9 +103,14 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(value != null);
var part = new MultipartPostPart("form-data");
- part.ContentAttributes["name"] = name;
- part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
- return part;
+ try {
+ part.ContentAttributes["name"] = name;
+ part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
+ return part;
+ } catch {
+ part.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -121,7 +126,13 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentType));
string fileName = Path.GetFileName(filePath);
- return CreateFormFilePart(name, fileName, contentType, File.OpenRead(filePath));
+ var fileStream = File.OpenRead(filePath);
+ try {
+ return CreateFormFilePart(name, fileName, contentType, fileStream);
+ } catch {
+ fileStream.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -139,14 +150,20 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(content != null);
var part = new MultipartPostPart("file");
- part.ContentAttributes["name"] = name;
- part.ContentAttributes["filename"] = fileName;
- part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
- if (!contentType.StartsWith("text/", StringComparison.Ordinal)) {
- part.PartHeaders["Content-Transfer-Encoding"] = "binary";
+ try {
+ part.ContentAttributes["name"] = name;
+ part.ContentAttributes["filename"] = fileName;
+ part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
+ if (!contentType.StartsWith("text/", StringComparison.Ordinal)) {
+ part.PartHeaders["Content-Transfer-Encoding"] = "binary";
+ }
+
+ part.Content = content;
+ return part;
+ } catch {
+ part.Dispose();
+ throw;
}
- part.Content = content;
- return part;
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
index 643cf81..800d2ba 100644
--- a/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
@@ -109,6 +109,8 @@ namespace DotNetOpenAuth.Messaging {
this.httpWebResponse = null;
}
}
+
+ base.Dispose(disposing);
}
}
}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
index 125742c..26d088b 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
@@ -33,6 +33,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <param name="messageType">A type that implements <see cref="IMessage"/>.</param>
/// <param name="messageVersion">The protocol version of the message.</param>
/// <returns>A <see cref="MessageDescription"/> instance.</returns>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
[Pure]
internal MessageDescription Get(Type messageType, Version messageVersion) {
Contract.Requires<ArgumentNullException>(messageType != null);
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index b876ec4..088aa05 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// The attribute discovered on <paramref name="member"/> that describes the
/// serialization requirements of the message part.
/// </param>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts requires it.")]
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Unavoidable"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts requires it.")]
internal MessagePart(MemberInfo member, MessagePartAttribute attribute) {
Contract.Requires<ArgumentNullException>(member != null);
Contract.Requires<ArgumentException>(member is FieldInfo || member is PropertyInfo);
@@ -295,6 +295,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <param name="toString">The function to convert the custom type to a string.</param>
/// <param name="toOriginalString">The mapping function that converts some custom value to its original (non-normalized) string. May be null if the same as the <paramref name="toString"/> function.</param>
/// <param name="toValue">The function to convert a string to the custom type.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "toString", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "toValue", Justification = "Code contracts")]
private static void Map<T>(Func<T, string> toString, Func<T, string> toOriginalString, Func<string, T> toValue) {
Contract.Requires<ArgumentNullException>(toString != null, "toString");
Contract.Requires<ArgumentNullException>(toValue != null, "toValue");
diff --git a/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
index db238b6..0ba4e6e 100644
--- a/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
+++ b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
@@ -5,6 +5,7 @@
<Rule Id="CA1054" Action="None" />
<Rule Id="CA1055" Action="None" />
<Rule Id="CA1056" Action="None" />
+ <Rule Id="CA1062" Action="None" />
<Rule Id="CA2104" Action="None" />
</Rules>
</RuleSet> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
index ffde271..adde6b6 100644
--- a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
+++ b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.Mvc {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -35,10 +36,11 @@ namespace DotNetOpenAuth.Mvc {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Ensures(Contract.Result<string>() != null);
- StringWriter result = new StringWriter();
- result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName);
- result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName);
- return result.ToString();
+ using (var result = new StringWriter(CultureInfo.CurrentCulture)) {
+ result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName);
+ result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName);
+ return result.ToString();
+ }
}
/// <summary>
@@ -59,43 +61,45 @@ namespace DotNetOpenAuth.Mvc {
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
public static string OpenIdSelectorScripts(this HtmlHelper html, OpenIdSelector selectorOptions, OpenIdAjaxOptions additionalOptions) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Ensures(Contract.Result<string>() != null);
+ bool selectorOptionsOwned = false;
if (selectorOptions == null) {
+ selectorOptionsOwned = true;
selectorOptions = new OpenId.RelyingParty.OpenIdSelector();
}
+ try {
+ if (additionalOptions == null) {
+ additionalOptions = new OpenIdAjaxOptions();
+ }
- if (additionalOptions == null) {
- additionalOptions = new OpenIdAjaxOptions();
- }
-
- StringWriter result = new StringWriter();
-
- if (additionalOptions.ShowDiagnosticIFrame || additionalOptions.ShowDiagnosticTrace) {
- string scriptFormat = @"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up
+ using (StringWriter result = new StringWriter(CultureInfo.CurrentCulture)) {
+ if (additionalOptions.ShowDiagnosticIFrame || additionalOptions.ShowDiagnosticTrace) {
+ string scriptFormat = @"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up
window.openid_trace = {1}; // causes lots of messages";
- result.WriteScriptBlock(string.Format(
- CultureInfo.InvariantCulture,
- scriptFormat,
- additionalOptions.ShowDiagnosticIFrame ? "true" : "false",
- additionalOptions.ShowDiagnosticTrace ? "true" : "false"));
- }
- var scriptResources = new[] {
+ result.WriteScriptBlock(string.Format(
+ CultureInfo.InvariantCulture,
+ scriptFormat,
+ additionalOptions.ShowDiagnosticIFrame ? "true" : "false",
+ additionalOptions.ShowDiagnosticTrace ? "true" : "false"));
+ }
+ var scriptResources = new[] {
OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource,
OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource,
OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedScriptResourceName,
};
- result.WriteScriptTags(scriptResources);
+ result.WriteScriptTags(scriptResources);
- if (selectorOptions.DownloadYahooUILibrary) {
- result.WriteScriptTagsUrls(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" });
- }
+ if (selectorOptions.DownloadYahooUILibrary) {
+ result.WriteScriptTagsUrls(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" });
+ }
- var blockBuilder = new StringWriter();
- if (selectorOptions.DownloadYahooUILibrary) {
- blockBuilder.WriteLine(@" try {
+ using (var blockBuilder = new StringWriter(CultureInfo.CurrentCulture)) {
+ if (selectorOptions.DownloadYahooUILibrary) {
+ blockBuilder.WriteLine(@" try {
if (YAHOO) {
var loader = new YAHOO.util.YUILoader({
require: ['button', 'menu'],
@@ -106,25 +110,25 @@ window.openid_trace = {1}; // causes lots of messages";
loader.insert();
}
} catch (e) { }");
- }
+ }
- blockBuilder.WriteLine("window.aspnetapppath = '{0}';", VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath));
+ blockBuilder.WriteLine("window.aspnetapppath = '{0}';", VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath));
- // Positive assertions can last no longer than this library is willing to consider them valid,
- // and when they come with OP private associations they last no longer than the OP is willing
- // to consider them valid. We assume the OP will hold them valid for at least five minutes.
- double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime.TotalMilliseconds));
- blockBuilder.WriteLine(
- "{0} = {1};",
- OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName,
- assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture));
+ // Positive assertions can last no longer than this library is willing to consider them valid,
+ // and when they come with OP private associations they last no longer than the OP is willing
+ // to consider them valid. We assume the OP will hold them valid for at least five minutes.
+ double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime.TotalMilliseconds));
+ blockBuilder.WriteLine(
+ "{0} = {1};",
+ OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName,
+ assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture));
- if (additionalOptions.PreloadedDiscoveryResults != null) {
- blockBuilder.WriteLine(additionalOptions.PreloadedDiscoveryResults);
- }
+ if (additionalOptions.PreloadedDiscoveryResults != null) {
+ blockBuilder.WriteLine(additionalOptions.PreloadedDiscoveryResults);
+ }
- string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath;
- string blockFormat = @" {0} = function (argument, resultFunction, errorCallback) {{
+ string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath;
+ string blockFormat = @" {0} = function (argument, resultFunction, errorCallback) {{
jQuery.ajax({{
async: true,
dataType: 'text',
@@ -133,22 +137,22 @@ window.openid_trace = {1}; // causes lots of messages";
url: '{1}'.replace('xxx', encodeURIComponent(argument))
}});
}};";
- blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl);
+ blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl);
- blockFormat = @" window.postLoginAssertion = function (positiveAssertion) {{
+ blockFormat = @" window.postLoginAssertion = function (positiveAssertion) {{
$('#{0}')[0].setAttribute('value', positiveAssertion);
if ($('#{1}')[0] && !$('#{1}')[0].value) {{ // popups have no ReturnUrl predefined, but full page LogOn does.
$('#{1}')[0].setAttribute('value', window.parent.location.href);
}}
document.forms[{2}].submit();
}};";
- blockBuilder.WriteLine(
- blockFormat,
- additionalOptions.AssertionHiddenFieldId,
- additionalOptions.ReturnUrlHiddenFieldId,
- additionalOptions.FormKey);
+ blockBuilder.WriteLine(
+ blockFormat,
+ additionalOptions.AssertionHiddenFieldId,
+ additionalOptions.ReturnUrlHiddenFieldId,
+ additionalOptions.FormKey);
- blockFormat = @" $(function () {{
+ blockFormat = @" $(function () {{
var box = document.getElementsByName('openid_identifier')[0];
initAjaxOpenId(box, {0}, {1}, {2}, {3}, {4}, {5},
null, // js function to invoke on receiving a positive assertion
@@ -156,32 +160,41 @@ window.openid_trace = {1}; // causes lots of messages";
false, // auto postback
null); // PostBackEventReference (unused in MVC)
}});";
- blockBuilder.WriteLine(
- blockFormat,
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName)),
- selectorOptions.Throttle,
- selectorOptions.Timeout.TotalMilliseconds,
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnText),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnToolTip),
- selectorOptions.TextBox.ShowLogOnPostBackButton ? "true" : "false",
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnPostBackToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryText),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.BusyToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.IdentifierRequiredMessage),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnInProgressMessage),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationSucceededToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticatedAsToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationFailedToolTip));
-
- result.WriteScriptBlock(blockBuilder.ToString());
- result.WriteScriptTags(OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName);
-
- Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name);
- return result.ToString();
+ blockBuilder.WriteLine(
+ blockFormat,
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName)),
+ selectorOptions.Throttle,
+ selectorOptions.Timeout.TotalMilliseconds,
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnText),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnToolTip),
+ selectorOptions.TextBox.ShowLogOnPostBackButton ? "true" : "false",
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnPostBackToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryText),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.BusyToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.IdentifierRequiredMessage),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnInProgressMessage),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationSucceededToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticatedAsToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationFailedToolTip));
+
+ result.WriteScriptBlock(blockBuilder.ToString());
+ result.WriteScriptTags(OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName);
+
+ Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name);
+ return result.ToString();
+ }
+ }
+ } catch {
+ if (selectorOptionsOwned) {
+ selectorOptions.Dispose();
+ }
+
+ throw;
+ }
}
/// <summary>
@@ -227,40 +240,42 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
public static string OpenIdSelector(this HtmlHelper html, params SelectorButton[] buttons) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Requires<ArgumentNullException>(buttons != null);
Contract.Ensures(Contract.Result<string>() != null);
- var writer = new StringWriter();
- var h = new HtmlTextWriter(writer);
+ using (var writer = new StringWriter(CultureInfo.CurrentCulture)) {
+ using (var h = new HtmlTextWriter(writer)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders");
+ h.RenderBeginTag(HtmlTextWriterTag.Ul);
- h.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders");
- h.RenderBeginTag(HtmlTextWriterTag.Ul);
+ foreach (SelectorButton button in buttons) {
+ var op = button as SelectorProviderButton;
+ if (op != null) {
+ h.Write(OpenIdSelectorOPButton(html, op.OPIdentifier, op.Image));
+ continue;
+ }
- foreach (SelectorButton button in buttons) {
- var op = button as SelectorProviderButton;
- if (op != null) {
- h.Write(OpenIdSelectorOPButton(html, op.OPIdentifier, op.Image));
- continue;
- }
+ var openid = button as SelectorOpenIdButton;
+ if (openid != null) {
+ h.Write(OpenIdSelectorOpenIdButton(html, openid.Image));
+ continue;
+ }
- var openid = button as SelectorOpenIdButton;
- if (openid != null) {
- h.Write(OpenIdSelectorOpenIdButton(html, openid.Image));
- continue;
- }
+ ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name);
+ }
- ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name);
- }
+ h.RenderEndTag(); // ul
- h.RenderEndTag(); // ul
+ if (buttons.OfType<SelectorOpenIdButton>().Any()) {
+ h.Write(OpenIdAjaxTextBox(html));
+ }
+ }
- if (buttons.OfType<SelectorOpenIdButton>().Any()) {
- h.Write(OpenIdAjaxTextBox(html));
+ return writer.ToString();
}
-
- return writer.ToString();
}
/// <summary>
@@ -271,6 +286,7 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "html", Justification = "Breaking change, and it's an extension method so it's useful.")]
public static string OpenIdAjaxTextBox(this HtmlHelper html) {
return @"<div style='display: none' id='OpenIDForm'>
<span class='OpenIdAjaxTextBox' style='display: inline-block; position: relative; font-size: 16px'>
@@ -289,48 +305,50 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
private static string OpenIdSelectorButton(this HtmlHelper html, string id, string cssClass, string imageUrl) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Requires<ArgumentNullException>(id != null);
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
Contract.Ensures(Contract.Result<string>() != null);
- var writer = new StringWriter();
- var h = new HtmlTextWriter(writer);
-
- h.AddAttribute(HtmlTextWriterAttribute.Id, id);
- if (!string.IsNullOrEmpty(cssClass)) {
- h.AddAttribute(HtmlTextWriterAttribute.Class, cssClass);
- }
- h.RenderBeginTag(HtmlTextWriterTag.Li);
+ using (var writer = new StringWriter(CultureInfo.CurrentCulture)) {
+ using (var h = new HtmlTextWriter(writer)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Id, id);
+ if (!string.IsNullOrEmpty(cssClass)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Class, cssClass);
+ }
+ h.RenderBeginTag(HtmlTextWriterTag.Li);
- h.AddAttribute(HtmlTextWriterAttribute.Href, "#");
- h.RenderBeginTag(HtmlTextWriterTag.A);
+ h.AddAttribute(HtmlTextWriterAttribute.Href, "#");
+ h.RenderBeginTag(HtmlTextWriterTag.A);
- h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
- h.RenderBeginTag(HtmlTextWriterTag.Img);
- h.RenderEndTag();
+ h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
+ h.RenderBeginTag(HtmlTextWriterTag.Img);
+ h.RenderEndTag();
- h.AddAttribute(HtmlTextWriterAttribute.Src, Util.GetWebResourceUrl(typeof(OpenIdSelector), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName));
- h.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess");
- h.AddAttribute(HtmlTextWriterAttribute.Title, "Authenticated as {0}");
- h.RenderBeginTag(HtmlTextWriterTag.Img);
- h.RenderEndTag();
+ h.AddAttribute(HtmlTextWriterAttribute.Src, Util.GetWebResourceUrl(typeof(OpenIdSelector), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName));
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess");
+ h.AddAttribute(HtmlTextWriterAttribute.Title, "Authenticated as {0}");
+ h.RenderBeginTag(HtmlTextWriterTag.Img);
+ h.RenderEndTag();
- h.RenderEndTag(); // div
+ h.RenderEndTag(); // div
- h.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay");
- h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.RenderEndTag(); // div
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay");
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderEndTag(); // div
- h.RenderEndTag(); // div
- h.RenderEndTag(); // a
- h.RenderEndTag(); // li
+ h.RenderEndTag(); // div
+ h.RenderEndTag(); // a
+ h.RenderEndTag(); // li
+ }
- return writer.ToString();
+ return writer.ToString();
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
index 53930bc..5828428 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
@@ -32,10 +32,11 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </remarks>
protected override string GetSignature(ITamperResistantOAuthMessage message) {
string key = GetConsumerAndTokenSecretString(message);
- HashAlgorithm hasher = new HMACSHA1(Encoding.ASCII.GetBytes(key));
- string baseString = ConstructSignatureBaseString(message, this.Channel.MessageDescriptions.GetAccessor(message));
- byte[] digest = hasher.ComputeHash(Encoding.ASCII.GetBytes(baseString));
- return Convert.ToBase64String(digest);
+ using (HashAlgorithm hasher = new HMACSHA1(Encoding.ASCII.GetBytes(key))) {
+ string baseString = ConstructSignatureBaseString(message, this.Channel.MessageDescriptions.GetAccessor(message));
+ byte[] digest = hasher.ComputeHash(Encoding.ASCII.GetBytes(baseString));
+ return Convert.ToBase64String(digest);
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
index ff6d6e9..a95001d 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
@@ -13,7 +13,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <summary>
/// An interface that OAuth messages implement to support signing.
/// </summary>
- public interface ITamperResistantOAuthMessage : IDirectedProtocolMessage, ITamperResistantProtocolMessage {
+ public interface ITamperResistantOAuthMessage : IDirectedProtocolMessage, ITamperResistantProtocolMessage, IMessageOriginalPayload {
/// <summary>
/// Gets or sets the method used to sign the message.
/// </summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index e6cfb78..2b1bea5 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -32,6 +33,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="store">The web application store to use for nonces.</param>
/// <param name="tokenManager">The token manager instance to use.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IConsumerTokenManager tokenManager, ConsumerSecuritySettings securitySettings)
: this(
signingBindingElement,
@@ -52,6 +54,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="store">The web application store to use for nonces.</param>
/// <param name="tokenManager">The token manager instance to use.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings)
: this(
signingBindingElement,
@@ -75,6 +78,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="messageTypeProvider">An injected message type provider instance.
/// Except for mock testing, this should always be one of
/// <see cref="OAuthConsumerMessageFactory"/> or <see cref="OAuthServiceProviderMessageFactory"/>.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, ITokenManager tokenManager, SecuritySettings securitySettings, IMessageFactory messageTypeProvider)
: base(messageTypeProvider, InitializeBindingElements(signingBindingElement, store, tokenManager, securitySettings)) {
Contract.Requires<ArgumentNullException>(tokenManager != null);
@@ -292,8 +296,9 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
};
var spTokenManager = tokenManager as IServiceProviderTokenManager;
- if (spTokenManager != null) {
- bindingElements.Insert(0, new TokenHandlingBindingElement(spTokenManager, (ServiceProviderSecuritySettings)securitySettings));
+ var serviceProviderSecuritySettings = securitySettings as ServiceProviderSecuritySettings;
+ if (spTokenManager != null && serviceProviderSecuritySettings != null) {
+ bindingElements.Insert(0, new TokenHandlingBindingElement(spTokenManager, serviceProviderSecuritySettings));
}
return bindingElements.ToArray();
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
index cb81139..31b5149 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
@@ -148,6 +149,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <remarks>
/// This method implements OAuth 1.0 section 9.1.
/// </remarks>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
internal static string ConstructSignatureBaseString(ITamperResistantOAuthMessage message, MessageDictionary messageDictionary) {
Contract.Requires<ArgumentNullException>(message != null);
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(message.HttpMethod));
@@ -175,6 +177,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
partsToInclude = messageDictionary;
}
+ // If this message was deserialized, include only those explicitly included message parts (excludes defaulted values)
+ // in the signature.
+ var originalPayloadMessage = (IMessageOriginalPayload)message;
+ if (originalPayloadMessage.OriginalPayload != null) {
+ partsToInclude = partsToInclude.Where(pair => originalPayloadMessage.OriginalPayload.ContainsKey(pair.Key));
+ }
+
foreach (var pair in OAuthChannel.GetUriEscapedParameters(partsToInclude)) {
encodedDictionary[pair.Key] = pair.Value;
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
index 329f8c4..bfebd8b 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -34,6 +35,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="tokenManager">The token manager.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contract"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal TokenHandlingBindingElement(IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(tokenManager != null);
Contract.Requires<ArgumentNullException>(securitySettings != null, "securitySettings");
diff --git a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
index 57ce470..6084fc0 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OAuth.Messages {
using System;
+ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
@@ -131,6 +132,24 @@ namespace DotNetOpenAuth.OAuth.Messages {
#endregion
+ #region IMessageOriginalPayload Members
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ IDictionary<string, string> IMessageOriginalPayload.OriginalPayload {
+ get { return this.OriginalPayload; }
+ set { this.OriginalPayload = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")]
+ protected IDictionary<string, string> OriginalPayload { get; set; }
+
+ #endregion
+
/// <summary>
/// Gets or sets the signature method used to sign the request.
/// </summary>
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
index fb4c9a1..723839d 100644
--- a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30104.0
+// Runtime Version:4.0.30319.225
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/src/DotNetOpenAuth/OAuth/Protocol.cs b/src/DotNetOpenAuth/OAuth/Protocol.cs
index a524ba7..6eecd8e 100644
--- a/src/DotNetOpenAuth/OAuth/Protocol.cs
+++ b/src/DotNetOpenAuth/OAuth/Protocol.cs
@@ -83,7 +83,7 @@ namespace DotNetOpenAuth.OAuth {
internal static readonly List<Protocol> AllVersions = new List<Protocol>() { V10a, V10 };
/// <summary>
- /// The default (or most recent) supported version of the OpenID protocol.
+ /// The default (or most recent) supported version of the OAuth protocol.
/// </summary>
internal static readonly Protocol Default = AllVersions[0];
diff --git a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
index fda895e..ec9206e 100644
--- a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
+++ b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
@@ -341,7 +341,7 @@ namespace DotNetOpenAuth.OAuth {
Contract.Requires<ArgumentException>((consumerKey == null) == (scope == null));
Contract.Requires<InvalidOperationException>(this.TokenManager is ICombinedOpenIdProviderTokenManager);
var openidTokenManager = (ICombinedOpenIdProviderTokenManager)this.TokenManager;
- ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), "The consumer key and the realm did not match according to the token manager.");
+ ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), OAuthStrings.OpenIdOAuthRealmConsumerKeyDoNotMatch);
this.AttachAuthorizationResponse(openIdAuthenticationRequest, scope);
}
diff --git a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
index 3afd44e..a6560d8 100644
--- a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
+++ b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
@@ -37,6 +37,7 @@ namespace DotNetOpenAuth.OAuth {
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Alikes", Justification = "Breaking change of existing API")]
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "AlphaNumeric", Justification = "Breaking change of existing API")]
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "LookAlikes", Justification = "Breaking change of existing API")]
AlphaNumericNoLookAlikes,
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
index c363c11..46c2139 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
@@ -99,27 +99,30 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// If ordering of the key=value pairs is important, a deterministic enumerator must
/// be used.
/// </remarks>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
public static byte[] GetBytes(IEnumerable<KeyValuePair<string, string>> keysAndValues) {
Contract.Requires<ArgumentNullException>(keysAndValues != null);
- MemoryStream ms = new MemoryStream();
- using (StreamWriter sw = new StreamWriter(ms, textEncoding)) {
- sw.NewLine = NewLineCharacters;
- foreach (var pair in keysAndValues) {
- if (pair.Key.IndexOfAny(IllegalKeyCharacters) >= 0) {
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Key));
- }
- if (pair.Value.IndexOfAny(IllegalValueCharacters) >= 0) {
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Value));
- }
+ using (MemoryStream ms = new MemoryStream()) {
+ using (StreamWriter sw = new StreamWriter(ms, textEncoding)) {
+ sw.NewLine = NewLineCharacters;
+ foreach (var pair in keysAndValues) {
+ if (pair.Key.IndexOfAny(IllegalKeyCharacters) >= 0) {
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Key));
+ }
+ if (pair.Value.IndexOfAny(IllegalValueCharacters) >= 0) {
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Value));
+ }
- sw.Write(pair.Key);
- sw.Write(':');
- sw.Write(pair.Value);
- sw.WriteLine();
+ sw.Write(pair.Key);
+ sw.Write(':');
+ sw.Write(pair.Value);
+ sw.WriteLine();
+ }
}
+
+ return ms.ToArray();
}
- return ms.ToArray();
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
index 55c2dc5..df36b5e 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
@@ -31,7 +31,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// <see cref="IdentifierDiscoveryResult.IsExtensionSupported&lt;T&gt;()"/> method.</para>
/// </remarks>
[Serializable]
- public sealed class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
+ public class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
index ba9852e..215ea24 100644
--- a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
+++ b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
@@ -212,6 +212,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="response">The response.</param>
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
/// <exception cref="ProtocolException">Thrown if the XRDS document has an invalid or a missing signature.</exception>
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "XmlDSig", Justification = "xml")]
private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) {
Contract.Requires<ArgumentNullException>(document != null);
Contract.Requires<ArgumentNullException>(identifier != null);
@@ -223,10 +224,10 @@ namespace DotNetOpenAuth.OpenId {
ErrorUtilities.VerifyProtocol(signedInfoNode != null, OpenIdStrings.MissingElement, "SignedInfo");
ErrorUtilities.VerifyProtocol(
signedInfoNode.SelectSingleNode("ds:CanonicalizationMethod[@Algorithm='http://docs.oasis-open.org/xri/xrd/2009/01#canonicalize-raw-octets']", document.XmlNamespaceResolver) != null,
- "Unrecognized or missing canonicalization method.");
+ OpenIdStrings.UnsupportedCanonicalizationMethod);
ErrorUtilities.VerifyProtocol(
signedInfoNode.SelectSingleNode("ds:SignatureMethod[@Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1']", document.XmlNamespaceResolver) != null,
- "Unrecognized or missing signature method.");
+ OpenIdStrings.UnsupportedSignatureMethod);
var certNodes = signatureNode.Select("ds:KeyInfo/ds:X509Data/ds:X509Certificate", document.XmlNamespaceResolver);
ErrorUtilities.VerifyProtocol(certNodes.Count > 0, OpenIdStrings.MissingElement, "X509Certificate");
var certs = certNodes.Cast<XPathNavigator>().Select(n => new X509Certificate2(Convert.FromBase64String(n.Value.Trim()))).ToList();
@@ -249,7 +250,7 @@ namespace DotNetOpenAuth.OpenId {
// Verify that the certificate is issued to the host on whom we are performing discovery.
string hostName = certs[0].GetNameInfo(X509NameType.DnsName, false);
- ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), "X.509 signing certificate issued to {0}, but a certificate for {1} was expected.", hostName, signingHost);
+ ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), OpenIdStrings.MisdirectedSigningCertificate, hostName, signingHost);
// Verify the signature itself
byte[] signature = Convert.FromBase64String(response.Headers["Signature"]);
@@ -257,7 +258,7 @@ namespace DotNetOpenAuth.OpenId {
byte[] data = new byte[response.ResponseStream.Length];
response.ResponseStream.Seek(0, SeekOrigin.Begin);
response.ResponseStream.Read(data, 0, data.Length);
- ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), "Invalid XmlDSig signature on XRDS document.");
+ ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), OpenIdStrings.InvalidDSig);
}
/// <summary>
@@ -271,7 +272,7 @@ namespace DotNetOpenAuth.OpenId {
/// an alternative plan.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if the certificate chain is invalid or unverifiable.</exception>
- [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "By design")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "DotNetOpenAuth.Messaging.ErrorUtilities.ThrowProtocol(System.String,System.Object[])", Justification = "The localized portion is a string resource already."), SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "By design")]
private static void VerifyCertChain(List<X509Certificate2> certs) {
var chain = new X509Chain();
foreach (var cert in certs) {
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
index ccfb1b8..a4fdf49 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
@@ -53,7 +53,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </remarks>
protected override Association CreateAssociationAtRelyingParty(AssociateRequest request) {
var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;
- ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, "request");
+ ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, OpenIdStrings.DiffieHellmanAssociationRequired);
HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(Protocol, this.SessionType);
byte[] associationSecret = DiffieHellmanUtilities.SHAHashXorSecret(hasher, diffieHellmanRequest.Algorithm, this.DiffieHellmanServerPublic, this.EncodedMacKey);
@@ -86,14 +86,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
// that will be transmitted to the Relying Party. The RP will perform an inverse operation
// using its part of a DH secret in order to decrypt the shared secret we just invented
// above when we created the association.
- DiffieHellman dh = new DiffieHellmanManaged(
+ using (DiffieHellman dh = new DiffieHellmanManaged(
diffieHellmanRequest.DiffieHellmanModulus ?? AssociateDiffieHellmanRequest.DefaultMod,
diffieHellmanRequest.DiffieHellmanGen ?? AssociateDiffieHellmanRequest.DefaultGen,
- AssociateDiffieHellmanRequest.DefaultX);
- HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);
- this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
- this.EncodedMacKey = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);
-
+ AssociateDiffieHellmanRequest.DefaultX)) {
+ HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);
+ this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
+ this.EncodedMacKey = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);
+ }
return association;
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
index d53b9d0..fce6028 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
@@ -16,7 +16,12 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// A common base class from which indirect response messages should derive.
/// </summary>
[Serializable]
- internal class IndirectResponseBase : RequestBase {
+ internal class IndirectResponseBase : RequestBase, IProtocolMessageWithExtensions {
+ /// <summary>
+ /// Backing store for the <see cref="Extensions"/> property.
+ /// </summary>
+ private IList<IExtensionMessage> extensions = new List<IExtensionMessage>();
+
/// <summary>
/// Initializes a new instance of the <see cref="IndirectResponseBase"/> class.
/// </summary>
@@ -42,6 +47,35 @@ namespace DotNetOpenAuth.OpenId.Messages {
: base(version, relyingPartyReturnTo, mode, MessageTransport.Indirect) {
}
+ #region IProtocolMessageWithExtensions Members
+
+ /// <summary>
+ /// Gets the list of extensions that are included with this message.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ public IList<IExtensionMessage> Extensions {
+ get { return this.extensions; }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets the signed extensions on this message.
+ /// </summary>
+ internal IEnumerable<IOpenIdMessageExtension> SignedExtensions {
+ get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => ext.IsSignedByRemoteParty); }
+ }
+
+ /// <summary>
+ /// Gets the unsigned extensions on this message.
+ /// </summary>
+ internal IEnumerable<IOpenIdMessageExtension> UnsignedExtensions {
+ get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => !ext.IsSignedByRemoteParty); }
+ }
+
/// <summary>
/// Gets the originating request message, if applicable.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
index 776b28b..baeae16 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
@@ -26,7 +26,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </summary>
[DebuggerDisplay("OpenID {Version} {Mode} (no id assertion)")]
[Serializable]
- internal class IndirectSignedResponse : IndirectResponseBase, ITamperResistantOpenIdMessage, IProtocolMessageWithExtensions {
+ internal class IndirectSignedResponse : IndirectResponseBase, ITamperResistantOpenIdMessage {
/// <summary>
/// The allowed date/time formats for the response_nonce parameter.
/// </summary>
@@ -36,11 +36,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
private static readonly string[] PermissibleDateTimeFormats = { "yyyy-MM-ddTHH:mm:ssZ" };
/// <summary>
- /// Backing store for the <see cref="Extensions"/> property.
- /// </summary>
- private IList<IExtensionMessage> extensions = new List<IExtensionMessage>();
-
- /// <summary>
/// Backing field for the <see cref="IExpiringProtocolMessage.UtcCreationDate"/> property.
/// </summary>
/// <remarks>
@@ -104,21 +99,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
this.ReturnTo = relyingPartyReturnTo;
}
- #region IProtocolMessageWithExtensions Members
-
- /// <summary>
- /// Gets the list of extensions that are included with this message.
- /// </summary>
- /// <value></value>
- /// <remarks>
- /// Implementations of this interface should ensure that this property never returns null.
- /// </remarks>
- public IList<IExtensionMessage> Extensions {
- get { return this.extensions; }
- }
-
- #endregion
-
/// <summary>
/// Gets the level of protection this message requires.
/// </summary>
@@ -241,20 +221,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
internal bool ReturnToParametersSignatureValidated { get; set; }
/// <summary>
- /// Gets the signed extensions on this message.
- /// </summary>
- internal IEnumerable<IOpenIdMessageExtension> SignedExtensions {
- get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => ext.IsSignedByRemoteParty); }
- }
-
- /// <summary>
- /// Gets the unsigned extensions on this message.
- /// </summary>
- internal IEnumerable<IOpenIdMessageExtension> UnsignedExtensions {
- get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => !ext.IsSignedByRemoteParty); }
- }
-
- /// <summary>
/// Gets or sets the nonce that will protect the message from replay attacks.
/// </summary>
/// <value>
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index 43283ac..f45af93 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.1
+// Runtime Version:4.0.30319.225
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -250,6 +250,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The associate request instance must be a Diffie-Hellman instance..
+ /// </summary>
+ internal static string DiffieHellmanAssociationRequired {
+ get {
+ return ResourceManager.GetString("DiffieHellmanAssociationRequired", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}.
/// </summary>
internal static string DiffieHellmanRequiredPropertiesNotSet {
@@ -349,6 +358,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Invalid XmlDSig signature on XRDS document..
+ /// </summary>
+ internal static string InvalidDSig {
+ get {
+ return ResourceManager.GetString("InvalidDSig", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Cannot decode Key-Value Form because a line was found without a &apos;{0}&apos; character. (line {1}: &apos;{2}&apos;).
/// </summary>
internal static string InvalidKeyValueFormCharacterMissing {
@@ -425,6 +443,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to X.509 signing certificate issued to {0}, but a certificate for {1} was expected..
+ /// </summary>
+ internal static string MisdirectedSigningCertificate {
+ get {
+ return ResourceManager.GetString("MisdirectedSigningCertificate", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Missing {0} element..
/// </summary>
internal static string MissingElement {
@@ -524,11 +551,20 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Looks up a localized string similar to An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party&apos;s whitelist..
+ /// Looks up a localized string similar to OpenID popup window or iframe did not recognize an OpenID response in the request..
/// </summary>
- internal static string PositiveAssertionFromNonWhitelistedProvider {
+ internal static string PopupRedirectMissingResponse {
get {
- return ResourceManager.GetString("PositiveAssertionFromNonWhitelistedProvider", resourceCulture);
+ return ResourceManager.GetString("PopupRedirectMissingResponse", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to An positive OpenID assertion was received from OP endpoint {0} and was rejected based on this site&apos;s security settings..
+ /// </summary>
+ internal static string PositiveAssertionFromNonQualifiedProvider {
+ get {
+ return ResourceManager.GetString("PositiveAssertionFromNonQualifiedProvider", resourceCulture);
}
}
@@ -722,6 +758,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Unrecognized or missing canonicalization method..
+ /// </summary>
+ internal static string UnsupportedCanonicalizationMethod {
+ get {
+ return ResourceManager.GetString("UnsupportedCanonicalizationMethod", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to This feature is unavailable due to an unrecognized channel configuration..
/// </summary>
internal static string UnsupportedChannelConfiguration {
@@ -731,6 +776,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Unrecognized or missing signature method..
+ /// </summary>
+ internal static string UnsupportedSignatureMethod {
+ get {
+ return ResourceManager.GetString("UnsupportedSignatureMethod", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests..
/// </summary>
internal static string UserSetupUrlRequiredInImmediateNegativeResponse {
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index fab03a9..b700d76 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -337,8 +337,8 @@ Discovered endpoint info:
<data name="BadExtension" xml:space="preserve">
<value>The {0} extension failed to deserialize and will be skipped. {1}</value>
</data>
- <data name="PositiveAssertionFromNonWhitelistedProvider" xml:space="preserve">
- <value>An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party's whitelist.</value>
+ <data name="PositiveAssertionFromNonQualifiedProvider" xml:space="preserve">
+ <value>An positive OpenID assertion was received from OP endpoint {0} and was rejected based on this site's security settings.</value>
</data>
<data name="HeadTagMustIncludeRunatServer" xml:space="preserve">
<value>The HTML head tag must include runat="server".</value>
@@ -355,4 +355,22 @@ Discovered endpoint info:
<data name="MissingElement" xml:space="preserve">
<value>Missing {0} element.</value>
</data>
+ <data name="DiffieHellmanAssociationRequired" xml:space="preserve">
+ <value>The associate request instance must be a Diffie-Hellman instance.</value>
+ </data>
+ <data name="InvalidDSig" xml:space="preserve">
+ <value>Invalid XmlDSig signature on XRDS document.</value>
+ </data>
+ <data name="MisdirectedSigningCertificate" xml:space="preserve">
+ <value>X.509 signing certificate issued to {0}, but a certificate for {1} was expected.</value>
+ </data>
+ <data name="PopupRedirectMissingResponse" xml:space="preserve">
+ <value>OpenID popup window or iframe did not recognize an OpenID response in the request.</value>
+ </data>
+ <data name="UnsupportedCanonicalizationMethod" xml:space="preserve">
+ <value>Unrecognized or missing canonicalization method.</value>
+ </data>
+ <data name="UnsupportedSignatureMethod" xml:space="preserve">
+ <value>Unrecognized or missing signature method.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
index ad73269..c5e6bba 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <param name="provider">The provider that received the request.</param>
/// <param name="request">The incoming authentication request message.</param>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts require it.")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "AuthenticationRequest", Justification = "Type name"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts require it.")]
internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
: base(provider, request) {
Contract.Requires<ArgumentNullException>(provider != null);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index 967ef60..3a17263 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -501,14 +501,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Contract.Requires<ArgumentNullException>(endpoints != null);
Contract.Requires<ArgumentNullException>(relyingParty != null);
- // Construct the endpoints filters based on criteria given by the host web site.
- EndpointSelector versionFilter = ep => ep.Version >= Protocol.Lookup(relyingParty.SecuritySettings.MinimumRequiredOpenIdVersion).Version;
- EndpointSelector hostingSiteFilter = relyingParty.EndpointFilter ?? (ep => true);
-
bool anyFilteredOut = false;
var filteredEndpoints = new List<IdentifierDiscoveryResult>();
foreach (var endpoint in endpoints) {
- if (versionFilter(endpoint) && hostingSiteFilter(endpoint)) {
+ if (relyingParty.FilterEndpoint(endpoint)) {
filteredEndpoints.Add(endpoint);
} else {
anyFilteredOut = true;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
index 869a342..9e3824d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+ using System.Linq;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -279,7 +280,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// have not been tampered with since the Provider sent the message.</para>
/// </remarks>
public T GetUntrustedExtension<T>() where T : IOpenIdMessageExtension {
- return default(T);
+ return this.response.Extensions.OfType<T>().FirstOrDefault();
}
/// <summary>
@@ -303,7 +304,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// have not been tampered with since the Provider sent the message.</para>
/// </remarks>
public IOpenIdMessageExtension GetUntrustedExtension(Type extensionType) {
- return null;
+ return this.response.Extensions.OfType<IOpenIdMessageExtension>().Where(ext => extensionType.IsInstanceOfType(ext)).FirstOrDefault();
}
#endregion
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index d80bf6a..8be097f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -721,11 +721,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
var css = new HtmlLink();
- css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName);
- css.Attributes["rel"] = "stylesheet";
- css.Attributes["type"] = "text/css";
- ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer);
- this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override
+ try {
+ css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName);
+ css.Attributes["rel"] = "stylesheet";
+ css.Attributes["type"] = "text/css";
+ ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer);
+ this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override
+ } catch {
+ css.Dispose();
+ throw;
+ }
this.PrepareClientJavascript();
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
index dbf6944..6243917 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
@@ -141,6 +141,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.HtmlTextWriter.WriteEncodedText(System.String)", Justification = "Not localizable")]
protected override void Render(HtmlTextWriter writer) {
if (string.IsNullOrEmpty(this.Identifier)) {
writer.WriteEncodedText(string.Format(CultureInfo.CurrentCulture, "[{0}]", OpenIdStrings.NoIdentifierSet));
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
index 5128599..eccdacf 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
@@ -316,7 +316,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets or sets the text to display if the user attempts to login
/// without providing an Identifier.
/// </summary>
- [Bindable(true)]
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), Bindable(true)]
[Category("Appearance")]
[DefaultValue(RequiredTextDefault)]
[Localizable(true)]
@@ -336,7 +336,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the text to display if the user provides an invalid form for an Identifier.
/// </summary>
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")]
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")]
[Bindable(true)]
[Category("Appearance")]
[DefaultValue(UriFormatTextDefault)]
@@ -687,150 +687,156 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Initializes the child controls.
/// </summary>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.WebControl.set_ToolTip(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Label.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.HyperLink.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.CheckBox.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Button.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.BaseValidator.set_ErrorMessage(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "It is correct"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "MyOpenID", Justification = "Correct spelling"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "myopenid", Justification = "URL")]
protected void InitializeControls() {
this.panel = new Panel();
Table table = new Table();
- TableRow row1, row2, row3;
- TableCell cell;
- table.Rows.Add(row1 = new TableRow());
- table.Rows.Add(row2 = new TableRow());
- table.Rows.Add(row3 = new TableRow());
-
- // top row, left cell
- cell = new TableCell();
try {
- this.label = new HtmlGenericControl("label");
- this.label.InnerText = LabelTextDefault;
- cell.Controls.Add(this.label);
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ TableRow row1, row2, row3;
+ TableCell cell;
+ table.Rows.Add(row1 = new TableRow());
+ table.Rows.Add(row2 = new TableRow());
+ table.Rows.Add(row3 = new TableRow());
+
+ // top row, left cell
+ cell = new TableCell();
+ try {
+ this.label = new HtmlGenericControl("label");
+ this.label.InnerText = LabelTextDefault;
+ cell.Controls.Add(this.label);
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // top row, middle cell
- cell = new TableCell();
- try {
- cell.Controls.Add(new InPlaceControl(this));
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // top row, middle cell
+ cell = new TableCell();
+ try {
+ cell.Controls.Add(new InPlaceControl(this));
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // top row, right cell
- cell = new TableCell();
- try {
- this.loginButton = new Button();
- this.loginButton.ID = this.ID + "_loginButton";
- this.loginButton.Text = ButtonTextDefault;
- this.loginButton.ToolTip = ButtonToolTipDefault;
- this.loginButton.Click += this.LoginButton_Click;
- this.loginButton.ValidationGroup = ValidationGroupDefault;
+ // top row, right cell
+ cell = new TableCell();
+ try {
+ this.loginButton = new Button();
+ this.loginButton.ID = this.ID + "_loginButton";
+ this.loginButton.Text = ButtonTextDefault;
+ this.loginButton.ToolTip = ButtonToolTipDefault;
+ this.loginButton.Click += this.LoginButton_Click;
+ this.loginButton.ValidationGroup = ValidationGroupDefault;
#if !Mono
- this.panel.DefaultButton = this.loginButton.ID;
+ this.panel.DefaultButton = this.loginButton.ID;
#endif
- cell.Controls.Add(this.loginButton);
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ cell.Controls.Add(this.loginButton);
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, left cell
- row2.Cells.Add(new TableCell());
+ // middle row, left cell
+ row2.Cells.Add(new TableCell());
+
+ // middle row, middle cell
+ cell = new TableCell();
+ try {
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ this.requiredValidator = new RequiredFieldValidator();
+ this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix;
+ this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix;
+ this.requiredValidator.Display = ValidatorDisplay.Dynamic;
+ this.requiredValidator.ValidationGroup = ValidationGroupDefault;
+ cell.Controls.Add(this.requiredValidator);
+ this.identifierFormatValidator = new CustomValidator();
+ this.identifierFormatValidator.ErrorMessage = UriFormatTextDefault + RequiredTextSuffix;
+ this.identifierFormatValidator.Text = UriFormatTextDefault + RequiredTextSuffix;
+ this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate;
+ this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault;
+ this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic;
+ this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault;
+ cell.Controls.Add(this.identifierFormatValidator);
+ this.errorLabel = new Label();
+ this.errorLabel.EnableViewState = false;
+ this.errorLabel.ForeColor = System.Drawing.Color.Red;
+ this.errorLabel.Style[HtmlTextWriterStyle.Display] = "block"; // puts it on its own line
+ this.errorLabel.Visible = false;
+ cell.Controls.Add(this.errorLabel);
+ this.examplePrefixLabel = new Label();
+ this.examplePrefixLabel.Text = ExamplePrefixDefault;
+ cell.Controls.Add(this.examplePrefixLabel);
+ cell.Controls.Add(new LiteralControl(" "));
+ this.exampleUrlLabel = new Label();
+ this.exampleUrlLabel.Font.Bold = true;
+ this.exampleUrlLabel.Text = ExampleUrlDefault;
+ cell.Controls.Add(this.exampleUrlLabel);
+ row2.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, middle cell
- cell = new TableCell();
- try {
- cell.Style[HtmlTextWriterStyle.Color] = "gray";
- cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
- this.requiredValidator = new RequiredFieldValidator();
- this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix;
- this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix;
- this.requiredValidator.Display = ValidatorDisplay.Dynamic;
- this.requiredValidator.ValidationGroup = ValidationGroupDefault;
- cell.Controls.Add(this.requiredValidator);
- this.identifierFormatValidator = new CustomValidator();
- this.identifierFormatValidator.ErrorMessage = UriFormatTextDefault + RequiredTextSuffix;
- this.identifierFormatValidator.Text = UriFormatTextDefault + RequiredTextSuffix;
- this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate;
- this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault;
- this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic;
- this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault;
- cell.Controls.Add(this.identifierFormatValidator);
- this.errorLabel = new Label();
- this.errorLabel.EnableViewState = false;
- this.errorLabel.ForeColor = System.Drawing.Color.Red;
- this.errorLabel.Style[HtmlTextWriterStyle.Display] = "block"; // puts it on its own line
- this.errorLabel.Visible = false;
- cell.Controls.Add(this.errorLabel);
- this.examplePrefixLabel = new Label();
- this.examplePrefixLabel.Text = ExamplePrefixDefault;
- cell.Controls.Add(this.examplePrefixLabel);
- cell.Controls.Add(new LiteralControl(" "));
- this.exampleUrlLabel = new Label();
- this.exampleUrlLabel.Font.Bold = true;
- this.exampleUrlLabel.Text = ExampleUrlDefault;
- cell.Controls.Add(this.exampleUrlLabel);
- row2.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // middle row, right cell
+ cell = new TableCell();
+ try {
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ cell.Style[HtmlTextWriterStyle.TextAlign] = "center";
+ this.registerLink = new HyperLink();
+ this.registerLink.Text = RegisterTextDefault;
+ this.registerLink.ToolTip = RegisterToolTipDefault;
+ this.registerLink.NavigateUrl = RegisterUrlDefault;
+ this.registerLink.Visible = RegisterVisibleDefault;
+ cell.Controls.Add(this.registerLink);
+ row2.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, right cell
- cell = new TableCell();
- try {
- cell.Style[HtmlTextWriterStyle.Color] = "gray";
- cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
- cell.Style[HtmlTextWriterStyle.TextAlign] = "center";
- this.registerLink = new HyperLink();
- this.registerLink.Text = RegisterTextDefault;
- this.registerLink.ToolTip = RegisterToolTipDefault;
- this.registerLink.NavigateUrl = RegisterUrlDefault;
- this.registerLink.Visible = RegisterVisibleDefault;
- cell.Controls.Add(this.registerLink);
- row2.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // bottom row, left cell
+ cell = new TableCell();
+ row3.Cells.Add(cell);
- // bottom row, left cell
- cell = new TableCell();
- row3.Cells.Add(cell);
+ // bottom row, middle cell
+ cell = new TableCell();
+ try {
+ this.rememberMeCheckBox = new CheckBox();
+ this.rememberMeCheckBox.Text = RememberMeTextDefault;
+ this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session;
+ this.rememberMeCheckBox.Visible = RememberMeVisibleDefault;
+ this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged;
+ cell.Controls.Add(this.rememberMeCheckBox);
+ row3.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // bottom row, middle cell
- cell = new TableCell();
- try {
- this.rememberMeCheckBox = new CheckBox();
- this.rememberMeCheckBox.Text = RememberMeTextDefault;
- this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session;
- this.rememberMeCheckBox.Visible = RememberMeVisibleDefault;
- this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged;
- cell.Controls.Add(this.rememberMeCheckBox);
- row3.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // bottom row, right cell
+ cell = new TableCell();
+ try {
+ row3.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // bottom row, right cell
- cell = new TableCell();
- try {
- row3.Cells.Add(cell);
+ // this sets all the controls' tab indexes
+ this.TabIndex = TabIndexDefault;
+
+ this.panel.Controls.Add(table);
} catch {
- cell.Dispose();
+ table.Dispose();
throw;
}
- // this sets all the controls' tab indexes
- this.TabIndex = TabIndexDefault;
-
- this.panel.Controls.Add(table);
-
this.idselectorJavascript = new Literal();
this.panel.Controls.Add(this.idselectorJavascript);
}
@@ -849,6 +855,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Renders the child controls.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the rendered content.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Literal.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselector", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "charset", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "src", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "openidselector", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselectorinputid", Justification = "html")]
protected override void RenderChildren(HtmlTextWriter writer) {
if (!this.DesignMode) {
this.label.Attributes["for"] = this.ClientID;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index a5fdf9b..57c1f05 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -39,6 +39,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Provides the programmatic facilities to act as an OpenID relying party.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
[ContractVerification(true)]
public class OpenIdRelyingParty : IDisposable {
/// <summary>
@@ -108,6 +109,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="associationStore">The association store. If null, the relying party will always operate in "dumb mode".</param>
/// <param name="nonceStore">The nonce store to use. If null, the relying party will always operate in "dumb mode".</param>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
private OpenIdRelyingParty(IAssociationStore<Uri> associationStore, INonceStore nonceStore) {
// If we are a smart-mode RP (supporting associations), then we MUST also be
// capable of storing nonces to prevent replay attacks.
@@ -542,15 +544,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
NegativeAssertionResponse negativeAssertion;
IndirectSignedResponse positiveExtensionOnly;
if ((positiveAssertion = message as PositiveAssertionResponse) != null) {
- if (this.EndpointFilter != null) {
- // We need to make sure that this assertion is coming from an endpoint
- // that the host deems acceptable.
- var providerEndpoint = new SimpleXrdsProviderEndpoint(positiveAssertion);
- ErrorUtilities.VerifyProtocol(
- this.EndpointFilter(providerEndpoint),
- OpenIdStrings.PositiveAssertionFromNonWhitelistedProvider,
- providerEndpoint.Uri);
- }
+ // We need to make sure that this assertion is coming from an endpoint
+ // that the host deems acceptable.
+ var providerEndpoint = new SimpleXrdsProviderEndpoint(positiveAssertion);
+ ErrorUtilities.VerifyProtocol(
+ this.FilterEndpoint(providerEndpoint),
+ OpenIdStrings.PositiveAssertionFromNonQualifiedProvider,
+ providerEndpoint.Uri);
var response = new PositiveAuthenticationResponse(positiveAssertion, this);
foreach (var behavior in this.Behaviors) {
@@ -660,8 +660,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
internal static OpenIdRelyingParty CreateNonVerifying() {
OpenIdRelyingParty rp = new OpenIdRelyingParty();
- rp.Channel = OpenIdChannel.CreateNonVerifyingChannel();
- return rp;
+ try {
+ rp.Channel = OpenIdChannel.CreateNonVerifyingChannel();
+ return rp;
+ } catch {
+ rp.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -672,13 +677,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <returns>
/// 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) {
Contract.Requires<ArgumentNullException>(request != null);
Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
string extensionsJson = null;
var authResponse = this.NonVerifyingRelyingParty.GetResponse();
- ErrorUtilities.VerifyProtocol(authResponse != null, "OpenID popup window or iframe did not recognize an OpenID response in the request.");
+ ErrorUtilities.VerifyProtocol(authResponse != null, OpenIdStrings.PopupRedirectMissingResponse);
// Give the caller a chance to notify the hosting page and fill up the clientScriptExtensions collection.
if (callback != null) {
@@ -761,6 +767,38 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Checks whether a given OP Endpoint is permitted by the host relying party.
+ /// </summary>
+ /// <param name="endpoint">The OP endpoint.</param>
+ /// <returns><c>true</c> if the OP Endpoint is allowed; <c>false</c> otherwise.</returns>
+ protected internal bool FilterEndpoint(IProviderEndpoint endpoint) {
+ if (this.SecuritySettings.RejectAssertionsFromUntrustedProviders) {
+ if (!this.SecuritySettings.TrustedProviderEndpoints.Contains(endpoint.Uri)) {
+ Logger.OpenId.InfoFormat("Filtering out OP endpoint {0} because it is not on the exclusive trusted provider whitelist.", endpoint.Uri.AbsoluteUri);
+ return false;
+ }
+ }
+
+ if (endpoint.Version < Protocol.Lookup(this.SecuritySettings.MinimumRequiredOpenIdVersion).Version) {
+ Logger.OpenId.InfoFormat(
+ "Filtering out OP endpoint {0} because it implements OpenID {1} but this relying party requires OpenID {2} or later.",
+ endpoint.Uri.AbsoluteUri,
+ endpoint.Version,
+ Protocol.Lookup(this.SecuritySettings.MinimumRequiredOpenIdVersion).Version);
+ return false;
+ }
+
+ if (this.EndpointFilter != null) {
+ if (!this.EndpointFilter(endpoint)) {
+ Logger.OpenId.InfoFormat("Filtering out OP endpoint {0} because the host rejected it.", endpoint.Uri.AbsoluteUri);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <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>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 62f6554..7cda8e0 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -546,7 +546,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Enables a server control to perform final clean up before it is released from memory.
/// </summary>
- [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Unavoidable because base class does not expose a protected virtual Dispose(bool) method."), SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
public sealed override void Dispose() {
this.Dispose(true);
base.Dispose();
@@ -809,6 +809,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Configures the relying party.
/// </summary>
/// <param name="relyingParty">The relying party.</param>
+ [SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "relyingParty", Justification = "This makes it possible for overrides to see the value before it is set on a field.")]
protected virtual void ConfigureRelyingParty(OpenIdRelyingParty relyingParty) {
Contract.Requires<ArgumentNullException>(relyingParty != null);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
index a7686c5..fc6d4c7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
@@ -8,6 +8,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -28,6 +30,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.PrivateSecretMaximumAge = TimeSpan.FromDays(7);
this.ProtectDownlevelReplayAttacks = ProtectDownlevelReplayAttacksDefault;
this.AllowApproximateIdentifierDiscovery = true;
+ this.TrustedProviderEndpoints = new HashSet<Uri>();
}
/// <summary>
@@ -143,6 +146,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public bool AllowApproximateIdentifierDiscovery { get; set; }
/// <summary>
+ /// Gets the set of trusted OpenID Provider Endpoint URIs.
+ /// </summary>
+ public HashSet<Uri> TrustedProviderEndpoints { get; private set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ /// whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ /// is true, all assertions are rejected.
+ /// </summary>
+ /// <value>Default is <c>false</c>.</value>
+ public bool RejectAssertionsFromUntrustedProviders { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether special measures are taken to
/// protect users from replay attacks when those users' identities are hosted
/// by OpenID 1.x Providers.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
index 279ca30..7926e8f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -50,6 +51,7 @@ namespace DotNetOpenAuth.OpenId {
/// </summary>
/// <param name="supportedServiceTypeUris">The supported service type URIs.</param>
/// <returns>The best OpenID protocol version to use when communicating with this Provider.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "Spelling correct")]
private static Protocol GetProtocolFromServices(string[] supportedServiceTypeUris) {
Protocol protocol = Protocol.FindBestVersion(p => p.RPReturnToTypeURI, supportedServiceTypeUris);
if (protocol == null) {
diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
index 48ed7f2..145a394 100644
--- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
@@ -480,7 +480,7 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<InternalErrorException>(schemeSubstitution);
Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
- int delimiterIndex = normal.IndexOf(Uri.SchemeDelimiter);
+ int delimiterIndex = normal.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal);
string normalScheme = delimiterIndex < 0 ? normal : normal.Substring(0, delimiterIndex);
string nonCompressingScheme;
if (string.Equals(normalScheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
diff --git a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
index e2c2d72..040c994 100644
--- a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.Xrds {
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Xml;
@@ -51,6 +52,7 @@ namespace DotNetOpenAuth.Xrds {
/// Initializes a new instance of the <see cref="XrdsDocument"/> class.
/// </summary>
/// <param name="xml">The text that is the XRDS document.</param>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Fixing would decrease readability, and not likely avoid any finalizer on a StringReader anyway.")]
public XrdsDocument(string xml)
: this(new XPathDocument(new StringReader(xml)).CreateNavigator()) { }
diff --git a/src/DotNetOpenAuth/XrdsPublisher.cs b/src/DotNetOpenAuth/XrdsPublisher.cs
index 83d82ff..03c32c1 100644
--- a/src/DotNetOpenAuth/XrdsPublisher.cs
+++ b/src/DotNetOpenAuth/XrdsPublisher.cs
@@ -208,7 +208,7 @@ namespace DotNetOpenAuth {
/// Renders the HTTP Header and/or HTML HEAD tags.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")]
protected override void Render(HtmlTextWriter writer) {
Contract.Assume(writer != null, "Missing contract.");
if (this.Enabled && this.Visible && !string.IsNullOrEmpty(this.XrdsUrl)) {
diff --git a/src/version.txt b/src/version.txt
index 2aa5131..7921bd0 100644
--- a/src/version.txt
+++ b/src/version.txt
@@ -1 +1 @@
-3.4.7
+3.4.8