summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs7
-rw-r--r--src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs56
-rw-r--r--src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs63
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs1
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj42
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln19
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs110
-rw-r--r--src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs8
-rw-r--r--src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs30
-rw-r--r--src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs61
-rw-r--r--src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs108
-rw-r--r--src/DotNetOpenAuth.BuildTasks/NativeMethods.cs18
-rw-r--r--src/DotNetOpenAuth.BuildTasks/PathSegment.cs321
-rw-r--r--src/DotNetOpenAuth.BuildTasks/Publicize.cs97
-rw-r--r--src/DotNetOpenAuth.BuildTasks/Purge.cs9
-rw-r--r--src/DotNetOpenAuth.BuildTasks/Utilities.cs31
-rw-r--r--src/DotNetOpenAuth.Test/AssemblyTesting.cs8
-rw-r--r--src/DotNetOpenAuth.Test/Configuration/SectionTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/CoordinatorBase.cs4
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj102
-rw-r--r--src/DotNetOpenAuth.Test/Hosting/HostingTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/LocalizationTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/Logging.config3
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs16
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs90
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/CollectionAssert.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs27
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs28
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs22
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs8
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs44
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs52
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs37
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Reflection/ValueMappingTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs14
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs12
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs47
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockReplayProtectionBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockTransformationBindingElement.cs4
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs52
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs16
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs48
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs24
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs28
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs20
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithBadXrds.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithEmptyXrds.html10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20dual.xml13
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs303
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs394
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs22
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs24
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs27
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs26
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs16
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs29
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs30
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs22
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs37
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs8
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs26
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Messages/SignedResponseRequestTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs37
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdUtilitiesTests.cs20
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs16
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs30
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs32
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs54
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RealmTests.cs38
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs69
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs199
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs16
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs28
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs10
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs39
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs71
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/ServiceEndpointTests.cs195
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs410
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs406
-rw-r--r--src/DotNetOpenAuth.Test/Test References/DotNetOpenAuth.accessor1
-rw-r--r--src/DotNetOpenAuth.Test/TestBase.cs33
-rw-r--r--src/DotNetOpenAuth.Test/UriUtilTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/UtilTests.cs6
-rw-r--r--src/DotNetOpenAuth.sln173
-rw-r--r--src/DotNetOpenAuth.vsmdi540
-rw-r--r--src/DotNetOpenAuth/ComponentModel/ConverterBase.cs1
-rw-r--r--src/DotNetOpenAuth/ComponentModel/IdentifierConverter.cs2
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd47
-rw-r--r--src/DotNetOpenAuth/Configuration/MessagingElement.cs23
-rw-r--r--src/DotNetOpenAuth/Configuration/OpenIdRelyingPartyElement.cs34
-rw-r--r--src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs55
-rw-r--r--src/DotNetOpenAuth/Configuration/ReportingElement.cs2
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj156
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.icobin0 -> 1150 bytes
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs3
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs65
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs4
-rw-r--r--src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs8
-rw-r--r--src/DotNetOpenAuth/InfoCard/Token/Token.cs22
-rw-r--r--src/DotNetOpenAuth/InfoCard/Token/TokenUtility.cs4
-rw-r--r--src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs13
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs69
-rw-r--r--src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs152
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs22
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.resx6
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs108
-rw-r--r--src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs7
-rw-r--r--src/DotNetOpenAuth/Messaging/ProtocolException.cs5
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/IMessagePartOriginalEncoder.cs22
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDescription.cs15
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs14
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs25
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs89
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/ValueMapping.cs21
-rw-r--r--src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset10
-rw-r--r--src/DotNetOpenAuth/Mvc/OpenIdAjaxOptions.cs76
-rw-r--r--src/DotNetOpenAuth/Mvc/OpenIdHelper.cs432
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs27
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs24
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBaseContract.cs3
-rw-r--r--src/DotNetOpenAuth/OAuth/ConsumerBase.cs22
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs27
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs31
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.resx3
-rw-r--r--src/DotNetOpenAuth/OpenId/Association.cs28
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.Designer.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs9
-rw-r--r--src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs515
-rw-r--r--src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs61
-rw-r--r--src/DotNetOpenAuth/OpenId/Identifier.cs66
-rw-r--r--src/DotNetOpenAuth/OpenId/IdentifierContract.cs13
-rw-r--r--src/DotNetOpenAuth/OpenId/IdentifierDiscoveryResult.cs (renamed from src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs)389
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs11
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs31
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx9
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs75
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs60
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs21
-rw-r--r--src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs98
-rw-r--r--src/DotNetOpenAuth/OpenId/Realm.cs46
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs20
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs103
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/DuplicateRequestedHostsComparer.cs74
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs21
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IProviderEndpoint.cs23
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpoint.cs41
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpointContract.cs59
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs238
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs10
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs175
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs287
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs318
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js8
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs165
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs110
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js10
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs49
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs51
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.gifbin237 -> 0 bytes
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.pngbin0 -> 457 bytes
-rw-r--r--src/DotNetOpenAuth/OpenId/UriDiscoveryService.cs139
-rw-r--r--src/DotNetOpenAuth/OpenId/UriIdentifier.cs458
-rw-r--r--src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs108
-rw-r--r--src/DotNetOpenAuth/OpenId/XriIdentifier.cs79
-rw-r--r--src/DotNetOpenAuth/Reporting.cs173
-rw-r--r--src/DotNetOpenAuth/Strings.Designer.cs16
-rw-r--r--src/DotNetOpenAuth/Util.cs2
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdElement.cs2
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsDocument.cs12
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsNode.cs6
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsStrings.Designer.cs4
-rw-r--r--src/DotNetOpenAuth/XrdsPublisher.cs2
-rw-r--r--src/DotNetOpenAuth/Yadis/DiscoveryResult.cs37
-rw-r--r--src/DotNetOpenAuth/Yadis/Yadis.cs3
-rw-r--r--src/LocalTestRun.testrunconfig22
-rw-r--r--src/version.txt2
235 files changed, 7607 insertions, 4068 deletions
diff --git a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs
index 30fa284..0b84398 100644
--- a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs
+++ b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs
@@ -6,13 +6,13 @@
namespace DotNetOpenAuth.BuildTasks {
using System;
+ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.BuildEngine;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
- using System.Collections;
public class AddProjectItems : Task {
/// <summary>
@@ -49,7 +49,10 @@ namespace DotNetOpenAuth.BuildTasks {
BuildItem newItem = project.AddNewItem(itemType, projectItem.ItemSpec, false);
var customMetadata = projectItem.CloneCustomMetadata();
foreach (DictionaryEntry entry in customMetadata) {
- newItem.SetMetadata((string)entry.Key, (string)entry.Value);
+ string value = (string)entry.Value;
+ if (value.Length > 0) {
+ newItem.SetMetadata((string)entry.Key, value);
+ }
}
}
diff --git a/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs
index f940a72..503e168 100644
--- a/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs
+++ b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs
@@ -1,47 +1,59 @@
-using System;
-using System.Linq;
-using System.IO;
-using System.Xml;
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.IO;
+ using System.Linq;
+ using System.Xml;
+ using Microsoft.Build.BuildEngine;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using Microsoft.Build.BuildEngine;
-
-namespace DotNetOpenAuth.BuildTasks {
/// <summary>
/// Replaces ProjectReference items in a set of projects with Reference items.
/// </summary>
public class ChangeProjectReferenceToAssemblyReference : Task {
+ private const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";
+
/// <summary>
/// The projects to alter.
/// </summary>
[Required]
public ITaskItem[] Projects { get; set; }
+
/// <summary>
- /// The project reference to remove.
+ /// The project references to remove.
/// </summary>
[Required]
- public string ProjectReference { get; set; }
+ public ITaskItem[] ProjectReferences { get; set; }
+
/// <summary>
- /// The assembly reference to add.
+ /// The assembly references to add.
/// </summary>
[Required]
- public string Reference { get; set; }
+ public ITaskItem[] References { get; set; }
- const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";
public override bool Execute() {
- foreach (var project in Projects) {
- Log.LogMessage(MessageImportance.Normal, "Changing P2P references to assembly references in \"{0}\".", project.ItemSpec);
+ if (this.ProjectReferences.Length != this.References.Length) {
+ this.Log.LogError("ProjectReferences and References arrays do not have matching lengths.");
+ }
+ foreach (var project in Projects) {
Project doc = new Project();
doc.Load(project.ItemSpec);
-
- var projectReference = doc.EvaluatedItems.OfType<BuildItem>().Where(
- item => item.Name == "ProjectReference" && item.Include == ProjectReference).Single();
- doc.RemoveItem(projectReference);
- var newReference = doc.AddNewItem("Reference", Path.GetFileNameWithoutExtension(Reference), true);
- newReference.SetMetadata("HintPath", Reference);
+ var projectReferences = doc.EvaluatedItems.OfType<BuildItem>().Where(item => item.Name == "ProjectReference");
+ var matchingReferences = from reference in projectReferences
+ join refToRemove in this.ProjectReferences on reference.Include equals refToRemove.ItemSpec
+ let addIndex = Array.IndexOf(this.ProjectReferences, refToRemove)
+ select new { Remove = reference, Add = this.References[addIndex] };
+ foreach (var matchingReference in matchingReferences) {
+ this.Log.LogMessage("Removing project reference to \"{0}\" from \"{1}\".", matchingReference.Remove.Include, project.ItemSpec);
+ doc.RemoveItem(matchingReference.Remove);
+ if (matchingReference.Add.ItemSpec != "REMOVE") {
+ this.Log.LogMessage("Adding assembly reference to \"{0}\" to \"{1}\".", matchingReference.Add.ItemSpec, project.ItemSpec);
+ var newReference = doc.AddNewItem("Reference", Path.GetFileNameWithoutExtension(matchingReference.Add.ItemSpec), true);
+ newReference.SetMetadata("HintPath", matchingReference.Add.ItemSpec);
+ }
+ }
doc.Save(project.ItemSpec);
}
diff --git a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
index e17d8f2..5b097ab 100644
--- a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
+++ b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs
@@ -56,38 +56,51 @@ namespace DotNetOpenAuth.BuildTasks {
for (int i = 0; i < this.SourceFiles.Length; i++) {
string sourcePath = this.SourceFiles[i].ItemSpec;
string destPath = this.DestinationFiles[i].ItemSpec;
- bool skipUnchangedFiles = bool.Parse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles"));
+ bool skipUnchangedFiles;
+ bool.TryParse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles"), out skipUnchangedFiles);
- // We deliberably consider newer destination files to be up-to-date rather than
- // requiring equality because this task modifies the destination file while copying.
- if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) {
- Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath);
- continue;
+ if (!Directory.Exists(Path.GetDirectoryName(destPath))) {
+ Directory.CreateDirectory(Path.GetDirectoryName(destPath));
}
- Log.LogMessage(MessageImportance.Normal, "Transforming \"{0}\" -> \"{1}\"", sourcePath, destPath);
+ if (string.IsNullOrEmpty(this.SourceFiles[i].GetMetadata("BeforeTokens"))) {
+ // this is just a standard copy without token substitution
+ if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) == File.GetLastWriteTimeUtc(destPath)) {
+ Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath);
+ continue;
+ }
- string[] beforeTokens = this.SourceFiles[i].GetMetadata("BeforeTokens").Split(';');
- string[] afterTokens = this.SourceFiles[i].GetMetadata("AfterTokens").Split(';');
- if (beforeTokens.Length != afterTokens.Length) {
- Log.LogError("Unequal number of before and after tokens. Before: \"{0}\". After \"{1}\".", beforeTokens, afterTokens);
- return false;
- }
+ Log.LogMessage(MessageImportance.Normal, "Copying file from \"{0}\" to \"{1}\"", sourcePath, destPath);
+ File.Copy(sourcePath, destPath, true);
+ } else {
+ // We deliberably consider newer destination files to be up-to-date rather than
+ // requiring equality because this task modifies the destination file while copying.
+ if (skipUnchangedFiles && File.GetLastWriteTimeUtc(sourcePath) < File.GetLastWriteTimeUtc(destPath)) {
+ Log.LogMessage(MessageImportance.Low, "Skipping \"{0}\" -> \"{1}\" because the destination is up to date.", sourcePath, destPath);
+ continue;
+ }
+
+ Log.LogMessage(MessageImportance.Normal, "Transforming \"{0}\" -> \"{1}\"", sourcePath, destPath);
- using (StreamReader sr = File.OpenText(sourcePath)) {
- if (!Directory.Exists(Path.GetDirectoryName(destPath))) {
- Directory.CreateDirectory(Path.GetDirectoryName(destPath));
+ string[] beforeTokens = this.SourceFiles[i].GetMetadata("BeforeTokens").Split(';');
+ string[] afterTokens = this.SourceFiles[i].GetMetadata("AfterTokens").Split(';');
+ if (beforeTokens.Length != afterTokens.Length) {
+ Log.LogError("Unequal number of before and after tokens. Before: \"{0}\". After \"{1}\".", beforeTokens, afterTokens);
+ return false;
}
- using (StreamWriter sw = File.CreateText(destPath)) {
- StringBuilder line = new StringBuilder();
- while (!sr.EndOfStream) {
- line.Length = 0;
- line.Append(sr.ReadLine());
- for (int j = 0; j < beforeTokens.Length; j++) {
- line.Replace(beforeTokens[j], afterTokens[j]);
- }
- sw.WriteLine(line);
+ using (StreamReader sr = File.OpenText(sourcePath)) {
+ using (StreamWriter sw = File.CreateText(destPath)) {
+ StringBuilder line = new StringBuilder();
+ while (!sr.EndOfStream) {
+ line.Length = 0;
+ line.Append(sr.ReadLine());
+ for (int j = 0; j < beforeTokens.Length; j++) {
+ line.Replace(beforeTokens[j], afterTokens[j]);
+ }
+
+ sw.WriteLine(line);
+ }
}
}
}
diff --git a/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs b/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs
index 0162c16..f49c9b1 100644
--- a/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs
+++ b/src/DotNetOpenAuth.BuildTasks/DiscoverProjectTemplates.cs
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.BuildTasks {
using Microsoft.Build.Utilities;
public class DiscoverProjectTemplates : Task {
+ [Required]
public ITaskItem[] TopLevelTemplates { get; set; }
[Output]
diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
index 5de32e7..365bec5 100644
--- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
+++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -12,6 +12,21 @@
<AssemblyName>DotNetOpenAuth.BuildTasks</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -48,6 +63,7 @@
</CodeContractsBaseLineFile>
<CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -56,6 +72,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build.Engine" />
@@ -89,15 +106,20 @@
<Compile Include="CreateWebApplication.cs" />
<Compile Include="DeleteWebApplication.cs" />
<Compile Include="DiscoverProjectTemplates.cs" />
+ <Compile Include="DowngradeProjects.cs" />
<Compile Include="ECMAScriptPacker.cs" />
<Compile Include="FilterItems.cs" />
<Compile Include="FixupReferenceHintPaths.cs" />
<Compile Include="FixupShippingToolSamples.cs" />
+ <Compile Include="HardLinkCopy.cs" />
<Compile Include="MergeProjectWithVSTemplate.cs" />
<Compile Include="GetBuildVersion.cs" />
<Compile Include="CheckAdminRights.cs" />
<Compile Include="JsPack.cs" />
+ <Compile Include="NativeMethods.cs" />
<Compile Include="ParseMaster.cs" />
+ <Compile Include="PathSegment.cs" />
+ <Compile Include="Publicize.cs" />
<Compile Include="Purge.cs" />
<Compile Include="ReSignDelaySignedAssemblies.cs" />
<Compile Include="SetEnvironmentVariable.cs" />
@@ -110,6 +132,7 @@
<DependentUpon>TaskStrings.resx</DependentUpon>
</Compile>
<Compile Include="Trim.cs" />
+ <Compile Include="Utilities.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="TaskStrings.resx">
@@ -117,6 +140,23 @@
<LastGenOutput>TaskStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln
index fca41e8..f3e3982 100644
--- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln
+++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln
@@ -1,16 +1,27 @@

-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}"
-EndProject
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABBE14A3-0404-4123-9093-E598C3DD3E9B}"
ProjectSection(SolutionItems) = preProject
..\..\build.proj = ..\..\build.proj
+ ..\..\doc\doc.proj = ..\..\doc\doc.proj
+ ..\..\tools\DotNetOpenAuth.automated.props = ..\..\tools\DotNetOpenAuth.automated.props
+ ..\..\tools\DotNetOpenAuth.automated.targets = ..\..\tools\DotNetOpenAuth.automated.targets
..\..\lib\DotNetOpenAuth.BuildTasks.targets = ..\..\lib\DotNetOpenAuth.BuildTasks.targets
..\..\tools\DotNetOpenAuth.Common.Settings.targets = ..\..\tools\DotNetOpenAuth.Common.Settings.targets
+ ..\..\tools\DotNetOpenAuth.props = ..\..\tools\DotNetOpenAuth.props
+ ..\..\tools\DotNetOpenAuth.targets = ..\..\tools\DotNetOpenAuth.targets
..\..\tools\DotNetOpenAuth.Versioning.targets = ..\..\tools\DotNetOpenAuth.Versioning.targets
+ ..\..\tools\drop.proj = ..\..\tools\drop.proj
+ ..\..\projecttemplates\projecttemplates.proj = ..\..\projecttemplates\projecttemplates.proj
+ ..\..\samples\Samples.proj = ..\..\samples\Samples.proj
+ ..\..\samples\tools.proj = ..\..\samples\tools.proj
+ ..\..\vsi\vsi.proj = ..\..\vsi\vsi.proj
+ ..\..\vsix\vsix.proj = ..\..\vsix\vsix.proj
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
diff --git a/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs b/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs
new file mode 100644
index 0000000..645522d
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/DowngradeProjects.cs
@@ -0,0 +1,110 @@
+//-----------------------------------------------------------------------
+// <copyright file="DowngradeProjects.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Microsoft.Build.BuildEngine;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+
+ /// <summary>
+ /// Downgrades Visual Studio 2010 solutions and projects so that they load in Visual Studio 2008.
+ /// </summary>
+ public class DowngradeProjects : Task {
+ /// <summary>
+ /// Gets or sets the projects and solutions to downgrade.
+ /// </summary>
+ [Required]
+ public ITaskItem[] Projects { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether ASP.NET MVC 2 projects are downgraded to MVC 1.0.
+ /// </summary>
+ public bool DowngradeMvc2ToMvc1 { get; set; }
+
+ /// <summary>
+ /// Executes this instance.
+ /// </summary>
+ public override bool Execute() {
+ foreach (ITaskItem taskItem in this.Projects) {
+ switch (GetClassification(taskItem)) {
+ case ProjectClassification.VS2010Project:
+ this.Log.LogMessage(MessageImportance.Low, "Downgrading project \"{0}\".", taskItem.ItemSpec);
+ Project project = new Project();
+ project.Load(taskItem.ItemSpec);
+ project.DefaultToolsVersion = "3.5";
+
+ if (this.DowngradeMvc2ToMvc1) {
+ string projectTypeGuids = project.GetEvaluatedProperty("ProjectTypeGuids");
+ if (!string.IsNullOrEmpty(projectTypeGuids)) {
+ projectTypeGuids = projectTypeGuids.Replace("{F85E285D-A4E0-4152-9332-AB1D724D3325}", "{603c0e0b-db56-11dc-be95-000d561079b0}");
+ project.SetProperty("ProjectTypeGuids", projectTypeGuids);
+ }
+ }
+
+ // Web projects usually have an import that includes these substrings
+ foreach (Import import in project.Imports) {
+ import.ProjectPath = import.ProjectPath
+ .Replace("$(MSBuildExtensionsPath32)", "$(MSBuildExtensionsPath)")
+ .Replace("VisualStudio\\v10.0", "VisualStudio\\v9.0");
+ }
+
+ // VS2010 won't let you have a System.Core reference, but VS2008 requires it.
+ BuildItemGroup references = project.GetEvaluatedItemsByName("Reference");
+ if (!references.Cast<BuildItem>().Any(item => item.FinalItemSpec.StartsWith("System.Core", StringComparison.OrdinalIgnoreCase))) {
+ project.AddNewItem("Reference", "System.Core");
+ }
+
+ project.Save(taskItem.ItemSpec);
+ break;
+ case ProjectClassification.VS2010Solution:
+ this.Log.LogMessage(MessageImportance.Low, "Downgrading solution \"{0}\".", taskItem.ItemSpec);
+ string[] contents = File.ReadAllLines(taskItem.ItemSpec);
+ if (contents[1] != "Microsoft Visual Studio Solution File, Format Version 11.00" ||
+ contents[2] != "# Visual Studio 2010") {
+ this.Log.LogError("Unrecognized solution file header in \"{0}\".", taskItem.ItemSpec);
+ break;
+ }
+
+ contents[1] = "Microsoft Visual Studio Solution File, Format Version 10.00";
+ contents[2] = "# Visual Studio 2008";
+
+ for (int i = 3; i < contents.Length; i++) {
+ contents[i] = contents[i].Replace("TargetFrameworkMoniker = \".NETFramework,Version%3Dv", "TargetFramework = \"");
+ }
+
+ File.WriteAllLines(taskItem.ItemSpec, contents);
+ break;
+ default:
+ this.Log.LogWarning("Unrecognized project type for \"{0}\".", taskItem.ItemSpec);
+ break;
+ }
+ }
+
+ return !this.Log.HasLoggedErrors;
+ }
+
+ private static ProjectClassification GetClassification(ITaskItem taskItem) {
+ if (Path.GetExtension(taskItem.ItemSpec).EndsWith("proj", StringComparison.OrdinalIgnoreCase)) {
+ return ProjectClassification.VS2010Project;
+ } else if (Path.GetExtension(taskItem.ItemSpec).Equals(".sln", StringComparison.OrdinalIgnoreCase)) {
+ return ProjectClassification.VS2010Solution;
+ } else {
+ return ProjectClassification.Unrecognized;
+ }
+ }
+
+ private enum ProjectClassification {
+ VS2010Project,
+ VS2010Solution,
+ Unrecognized,
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs b/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs
index 13a4b8f..babaab3 100644
--- a/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs
+++ b/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs
@@ -40,7 +40,13 @@ namespace DotNetOpenAuth.BuildTasks {
// Figure out what the assembly names are of the references that are available.
AssemblyName[] availableReferences = new AssemblyName[this.References.Length];
for (int i = 0; i < this.References.Length; i++) {
- availableReferences[i] = AssemblyName.GetAssemblyName(this.References[i].ItemSpec);
+ if (File.Exists(this.References[i].ItemSpec)) {
+ availableReferences[i] = AssemblyName.GetAssemblyName(this.References[i].ItemSpec);
+ } else {
+ availableReferences[i] = new AssemblyName(Path.GetFileNameWithoutExtension(this.References[i].ItemSpec)) {
+ CodeBase = this.References[i].GetMetadata("FullPath"),
+ };
+ }
}
foreach (var projectTaskItem in this.Projects) {
diff --git a/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs b/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs
index 92b0235..6c71740 100644
--- a/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs
+++ b/src/DotNetOpenAuth.BuildTasks/FixupShippingToolSamples.cs
@@ -6,13 +6,14 @@
namespace DotNetOpenAuth.BuildTasks {
using System;
+ using System.Collections;
using System.Collections.Generic;
+ using System.IO;
using System.Linq;
using System.Text;
- using Microsoft.Build.Utilities;
- using Microsoft.Build.Framework;
- using System.IO;
using Microsoft.Build.BuildEngine;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
/// <summary>
/// Removes imports that only apply when a shipping tool sample builds as part of
@@ -22,6 +23,10 @@ namespace DotNetOpenAuth.BuildTasks {
[Required]
public ITaskItem[] Projects { get; set; }
+ public string[] RemoveImportsStartingWith { get; set; }
+
+ public ITaskItem[] AddReferences { get; set; }
+
/// <summary>
/// Executes this instance.
/// </summary>
@@ -34,10 +39,21 @@ namespace DotNetOpenAuth.BuildTasks {
Uri projectUri = new Uri(projectTaskItem.GetMetadata("FullPath"));
project.Load(projectTaskItem.ItemSpec, ProjectLoadSettings.IgnoreMissingImports);
- project.Imports.Cast<Import>()
- .Where(import => import.ProjectPath.StartsWith(@"..\..\tools\", StringComparison.OrdinalIgnoreCase))
- .ToList()
- .ForEach(import => project.Imports.RemoveImport(import));
+ if (this.RemoveImportsStartingWith != null && this.RemoveImportsStartingWith.Length > 0) {
+ project.Imports.Cast<Import>()
+ .Where(import => this.RemoveImportsStartingWith.Any(start => import.ProjectPath.StartsWith(start, StringComparison.OrdinalIgnoreCase)))
+ .ToList()
+ .ForEach(import => project.Imports.RemoveImport(import));
+ }
+
+ if (this.AddReferences != null) {
+ foreach (var reference in this.AddReferences) {
+ BuildItem item = project.AddNewItem("Reference", reference.ItemSpec);
+ foreach (DictionaryEntry metadata in reference.CloneCustomMetadata()) {
+ item.SetMetadata((string)metadata.Key, (string)metadata.Value);
+ }
+ }
+ }
project.Save(projectTaskItem.ItemSpec);
}
diff --git a/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs b/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs
new file mode 100644
index 0000000..af2d1d0
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/HardLinkCopy.cs
@@ -0,0 +1,61 @@
+//-----------------------------------------------------------------------
+// <copyright file="HardLinkCopy.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+ using System.IO;
+
+ public class HardLinkCopy : Task {
+ [Required]
+ public ITaskItem[] SourceFiles { get; set; }
+
+ [Required]
+ public ITaskItem[] DestinationFiles { get; set; }
+
+ /// <summary>
+ /// Executes this instance.
+ /// </summary>
+ public override bool Execute() {
+ if (this.SourceFiles.Length != this.DestinationFiles.Length) {
+ this.Log.LogError("SourceFiles has {0} elements and DestinationFiles has {1} elements.", this.SourceFiles.Length, this.DestinationFiles.Length);
+ return false;
+ }
+
+ for (int i = 0; i < this.SourceFiles.Length; i++) {
+ bool hardLink;
+ bool.TryParse(this.DestinationFiles[i].GetMetadata("HardLink"), out hardLink);
+ string sourceFile = this.SourceFiles[i].ItemSpec;
+ string destinationFile = this.DestinationFiles[i].ItemSpec;
+ this.Log.LogMessage(
+ MessageImportance.Low,
+ "Copying {0} -> {1}{2}.",
+ sourceFile,
+ destinationFile,
+ hardLink ? " as hard link" : string.Empty);
+
+ if (!Directory.Exists(Path.GetDirectoryName(destinationFile))) {
+ Directory.CreateDirectory(Path.GetDirectoryName(destinationFile));
+ }
+
+ if (hardLink) {
+ if (File.Exists(destinationFile)) {
+ File.Delete(destinationFile);
+ }
+ NativeMethods.CreateHardLink(sourceFile, destinationFile);
+ } else {
+ File.Copy(sourceFile, destinationFile, true);
+ }
+ }
+
+ return !this.Log.HasLoggedErrors;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs
index 1a8a17d..d162cd6 100644
--- a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs
+++ b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs
@@ -7,18 +7,27 @@
namespace DotNetOpenAuth.BuildTasks {
using System;
using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.IO;
using System.Linq;
using System.Text;
- using Microsoft.Build.Framework;
- using Microsoft.Build.Utilities;
using System.Xml.Linq;
- using System.IO;
using Microsoft.Build.BuildEngine;
- using System.Diagnostics.Contracts;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
public class MergeProjectWithVSTemplate : Task {
internal const string VSTemplateNamespace = "http://schemas.microsoft.com/developer/vstemplate/2005";
+ internal const string VsixNamespace = "http://schemas.microsoft.com/developer/vsx-schema/2010";
+
+ /// <summary>
+ /// A dictionary where the key is the project name and the value is the path contribution.
+ /// </summary>
+ private Dictionary<string, string> vsixContributionToPath = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
[Required]
public string[] ProjectItemTypes { get; set; }
@@ -26,13 +35,44 @@ namespace DotNetOpenAuth.BuildTasks {
public string[] ReplaceParametersExtensions { get; set; }
[Required]
- public ITaskItem[] Templates { get; set; }
+ public ITaskItem[] SourceTemplates { get; set; }
+
+ [Required]
+ public ITaskItem[] SourceProjects { get; set; }
+
+ [Required]
+ public ITaskItem[] DestinationTemplates { get; set; }
+
+ public ITaskItem[] SourcePathExceptions { get; set; }
+
+ /// <summary>
+ /// Gets or sets the maximum length a project item's relative path should
+ /// be limited to, artificially renaming them as necessary.
+ /// </summary>
+ /// <value>Use 0 to disable the renaming feature.</value>
+ public int MaximumRelativePathLength { get; set; }
+
+ /// <summary>
+ /// Gets or sets the project item paths from the source project to copy to the destination location.
+ /// </summary>
+ [Output]
+ public ITaskItem[] ProjectItems { get; set; }
/// <summary>
/// Executes this instance.
/// </summary>
public override bool Execute() {
- foreach(ITaskItem sourceTemplateTaskItem in this.Templates) {
+ if (this.DestinationTemplates.Length != this.SourceTemplates.Length) {
+ this.Log.LogError("SourceTemplates array has length {0} while DestinationTemplates array has length {1}, but must equal.", this.SourceTemplates.Length, this.DestinationTemplates.Length);
+ }
+ if (this.SourceProjects.Length != this.SourceTemplates.Length) {
+ this.Log.LogError("SourceTemplates array has length {0} while SourceProjects array has length {1}, but must equal.", this.SourceTemplates.Length, this.SourceProjects.Length);
+ }
+
+ var projectItemsToCopy = new List<ITaskItem>();
+
+ for (int iTemplate = 0; iTemplate < this.SourceTemplates.Length; iTemplate++) {
+ ITaskItem sourceTemplateTaskItem = this.SourceTemplates[iTemplate];
var template = XElement.Load(sourceTemplateTaskItem.ItemSpec);
var templateContentElement = template.Element(XName.Get("TemplateContent", VSTemplateNamespace));
var projectElement = templateContentElement.Element(XName.Get("Project", VSTemplateNamespace));
@@ -41,37 +81,65 @@ namespace DotNetOpenAuth.BuildTasks {
continue;
}
- var projectPath = Path.Combine(Path.GetDirectoryName(sourceTemplateTaskItem.ItemSpec), projectElement.Attribute("File").Value);
+ var projectPath = this.SourceProjects[iTemplate].ItemSpec;
+ var projectDirectory = Path.GetDirectoryName(Path.Combine(Path.GetDirectoryName(sourceTemplateTaskItem.GetMetadata("FullPath")), projectElement.Attribute("File").Value));
Log.LogMessage("Merging project \"{0}\" with \"{1}\".", projectPath, sourceTemplateTaskItem.ItemSpec);
var sourceProject = new Project();
sourceProject.Load(projectPath);
+ var projectItems = sourceProject.EvaluatedItems.Cast<BuildItem>().Where(item => this.ProjectItemTypes.Contains(item.Name));
+
+ // Figure out where every project item is in source, and where it will go in the destination,
+ // taking into account a given maximum path length that may require that we shorten the path.
+ PathSegment root = new PathSegment();
+ root.Add(projectItems.Select(item => item.Include));
+ root.EnsureSelfAndChildrenNoLongerThan(this.MaximumRelativePathLength);
// Collect the project items from the project that are appropriate
// to include in the .vstemplate file.
- var itemsByFolder = from item in sourceProject.EvaluatedItems.Cast<BuildItem>()
- where this.ProjectItemTypes.Contains(item.Name)
- orderby item.Include
- group item by Path.GetDirectoryName(item.Include);
- foreach (var folder in itemsByFolder) {
- XElement parentNode = FindOrCreateParent(folder.Key, projectElement);
-
- foreach (var item in folder) {
- bool replaceParameters = this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.Include));
+ foreach (var folder in root.SelfAndDescendents.Where(path => !path.IsLeaf && path.LeafChildren.Any())) {
+ XElement parentNode = projectElement;
+ parentNode = FindOrCreateParent(folder.CurrentPath, projectElement);
+ if (folder.NameChanged) {
+ parentNode.SetAttributeValue("TargetFolderName", folder.OriginalName);
+ }
+
+ foreach (var item in folder.LeafChildren) {
var itemName = XName.Get("ProjectItem", VSTemplateNamespace);
- var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.Include), StringComparison.OrdinalIgnoreCase));
+ // The project item MAY be hard-coded in the .vstemplate file, under the original name.
+ var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.OriginalName), StringComparison.OrdinalIgnoreCase));
if (projectItem == null) {
- projectItem = new XElement(itemName, Path.GetFileName(item.Include));
+ projectItem = new XElement(itemName, item.CurrentName);
parentNode.Add(projectItem);
}
- if (replaceParameters) {
+ if (item.NameChanged) {
+ projectItem.Value = item.CurrentName; // set Value in case it was a hard-coded item in the .vstemplate file.
+ projectItem.SetAttributeValue("TargetFileName", item.OriginalName);
+ }
+ if (this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.OriginalPath))) {
projectItem.SetAttributeValue("ReplaceParameters", "true");
}
}
}
- template.Save(sourceTemplateTaskItem.ItemSpec);
+ template.Save(this.DestinationTemplates[iTemplate].ItemSpec);
+ foreach (var pair in root.LeafDescendents) {
+ TaskItem item = new TaskItem(Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath));
+ string apparentSource = Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath);
+ var sourcePathException = this.SourcePathExceptions.FirstOrDefault(ex => string.Equals(ex.ItemSpec, apparentSource));
+ if (sourcePathException != null) {
+ item.SetMetadata("SourceFullPath", sourcePathException.GetMetadata("ActualSource"));
+ } else {
+ item.SetMetadata("SourceFullPath", Path.GetFullPath(apparentSource));
+ }
+ item.SetMetadata("DestinationFullPath", Path.GetFullPath(Path.Combine(Path.GetDirectoryName(this.DestinationTemplates[iTemplate].ItemSpec), pair.CurrentPath)));
+ item.SetMetadata("RecursiveDir", Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec));
+ item.SetMetadata("Transform", this.ReplaceParametersExtensions.Contains(Path.GetExtension(pair.OriginalName)) ? "true" : "false");
+ projectItemsToCopy.Add(item);
+ }
}
+ this.ProjectItems = projectItemsToCopy.ToArray();
+
return !Log.HasLoggedErrors;
}
diff --git a/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs b/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs
new file mode 100644
index 0000000..26de3a4
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/NativeMethods.cs
@@ -0,0 +1,18 @@
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Runtime.InteropServices;
+
+ internal static class NativeMethods {
+ [DllImport("kernel32", SetLastError = true)]
+ private static extern bool CreateHardLink(string newFileName, string existingFileName, IntPtr securityAttributes);
+
+ internal static void CreateHardLink(string existingFileName, string newFileName) {
+ if (!CreateHardLink(newFileName, existingFileName, IntPtr.Zero)) {
+ Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/PathSegment.cs b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs
new file mode 100644
index 0000000..56655ff
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs
@@ -0,0 +1,321 @@
+//-----------------------------------------------------------------------
+// <copyright file="PathSegment.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+
+ internal class PathSegment {
+ private const float ParentChildResizeThreshold = 0.30f;
+ private readonly PathSegment parent;
+ private readonly string originalName;
+ private string currentName;
+ private bool minimized;
+ private static readonly string[] ReservedFileNames = "CON PRN AUX CLOCK$ NUL COM0 COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8 COM9 LPT0 LPT1 LPT2 LPT3 LPT4 LPT5 LPT6 LPT7 LPT8 LPT9".Split(' ');
+
+ internal PathSegment() {
+ this.currentName = string.Empty;
+ this.originalName = string.Empty;
+ this.minimized = true;
+ this.Children = new Collection<PathSegment>();
+ }
+
+ private PathSegment(string originalName, PathSegment parent)
+ : this() {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalName));
+ Contract.Requires<ArgumentNullException>(parent != null);
+ this.currentName = this.originalName = originalName;
+ this.parent = parent;
+ this.minimized = false;
+ }
+
+ internal string OriginalPath {
+ get {
+ if (this.parent != null) {
+ return Path.Combine(this.parent.OriginalPath, this.originalName);
+ } else {
+ return this.originalName;
+ }
+ }
+ }
+
+ internal string CurrentPath {
+ get {
+ if (this.parent != null) {
+ return Path.Combine(this.parent.CurrentPath, this.currentName);
+ } else {
+ return this.currentName;
+ }
+ }
+ }
+
+ internal string CurrentName {
+ get { return this.currentName; }
+ }
+
+ internal string OriginalName {
+ get { return this.originalName; }
+ }
+
+ private int SegmentCount {
+ get {
+ int parents = this.parent != null ? this.parent.SegmentCount : 0;
+ return parents + 1;
+ }
+ }
+
+ internal int FullLength {
+ get {
+ if (this.parent != null) {
+ int parentLength = this.parent.FullLength;
+ if (parentLength > 0) {
+ parentLength++; // allow for an in between slash
+ }
+ return parentLength + this.currentName.Length;
+ } else {
+ return this.currentName.Length;
+ }
+ }
+ }
+
+ internal bool NameChanged {
+ get { return !string.Equals(this.currentName, this.originalName, StringComparison.OrdinalIgnoreCase); }
+ }
+
+ internal bool IsLeaf {
+ get { return this.Children.Count == 0; }
+ }
+
+ internal IEnumerable<PathSegment> Descendents {
+ get {
+ IEnumerable<PathSegment> result = this.Children;
+ foreach (PathSegment child in this.Children) {
+ result = result.Concat(child.Descendents);
+ }
+
+ return result;
+ }
+ }
+
+ internal IEnumerable<PathSegment> Ancestors {
+ get {
+ PathSegment parent = this.parent;
+ while (parent != null) {
+ yield return parent;
+ parent = parent.parent;
+ }
+ }
+ }
+
+ internal IEnumerable<PathSegment> SelfAndDescendents {
+ get {
+ yield return this;
+ foreach (var child in this.Descendents) {
+ yield return child;
+ }
+ }
+ }
+
+ internal IEnumerable<PathSegment> SelfAndAncestors {
+ get {
+ yield return this;
+ foreach (var parent in this.Ancestors) {
+ yield return parent;
+ }
+ }
+ }
+
+ internal IEnumerable<PathSegment> LeafChildren {
+ get { return this.Children.Where(child => child.IsLeaf); }
+ }
+
+ internal IEnumerable<PathSegment> LeafDescendents {
+ get { return this.Descendents.Where(child => child.IsLeaf); }
+ }
+
+ internal IEnumerable<PathSegment> Siblings {
+ get { return this.parent != null ? this.parent.Children : Enumerable.Empty<PathSegment>(); }
+ }
+
+ internal Collection<PathSegment> Children { get; private set; }
+
+ public override string ToString() {
+ string path;
+ if (this.NameChanged) {
+ path = "{" + this.originalName + " => " + this.currentName + "}";
+ } else {
+ path = this.currentName;
+ }
+
+ if (path.Length > 0 && !this.IsLeaf) {
+ path += "\\";
+ }
+
+ if (this.parent != null) {
+ path = parent.ToString() + path;
+ }
+
+ return path;
+ }
+
+ internal PathSegment Add(string originalPath) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath));
+ Contract.Ensures(Contract.Result<PathSegment>() != null);
+ string[] segments = originalPath.Split(Path.DirectorySeparatorChar);
+ return this.Add(segments, 0);
+ }
+
+ internal void Add(IEnumerable<string> originalPaths) {
+ foreach (string path in originalPaths) {
+ this.Add(path);
+ }
+ }
+
+ internal int EnsureSelfAndChildrenNoLongerThan(int maxLength) {
+ Contract.Requires<ArgumentOutOfRangeException>(maxLength > 0, "A path can only have a positive length.");
+ Contract.Requires<ArgumentOutOfRangeException>(this.parent == null || maxLength > this.parent.FullLength + 1, "A child path cannot possibly be made shorter than its parent.");
+ Contract.Ensures(Contract.Result<int>() <= maxLength);
+ const int uniqueBase = 16;
+
+ // Find the items that are too long, and always work on the longest one
+ var longPaths = this.SelfAndDescendents.Where(path => path.FullLength > maxLength).OrderByDescending(path => path.FullLength);
+ PathSegment longPath;
+ while ((longPath = longPaths.FirstOrDefault()) != null) {
+ // Keep working on this one until it's short enough.
+ do {
+ int tooLongBy = longPath.FullLength - maxLength;
+ var longSegments = longPath.SelfAndAncestors.Where(segment => !segment.minimized).OrderByDescending(segment => segment.CurrentName.Length);
+ PathSegment longestSegment = longSegments.FirstOrDefault();
+ if (longestSegment == null) {
+ throw new InvalidOperationException("Unable to shrink path length sufficiently.");
+ }
+ PathSegment secondLongestSegment = longSegments.Skip(1).FirstOrDefault();
+ int shortenByUpTo;
+ if (secondLongestSegment != null) {
+ shortenByUpTo = Math.Min(tooLongBy, Math.Max(1, longestSegment.CurrentName.Length - secondLongestSegment.CurrentName.Length));
+ } else {
+ shortenByUpTo = tooLongBy;
+ }
+ int minimumGuaranteedUniqueLength = Math.Max(1, RoundUp(Math.Log(longestSegment.Siblings.Count(), uniqueBase)));
+ int allowableSegmentLength = Math.Max(minimumGuaranteedUniqueLength, longestSegment.CurrentName.Length - shortenByUpTo);
+ if (allowableSegmentLength >= longestSegment.CurrentName.Length) {
+ // We can't make this segment any shorter.
+ longestSegment.minimized = true;
+ }
+ longestSegment.currentName = longestSegment.CreateUniqueShortFileName(longestSegment.CurrentName, allowableSegmentLength);
+ } while (longPath.FullLength > maxLength);
+ }
+
+ // Return the total length of self or longest child.
+ return this.SelfAndDescendents.Max(c => c.FullLength);
+ }
+
+ internal PathSegment FindByOriginalPath(string originalPath) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath));
+ string[] segments = originalPath.Split(Path.DirectorySeparatorChar);
+ return this.FindByOriginalPath(segments, 0);
+ }
+
+ private string GetUniqueShortName(string preferredPrefix, string preferredSuffix, int allowableLength) {
+ Contract.Requires<ArgumentNullException>(preferredPrefix != null);
+ Contract.Requires<ArgumentNullException>(preferredSuffix != null);
+ Contract.Requires<ArgumentException>(allowableLength > 0);
+ Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
+ Contract.Ensures(Contract.Result<string>().Length <= allowableLength);
+ string candidateName = string.Empty;
+ int i;
+ for (i = -1; candidateName.Length == 0 || ReservedFileNames.Contains(candidateName, StringComparer.OrdinalIgnoreCase) || this.Siblings.Any(child => string.Equals(child.CurrentName, candidateName, StringComparison.OrdinalIgnoreCase)); i++) {
+ string unique = i < 0 ? string.Empty : i.ToString("x");
+ if (allowableLength < unique.Length) {
+ throw new InvalidOperationException("Unable to shorten path sufficiently to fit constraints.");
+ }
+
+ candidateName = unique;
+
+ // Suffix gets higher priority than the prefix, but only if the entire suffix can be appended.
+ if (candidateName.Length + preferredSuffix.Length <= allowableLength) {
+ candidateName += preferredSuffix;
+ }
+
+ // Now prepend as much of the prefix as fits.
+ candidateName = preferredPrefix.Substring(0, Math.Min(allowableLength - candidateName.Length, preferredPrefix.Length)) + candidateName;
+ }
+
+ return candidateName;
+ }
+
+ private static int RoundUp(double value) {
+ int roundedValue = (int)value;
+ if (roundedValue < value) {
+ roundedValue++;
+ }
+
+ return roundedValue;
+ }
+
+ private string CreateUniqueShortFileName(string fileName, int targetLength) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(fileName));
+ Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
+ Contract.Ensures(Contract.Result<string>().Length <= targetLength);
+
+ // The filename may already full within the target length.
+ if (fileName.Length <= targetLength) {
+ return fileName;
+ }
+
+ string preferredPrefix = Path.GetFileNameWithoutExtension(fileName);
+ string preferredSuffix = Path.GetExtension(fileName);
+
+ string shortenedFileName = GetUniqueShortName(preferredPrefix, preferredSuffix, targetLength);
+ return shortenedFileName;
+ }
+
+ private void ShortenThis(int targetLength) {
+ this.currentName = CreateUniqueShortFileName(this.originalName, targetLength);
+ }
+
+ private PathSegment Add(string[] segments, int segmentIndex) {
+ Contract.Requires<ArgumentNullException>(segments != null);
+ Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length);
+ Contract.Ensures(Contract.Result<PathSegment>() != null);
+ var match = this.Children.SingleOrDefault(child => String.Equals(child.originalName, segments[segmentIndex]));
+ if (match == null) {
+ match = new PathSegment(segments[segmentIndex], this);
+ this.Children.Add(match);
+ if (segments.Length == segmentIndex + 1) {
+ return match;
+ }
+ }
+
+ return match.Add(segments, segmentIndex + 1);
+ }
+
+ private PathSegment FindByOriginalPath(string[] segments, int segmentIndex) {
+ Contract.Requires<ArgumentNullException>(segments != null);
+ Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length);
+ if (string.Equals(this.originalName, segments[segmentIndex], StringComparison.OrdinalIgnoreCase)) {
+ if (segmentIndex == segments.Length - 1) {
+ return this;
+ }
+
+ foreach (var child in this.Children) {
+ var match = child.FindByOriginalPath(segments, segmentIndex + 1);
+ if (match != null) {
+ return match;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/Publicize.cs b/src/DotNetOpenAuth.BuildTasks/Publicize.cs
new file mode 100644
index 0000000..f1781a7
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/Publicize.cs
@@ -0,0 +1,97 @@
+//-----------------------------------------------------------------------
+// <copyright file="Publicize.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using Microsoft.Build.BuildEngine;
+ using Microsoft.Build.Utilities;
+ using Microsoft.Build.Framework;
+
+ public class Publicize : ToolTask {
+ [Required]
+ public string MSBuildExtensionsPath { get; set; }
+
+ [Required]
+ public ITaskItem Assembly { get; set; }
+
+ public bool DelaySign { get; set; }
+
+ public string KeyFile { get; set; }
+
+ public bool SkipUnchangedFiles { get; set; }
+
+ [Output]
+ public ITaskItem AccessorAssembly { get; set; }
+
+ /// <summary>
+ /// Generates the full path to tool.
+ /// </summary>
+ /// <returns>An absolute path.</returns>
+ protected override string GenerateFullPathToTool() {
+ string toolPath = Path.Combine(this.MSBuildExtensionsPath, @"Microsoft\VisualStudio\v9.0\TeamTest\Publicize.exe");
+ return toolPath;
+ }
+
+ /// <summary>
+ /// Gets the name of the tool.
+ /// </summary>
+ /// <value>The name of the tool.</value>
+ protected override string ToolName {
+ get { return "Publicize.exe"; }
+ }
+
+ /// <summary>
+ /// Validates the parameters.
+ /// </summary>
+ protected override bool ValidateParameters() {
+ if (!base.ValidateParameters()) {
+ return false;
+ }
+
+ if (this.DelaySign && string.IsNullOrEmpty(this.KeyFile)) {
+ this.Log.LogError("DelaySign=true, but no KeyFile given.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Generates the command line commands.
+ /// </summary>
+ protected override string GenerateCommandLineCommands() {
+ CommandLineBuilder builder = new CommandLineBuilder();
+
+ if (this.DelaySign) {
+ builder.AppendSwitch("/delaysign");
+ }
+
+ builder.AppendSwitchIfNotNull("/keyfile:", this.KeyFile);
+
+ builder.AppendFileNameIfNotNull(this.Assembly);
+
+ return builder.ToString();
+ }
+
+ public override bool Execute() {
+ this.AccessorAssembly = new TaskItem(this.Assembly);
+ this.AccessorAssembly.ItemSpec = Path.Combine(
+ Path.GetDirectoryName(this.AccessorAssembly.ItemSpec),
+ Path.GetFileNameWithoutExtension(this.AccessorAssembly.ItemSpec) + "_Accessor") + Path.GetExtension(this.AccessorAssembly.ItemSpec);
+
+ if (this.SkipUnchangedFiles && File.GetLastWriteTimeUtc(this.Assembly.ItemSpec) < File.GetLastWriteTimeUtc(this.AccessorAssembly.ItemSpec)) {
+ Log.LogMessage(MessageImportance.Low, "Skipping public accessor generation for {0} because {1} is up to date.", this.Assembly.ItemSpec, this.AccessorAssembly.ItemSpec);
+ return true;
+ }
+
+ return base.Execute();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/Purge.cs b/src/DotNetOpenAuth.BuildTasks/Purge.cs
index e19e485..cf1a214 100644
--- a/src/DotNetOpenAuth.BuildTasks/Purge.cs
+++ b/src/DotNetOpenAuth.BuildTasks/Purge.cs
@@ -7,12 +7,12 @@
namespace DotNetOpenAuth.BuildTasks {
using System;
using System.Collections.Generic;
+ using System.IO;
using System.Linq;
using System.Text;
- using Microsoft.Build.Utilities;
- using Microsoft.Build.Framework;
- using System.IO;
using System.Text.RegularExpressions;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
/// <summary>
/// Purges directory trees of all directories and files that are not on a whitelist.
@@ -40,6 +40,7 @@ namespace DotNetOpenAuth.BuildTasks {
/// <summary>
/// Gets or sets the files that should be NOT be purged.
/// </summary>
+ [Required]
public ITaskItem[] IntendedFiles { get; set; }
/// <summary>
@@ -82,7 +83,7 @@ namespace DotNetOpenAuth.BuildTasks {
}
private static string NormalizePath(string path) {
- return Regex.Replace(path, @"\\+", @"\");
+ return Path.GetFullPath(Regex.Replace(path, @"\\+", @"\"));
}
}
}
diff --git a/src/DotNetOpenAuth.BuildTasks/Utilities.cs b/src/DotNetOpenAuth.BuildTasks/Utilities.cs
new file mode 100644
index 0000000..80e1733
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/Utilities.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------
+// <copyright file="Utilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+
+ internal static class Utilities {
+ internal static string SuppressCharacters(string fileName, char[] suppress, char replacement) {
+ Contract.Requires<ArgumentNullException>(fileName != null);
+ Contract.Requires<ArgumentNullException>(suppress != null);
+
+ if (fileName.IndexOfAny(suppress) < 0) {
+ return fileName;
+ }
+
+ StringBuilder builder = new StringBuilder(fileName);
+ foreach (char ch in suppress) {
+ builder.Replace(ch, replacement);
+ }
+
+ return builder.ToString();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/AssemblyTesting.cs b/src/DotNetOpenAuth.Test/AssemblyTesting.cs
index 7659a82..92b08ec 100644
--- a/src/DotNetOpenAuth.Test/AssemblyTesting.cs
+++ b/src/DotNetOpenAuth.Test/AssemblyTesting.cs
@@ -6,12 +6,12 @@
namespace DotNetOpenAuth.Test {
using System.Diagnostics.Contracts;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [SetUpFixture]
public class AssemblyTesting {
- [AssemblyInitialize]
- public static void AssemblyInitialize(TestContext tc) {
+ [SetUp]
+ public static void AssemblyInitialize() {
// Make contract failures become test failures.
Contract.ContractFailed += (sender, e) => {
// For now, we have tests that verify that preconditions throw exceptions.
diff --git a/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs b/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs
index 73aad6d..e423053 100644
--- a/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs
+++ b/src/DotNetOpenAuth.Test/Configuration/SectionTests.cs
@@ -9,11 +9,11 @@ namespace DotNetOpenAuth.Test.Configuration {
using System.Linq;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class SectionTests {
- [TestMethod]
+ [TestCase]
public void UntrustedWebRequest() {
var uwr = DotNetOpenAuthSection.Configuration.Messaging.UntrustedWebRequest;
@@ -29,12 +29,12 @@ namespace DotNetOpenAuth.Test.Configuration {
Assert.IsTrue(uwr.WhitelistHostsRegex.KeysAsStrings.Contains(".+trusted.+"));
}
- [TestMethod]
+ [TestCase]
public void OpenIdMaxAuthenticationTime() {
Assert.AreEqual(TimeSpan.Parse("00:08:17"), DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime);
}
- [TestMethod]
+ [TestCase]
public void OpenIdRelyingParty() {
var rp = DotNetOpenAuthSection.Configuration.OpenId.RelyingParty;
Assert.IsNull(rp.ApplicationStore.CustomType);
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.Configuration {
Assert.IsFalse(rp.SecuritySettings.RequireSsl);
}
- [TestMethod]
+ [TestCase]
public void OpenIdProvider() {
var op = DotNetOpenAuthSection.Configuration.OpenId.Provider;
Assert.IsNull(op.ApplicationStore.CustomType);
diff --git a/src/DotNetOpenAuth.Test/CoordinatorBase.cs b/src/DotNetOpenAuth.Test/CoordinatorBase.cs
index df331f3..f25964c 100644
--- a/src/DotNetOpenAuth.Test/CoordinatorBase.cs
+++ b/src/DotNetOpenAuth.Test/CoordinatorBase.cs
@@ -11,7 +11,7 @@ namespace DotNetOpenAuth.Test {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
internal abstract class CoordinatorBase<T1, T2> {
private Action<T1> party1Action;
@@ -84,7 +84,7 @@ namespace DotNetOpenAuth.Test {
// Use the failing reason of a failing sub-thread as our reason, if anything failed.
if (failingException != null) {
- throw new AssertFailedException("Coordinator thread threw unhandled exception: " + failingException, failingException);
+ throw new AssertionException("Coordinator thread threw unhandled exception: " + failingException, failingException);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index d4997ae..df29b1f 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -1,7 +1,12 @@
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
+ <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)\..\..\</ProjectRoot>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ </PropertyGroup>
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" />
+ <PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}</ProjectGuid>
@@ -9,15 +14,31 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DotNetOpenAuth.Test</RootNamespace>
<AssemblyName>DotNetOpenAuth.Test</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
- <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <OutputPath>..\..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -46,11 +67,11 @@
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
- <OutputPath>..\..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -79,13 +100,10 @@
<CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
<CodeContractsRunInBackground>True</CodeContractsRunInBackground>
<CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\bin\CodeAnalysis\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -117,21 +135,13 @@
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
<CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
- <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\log4net.dll</HintPath>
- </Reference>
- <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\Microsoft.Contracts.dll</HintPath>
- </Reference>
- <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
- <Reference Include="Moq, Version=3.1.416.3, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\Moq.dll</HintPath>
- </Reference>
+ <Reference Include="log4net" />
+ <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
+ <Reference Include="Moq" />
+ <Reference Include="NUnit.Framework"/>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
@@ -185,6 +195,7 @@
<Compile Include="Mocks\InMemoryTokenManager.cs" />
<Compile Include="Mocks\MockHttpRequest.cs" />
<Compile Include="Mocks\MockIdentifier.cs" />
+ <Compile Include="Mocks\MockIdentifierDiscoveryService.cs" />
<Compile Include="Mocks\MockOpenIdExtension.cs" />
<Compile Include="Mocks\MockRealm.cs" />
<Compile Include="Mocks\MockTransformationBindingElement.cs" />
@@ -219,6 +230,8 @@
<Compile Include="Messaging\Bindings\StandardReplayProtectionBindingElementTests.cs" />
<Compile Include="OpenId\ChannelElements\SigningBindingElementTests.cs" />
<Compile Include="OpenId\DiffieHellmanTests.cs" />
+ <Compile Include="OpenId\DiscoveryServices\UriDiscoveryServiceTests.cs" />
+ <Compile Include="OpenId\DiscoveryServices\XriDiscoveryProxyServiceTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchRequestTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchResponseTests.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeExchangeRoundtripTests.cs" />
@@ -255,6 +268,7 @@
<Compile Include="OpenId\OpenIdCoordinator.cs" />
<Compile Include="OpenId\AssociationHandshakeTests.cs" />
<Compile Include="OpenId\OpenIdTestBase.cs" />
+ <Compile Include="OpenId\OpenIdUtilitiesTests.cs" />
<Compile Include="OpenId\Provider\PerformanceTests.cs" />
<Compile Include="OpenId\ProviderEndpointDescriptionTests.cs" />
<Compile Include="OpenId\Provider\AnonymousRequestTests.cs" />
@@ -267,10 +281,11 @@
<Compile Include="OpenId\RelyingParty\NegativeAuthenticationResponseTests.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdTextBoxTests.cs" />
<Compile Include="OpenId\RelyingParty\PositiveAnonymousResponseTests.cs" />
+ <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseSnapshotTests.cs" />
<Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseTests.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyTests.cs" />
<Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettingsTests.cs" />
- <Compile Include="OpenId\RelyingParty\ServiceEndpointTests.cs" />
+ <Compile Include="OpenId\RelyingParty\IdentifierDiscoveryResultTests.cs" />
<Compile Include="OpenId\UriIdentifierTests.cs" />
<Compile Include="OpenId\XriIdentifierTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -287,15 +302,13 @@
<ProjectReference Include="..\DotNetOpenAuth\DotNetOpenAuth.csproj">
<Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project>
<Name>DotNetOpenAuth</Name>
+ <Shadow>true</Shadow>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Logging.config" />
</ItemGroup>
<ItemGroup>
- <Shadow Include="Test References\DotNetOpenAuth.accessor" />
- </ItemGroup>
- <ItemGroup>
<EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html1020.html" />
<EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html10both.html" />
<EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html10del.html" />
@@ -325,8 +338,39 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="OpenId\Discovery\xrdsdiscovery\xrds20dual.xml" />
+ </ItemGroup>
+ <ItemGroup>
<Folder Include="OpenId\UI\" />
</ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
-</Project>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.0">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20provWithEmptyXrds.html" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="OpenId\Discovery\htmldiscovery\html20provWithBadXrds.html" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
+</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
index d7de7a1..b7e04f7 100644
--- a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
+++ b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
@@ -12,11 +12,11 @@ namespace DotNetOpenAuth.Test.Hosting {
using System.Net;
using System.Text;
using DotNetOpenAuth.Test.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture, Category("HostASPNET")]
public class HostingTests : TestBase {
- [TestMethod]
+ [TestCase]
public void AspHostBasicTest() {
try {
using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.Hosting {
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
using (StreamReader sr = new StreamReader(response.GetResponseStream())) {
string content = sr.ReadToEnd();
- StringAssert.Contains(content, "Test home page");
+ StringAssert.Contains("Test home page", content);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/LocalizationTests.cs b/src/DotNetOpenAuth.Test/LocalizationTests.cs
index 50e9a34..4920deb 100644
--- a/src/DotNetOpenAuth.Test/LocalizationTests.cs
+++ b/src/DotNetOpenAuth.Test/LocalizationTests.cs
@@ -8,19 +8,21 @@ namespace DotNetOpenAuth.Test {
using System;
using System.Globalization;
using System.Threading;
+ using System.Web;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// Tests various localized resources work as expected.
/// </summary>
- [TestClass]
- public class LocalizationTests {
+ [TestFixture]
+ public class LocalizationTests : TestBase {
/// <summary>
/// Tests that Serbian localized strings are correctly installed.
/// </summary>
- [TestMethod, ExpectedException(typeof(InvalidOperationException), "Ovaj metod zahteva tekući HttpContext. Kao alternativa, koristite preklopljeni metod koji dozvoljava da se prosledi informacija bez HttpContext-a.")]
+ [TestCase, ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Ovaj metod zahteva tekući HttpContext. Kao alternativa, koristite preklopljeni metod koji dozvoljava da se prosledi informacija bez HttpContext-a.")]
public void Serbian() {
+ HttpContext.Current = null; // our testbase initializes this, but it must be null to throw
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("sr");
ErrorUtilities.VerifyHttpContext();
}
diff --git a/src/DotNetOpenAuth.Test/Logging.config b/src/DotNetOpenAuth.Test/Logging.config
index cd19de2..87da027 100644
--- a/src/DotNetOpenAuth.Test/Logging.config
+++ b/src/DotNetOpenAuth.Test/Logging.config
@@ -30,7 +30,4 @@
<logger name="DotNetOpenAuth.Test">
<level value="Debug" />
</logger>
- <logger name="DotNetOpenAuth.OpenId.ChannelElements.SigningBindingElement">
- <level value="WARN" />
- </logger>
</log4net>
diff --git a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs
index 3cc792b..9ba433d 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardExpirationBindingElementTests.cs
@@ -9,11 +9,11 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class StandardExpirationBindingElementTests : MessagingTestBase {
- [TestMethod]
+ [TestCase]
public void SendSetsTimestamp() {
TestExpiringMessage message = new TestExpiringMessage(MessageTransport.Indirect);
message.Recipient = new Uri("http://localtest");
@@ -24,13 +24,13 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
Assert.IsTrue(DateTime.UtcNow - ((IExpiringProtocolMessage)message).UtcCreationDate < TimeSpan.FromSeconds(3), "The timestamp on the message was not set on send.");
}
- [TestMethod]
+ [TestCase]
public void VerifyGoodTimestampIsAccepted() {
this.Channel = CreateChannel(MessageProtections.Expiration);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
}
- [TestMethod, ExpectedException(typeof(ExpiredMessageException))]
+ [TestCase, ExpectedException(typeof(ExpiredMessageException))]
public void VerifyBadTimestampIsRejected() {
this.Channel = CreateChannel(MessageProtections.Expiration);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow - StandardExpirationBindingElement.MaximumMessageAge - TimeSpan.FromSeconds(1), false);
diff --git a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs
index 14651bc..d8698ce 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Bindings/StandardReplayProtectionBindingElementTests.cs
@@ -15,16 +15,16 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class StandardReplayProtectionBindingElementTests : MessagingTestBase {
private Protocol protocol;
private StandardReplayProtectionBindingElement nonceElement;
private IReplayProtectedProtocolMessage message;
private INonceStore nonceStore;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
/// <summary>
/// Verifies that the generated nonce includes random characters.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RandomCharactersTest() {
Assert.IsNotNull(this.nonceElement.ProcessOutgoingMessage(this.message));
Assert.IsNotNull(this.message.Nonce, "No nonce was set on the message.");
@@ -56,7 +56,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
/// <summary>
/// Verifies that a message is received correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ValidMessageReceivedTest() {
this.message.Nonce = "a";
Assert.IsNotNull(this.nonceElement.ProcessIncomingMessage(this.message));
@@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
/// <summary>
/// Verifies that a message that doesn't have a string of random characters is received correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ValidMessageNoNonceReceivedTest() {
this.message.Nonce = string.Empty;
this.nonceElement.AllowZeroLengthNonce = true;
@@ -75,7 +75,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
/// <summary>
/// Verifies that a message that doesn't have a string of random characters is received correctly.
/// </summary>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void InvalidMessageNoNonceReceivedTest() {
this.message.Nonce = string.Empty;
this.nonceElement.AllowZeroLengthNonce = false;
@@ -85,7 +85,7 @@ namespace DotNetOpenAuth.Test.Messaging.Bindings {
/// <summary>
/// Verifies that a replayed message is rejected.
/// </summary>
- [TestMethod, ExpectedException(typeof(ReplayedMessageException))]
+ [TestCase, ExpectedException(typeof(ReplayedMessageException))]
public void ReplayDetectionTest() {
this.message.Nonce = "a";
Assert.IsNotNull(this.nonceElement.ProcessIncomingMessage(this.message));
diff --git a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
index 7846411..d22c2f7 100644
--- a/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/ChannelTests.cs
@@ -13,23 +13,23 @@ namespace DotNetOpenAuth.Test.Messaging {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ChannelTests : MessagingTestBase {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNull() {
// This bad channel is deliberately constructed to pass null to
// its protected base class' constructor.
new TestBadChannel(true);
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestQueryString() {
this.ParameterizedReceiveTest("GET");
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestForm() {
this.ParameterizedReceiveTest("POST");
}
@@ -38,37 +38,37 @@ namespace DotNetOpenAuth.Test.Messaging {
/// Verifies compliance to OpenID 2.0 section 5.1.1 by verifying the channel
/// will reject messages that come with an unexpected HTTP verb.
/// </summary>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void ReadFromRequestDisallowedHttpMethod() {
var fields = GetStandardTestFields(FieldFill.CompleteBeforeBindings);
fields["GetOnly"] = "true";
this.Channel.ReadFromRequest(CreateHttpRequestInfo("POST", fields));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendNull() {
this.Channel.PrepareResponse(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void SendIndirectedUndirectedMessage() {
IProtocolMessage message = new TestDirectedMessage(MessageTransport.Indirect);
this.Channel.PrepareResponse(message);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void SendDirectedNoRecipientMessage() {
IProtocolMessage message = new TestDirectedMessage(MessageTransport.Indirect);
this.Channel.PrepareResponse(message);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void SendInvalidMessageTransport() {
IProtocolMessage message = new TestDirectedMessage((MessageTransport)100);
this.Channel.PrepareResponse(message);
}
- [TestMethod]
+ [TestCase]
public void SendIndirectMessage301Get() {
TestDirectedMessage message = new TestDirectedMessage(MessageTransport.Indirect);
GetStandardTestMessage(FieldFill.CompleteBeforeBindings, message);
@@ -77,29 +77,29 @@ namespace DotNetOpenAuth.Test.Messaging {
OutgoingWebResponse response = this.Channel.PrepareResponse(message);
Assert.AreEqual(HttpStatusCode.Redirect, response.Status);
- StringAssert.StartsWith(response.Headers[HttpResponseHeader.Location], "http://provider/path");
+ StringAssert.StartsWith("http://provider/path", response.Headers[HttpResponseHeader.Location]);
foreach (var pair in expected) {
string key = MessagingUtilities.EscapeUriDataStringRfc3986(pair.Key);
string value = MessagingUtilities.EscapeUriDataStringRfc3986(pair.Value);
string substring = string.Format("{0}={1}", key, value);
- StringAssert.Contains(response.Headers[HttpResponseHeader.Location], substring);
+ StringAssert.Contains(substring, response.Headers[HttpResponseHeader.Location]);
}
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendIndirectMessage301GetNullMessage() {
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.Create301RedirectResponse(null, new Dictionary<string, string>());
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void SendIndirectMessage301GetEmptyRecipient() {
TestBadChannel badChannel = new TestBadChannel(false);
var message = new TestDirectedMessage(MessageTransport.Indirect);
badChannel.Create301RedirectResponse(message, new Dictionary<string, string>());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendIndirectMessage301GetNullFields() {
TestBadChannel badChannel = new TestBadChannel(false);
var message = new TestDirectedMessage(MessageTransport.Indirect);
@@ -107,7 +107,7 @@ namespace DotNetOpenAuth.Test.Messaging {
badChannel.Create301RedirectResponse(message, null);
}
- [TestMethod]
+ [TestCase]
public void SendIndirectMessageFormPost() {
// We craft a very large message to force fallback to form POST.
// We'll also stick some HTML reserved characters in the string value
@@ -122,29 +122,29 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreEqual(HttpStatusCode.OK, response.Status, "A form redirect should be an HTTP successful response.");
Assert.IsNull(response.Headers[HttpResponseHeader.Location], "There should not be a redirection header in the response.");
string body = response.Body;
- StringAssert.Contains(body, "<form ");
- StringAssert.Contains(body, "action=\"http://provider/path\"");
- StringAssert.Contains(body, "method=\"post\"");
- StringAssert.Contains(body, "<input type=\"hidden\" name=\"age\" value=\"15\" />");
- StringAssert.Contains(body, "<input type=\"hidden\" name=\"Location\" value=\"http://host/path\" />");
- StringAssert.Contains(body, "<input type=\"hidden\" name=\"Name\" value=\"" + HttpUtility.HtmlEncode(message.Name) + "\" />");
- StringAssert.Contains(body, ".submit()", "There should be some javascript to automate form submission.");
+ StringAssert.Contains("<form ", body);
+ StringAssert.Contains("action=\"http://provider/path\"", body);
+ StringAssert.Contains("method=\"post\"", body);
+ StringAssert.Contains("<input type=\"hidden\" name=\"age\" value=\"15\" />", body);
+ StringAssert.Contains("<input type=\"hidden\" name=\"Location\" value=\"http://host/path\" />", body);
+ StringAssert.Contains("<input type=\"hidden\" name=\"Name\" value=\"" + HttpUtility.HtmlEncode(message.Name) + "\" />", body);
+ StringAssert.Contains(".submit()", body, "There should be some javascript to automate form submission.");
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendIndirectMessageFormPostNullMessage() {
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.CreateFormPostResponse(null, new Dictionary<string, string>());
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void SendIndirectMessageFormPostEmptyRecipient() {
TestBadChannel badChannel = new TestBadChannel(false);
var message = new TestDirectedMessage(MessageTransport.Indirect);
badChannel.CreateFormPostResponse(message, new Dictionary<string, string>());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendIndirectMessageFormPostNullFields() {
TestBadChannel badChannel = new TestBadChannel(false);
var message = new TestDirectedMessage(MessageTransport.Indirect);
@@ -159,7 +159,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// Since this is a mock channel that doesn't actually formulate a direct message response,
/// we just check that the right method was called.
/// </remarks>
- [TestMethod, ExpectedException(typeof(NotImplementedException), "SendDirectMessageResponse")]
+ [TestCase, ExpectedException(typeof(NotImplementedException))]
public void SendDirectMessageResponse() {
IProtocolMessage message = new TestDirectedMessage {
Age = 15,
@@ -169,25 +169,25 @@ namespace DotNetOpenAuth.Test.Messaging {
this.Channel.PrepareResponse(message);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SendIndirectMessageNull() {
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.PrepareIndirectResponse(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void ReceiveNull() {
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.Receive(null, null);
}
- [TestMethod]
+ [TestCase]
public void ReceiveUnrecognizedMessage() {
TestBadChannel badChannel = new TestBadChannel(false);
Assert.IsNull(badChannel.Receive(new Dictionary<string, string>(), null));
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestWithContext() {
var fields = GetStandardTestFields(FieldFill.AllRequired);
TestMessage expectedMessage = GetStandardTestMessage(FieldFill.AllRequired);
@@ -195,24 +195,24 @@ namespace DotNetOpenAuth.Test.Messaging {
HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
IProtocolMessage message = this.Channel.ReadFromRequest();
Assert.IsNotNull(message);
- Assert.IsInstanceOfType(message, typeof(TestMessage));
+ Assert.IsInstanceOf<TestMessage>(message);
Assert.AreEqual(expectedMessage.Age, ((TestMessage)message).Age);
}
- [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ [TestCase, ExpectedException(typeof(InvalidOperationException))]
public void ReadFromRequestNoContext() {
HttpContext.Current = null;
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.ReadFromRequest();
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void ReadFromRequestNull() {
TestBadChannel badChannel = new TestBadChannel(false);
badChannel.ReadFromRequest(null);
}
- [TestMethod]
+ [TestCase]
public void SendReplayProtectedMessageSetsNonce() {
TestReplayProtectedMessage message = new TestReplayProtectedMessage(MessageTransport.Indirect);
message.Recipient = new Uri("http://localtest");
@@ -222,33 +222,33 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.IsNotNull(((IReplayProtectedProtocolMessage)message).Nonce);
}
- [TestMethod, ExpectedException(typeof(InvalidSignatureException))]
+ [TestCase, ExpectedException(typeof(InvalidSignatureException))]
public void ReceivedInvalidSignature() {
this.Channel = CreateChannel(MessageProtections.TamperProtection);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, true);
}
- [TestMethod]
+ [TestCase]
public void ReceivedReplayProtectedMessageJustOnce() {
this.Channel = CreateChannel(MessageProtections.ReplayProtection);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
}
- [TestMethod, ExpectedException(typeof(ReplayedMessageException))]
+ [TestCase, ExpectedException(typeof(ReplayedMessageException))]
public void ReceivedReplayProtectedMessageTwice() {
this.Channel = CreateChannel(MessageProtections.ReplayProtection);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
this.ParameterizedReceiveProtectedTest(DateTime.UtcNow, false);
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void MessageExpirationWithoutTamperResistance() {
new TestChannel(
new TestMessageFactory(),
new StandardExpirationBindingElement());
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void TooManyBindingElementsProvidingSameProtection() {
Channel channel = new TestChannel(
new TestMessageFactory(),
@@ -258,7 +258,7 @@ namespace DotNetOpenAuth.Test.Messaging {
accessor.ProcessOutgoingMessage(new TestSignedDirectedMessage());
}
- [TestMethod]
+ [TestCase]
public void BindingElementsOrdering() {
IChannelBindingElement transformA = new MockTransformationBindingElement("a");
IChannelBindingElement transformB = new MockTransformationBindingElement("b");
@@ -282,20 +282,20 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreSame(sign, channel.BindingElements[4]);
}
- [TestMethod, ExpectedException(typeof(UnprotectedMessageException))]
+ [TestCase, ExpectedException(typeof(UnprotectedMessageException))]
public void InsufficientlyProtectedMessageSent() {
var message = new TestSignedDirectedMessage(MessageTransport.Direct);
message.Recipient = new Uri("http://localtest");
this.Channel.PrepareResponse(message);
}
- [TestMethod, ExpectedException(typeof(UnprotectedMessageException))]
+ [TestCase, ExpectedException(typeof(UnprotectedMessageException))]
public void InsufficientlyProtectedMessageReceived() {
this.Channel = CreateChannel(MessageProtections.None, MessageProtections.TamperProtection);
this.ParameterizedReceiveProtectedTest(DateTime.Now, false);
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void IncomingMessageMissingRequiredParameters() {
var fields = GetStandardTestFields(FieldFill.IdentifiableButNotAllRequired);
this.Channel.ReadFromRequest(CreateHttpRequestInfo("GET", fields));
diff --git a/src/DotNetOpenAuth.Test/Messaging/CollectionAssert.cs b/src/DotNetOpenAuth.Test/Messaging/CollectionAssert.cs
index db136f5..506a6b2 100644
--- a/src/DotNetOpenAuth.Test/Messaging/CollectionAssert.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/CollectionAssert.cs
@@ -11,7 +11,7 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
internal class CollectionAssert<T> {
internal static void AreEquivalent(ICollection<T> expected, ICollection<T> actual) {
diff --git a/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs b/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs
index 55f4394..1c9f5a8 100644
--- a/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/EnumerableCacheTests.cs
@@ -11,12 +11,12 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.Collections.ObjectModel;
using System.Linq;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// Tests for cached enumeration.
/// </summary>
- [TestClass]
+ [TestFixture]
public class EnumerableCacheTests {
/// <summary>
/// The number of times the generator method's implementation is started.
@@ -29,20 +29,15 @@ namespace DotNetOpenAuth.Test.Messaging {
private int generatorCompleted;
/// <summary>
- /// Gets or sets the test context.
- /// </summary>
- public TestContext TestContext { get; set; }
-
- /// <summary>
/// Sets up a test.
/// </summary>
- [TestInitialize]
+ [SetUp]
public void Setup() {
this.generatorInvocations = 0;
this.generatorCompleted = 0;
}
- [TestMethod]
+ [TestCase]
public void EnumerableCache() {
// Baseline
var generator = this.NumberGenerator();
@@ -63,7 +58,7 @@ namespace DotNetOpenAuth.Test.Messaging {
CollectionAssert.AreEqual(list1, list4);
}
- [TestMethod]
+ [TestCase]
public void GeneratesOnlyRequiredElements() {
var generator = this.NumberGenerator().CacheGeneratedResults();
Assert.AreEqual(0, this.generatorInvocations);
@@ -72,28 +67,28 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreEqual(0, this.generatorCompleted, "Only taking part of the list should not have completed the generator.");
}
- [TestMethod]
+ [TestCase]
public void PassThruDoubleCache() {
var cache1 = this.NumberGenerator().CacheGeneratedResults();
var cache2 = cache1.CacheGeneratedResults();
Assert.AreSame(cache1, cache2, "Two caches were set up rather than just sharing the first one.");
}
- [TestMethod]
+ [TestCase]
public void PassThruList() {
var list = this.NumberGenerator().ToList();
var cache = list.CacheGeneratedResults();
Assert.AreSame(list, cache);
}
- [TestMethod]
+ [TestCase]
public void PassThruArray() {
var array = this.NumberGenerator().ToArray();
var cache = array.CacheGeneratedResults();
Assert.AreSame(array, cache);
}
- [TestMethod]
+ [TestCase]
public void PassThruCollection() {
var collection = new Collection<int>();
var cache = collection.CacheGeneratedResults();
@@ -103,7 +98,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Tests calling IEnumerator.Current before first call to MoveNext.
/// </summary>
- [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ [TestCase, ExpectedException(typeof(InvalidOperationException))]
public void EnumerableCacheCurrentThrowsBefore() {
var foo = this.NumberGenerator().CacheGeneratedResults().GetEnumerator().Current;
}
@@ -111,7 +106,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Tests calling IEnumerator.Current after MoveNext returns false.
/// </summary>
- [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ [TestCase, ExpectedException(typeof(InvalidOperationException))]
public void EnumerableCacheCurrentThrowsAfter() {
var enumerator = this.NumberGenerator().CacheGeneratedResults().GetEnumerator();
while (enumerator.MoveNext()) {
diff --git a/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs
index 36b6ae7..4408708 100644
--- a/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs
@@ -7,31 +7,31 @@
namespace DotNetOpenAuth.Test.Messaging {
using System;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ErrorUtilitiesTests {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void VerifyArgumentNotNullThrows() {
ErrorUtilities.VerifyArgumentNotNull(null, "someArg");
}
- [TestMethod]
+ [TestCase]
public void VerifyArgumentNotNullDoesNotThrow() {
ErrorUtilities.VerifyArgumentNotNull("hi", "someArg");
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void VerifyNonZeroLengthOnNull() {
ErrorUtilities.VerifyNonZeroLength(null, "someArg");
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void VerifyNonZeroLengthOnEmpty() {
ErrorUtilities.VerifyNonZeroLength(string.Empty, "someArg");
}
- [TestMethod]
+ [TestCase]
public void VerifyNonZeroLengthOnNonEmpty() {
ErrorUtilities.VerifyNonZeroLength("some Value", "someArg");
}
diff --git a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
index fd77746..0085d59 100644
--- a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
@@ -9,17 +9,17 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.Collections.Specialized;
using System.Web;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class HttpRequestInfoTests : TestBase {
- [TestMethod]
+ [TestCase]
public void CtorDefault() {
HttpRequestInfo info = new HttpRequestInfo();
Assert.AreEqual("GET", info.HttpMethod);
}
- [TestMethod]
+ [TestCase]
public void CtorRequest() {
HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b");
////request.Headers["headername"] = "headervalue"; // PlatformNotSupportedException prevents us mocking this up
@@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.Messaging {
}
// All these tests are ineffective because ServerVariables[] cannot be set.
- ////[TestMethod]
+ ////[TestCase]
////public void CtorRequestWithDifferentPublicHttpHost() {
//// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b");
//// request.ServerVariables["HTTP_HOST"] = "publichost";
@@ -44,7 +44,7 @@ namespace DotNetOpenAuth.Test.Messaging {
//// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
////}
- ////[TestMethod]
+ ////[TestCase]
////public void CtorRequestWithDifferentPublicHttpsHost() {
//// HttpRequest request = new HttpRequest("file", "https://someserver?a=b", "a=b");
//// request.ServerVariables["HTTP_HOST"] = "publichost";
@@ -55,7 +55,7 @@ namespace DotNetOpenAuth.Test.Messaging {
//// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
////}
- ////[TestMethod]
+ ////[TestCase]
////public void CtorRequestWithDifferentPublicHostNonstandardPort() {
//// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b");
//// request.ServerVariables["HTTP_HOST"] = "publichost:550";
@@ -66,7 +66,7 @@ namespace DotNetOpenAuth.Test.Messaging {
//// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
////}
- ////[TestMethod]
+ ////[TestCase]
////public void CtorRequestWithDifferentPublicIPv6Host() {
//// HttpRequest request = new HttpRequest("file", "http://[fe80::587e:c6e5:d3aa:657a]:8089/v3.1/", "");
//// request.ServerVariables["HTTP_HOST"] = "[fe80::587e:c6e5:d3aa:657b]:8089";
@@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// Checks that a property dependent on another null property
/// doesn't generate a NullReferenceException.
/// </summary>
- [TestMethod]
+ [TestCase]
public void QueryBeforeSettingUrl() {
HttpRequestInfo info = new HttpRequestInfo();
Assert.IsNull(info.Query);
@@ -89,7 +89,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies that looking up a querystring variable is gracefully handled without a query in the URL.
/// </summary>
- [TestMethod]
+ [TestCase]
public void QueryStringLookupWithoutQuery() {
HttpRequestInfo info = new HttpRequestInfo();
Assert.IsNull(info.QueryString["hi"]);
@@ -98,7 +98,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetPublicFacingUrlSSLForwarder1() {
HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b");
var serverVariables = new NameValueCollection();
@@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST:port
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetPublicFacingUrlSSLForwarder2() {
HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b");
var serverVariables = new NameValueCollection();
@@ -126,7 +126,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies SSL forwarders are correctly handled when they supply just HOST
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetPublicFacingUrlSSLForwarder3() {
HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b");
var serverVariables = new NameValueCollection();
@@ -139,7 +139,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies SSL forwarders are correctly handled when they supply just HOST:port
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetPublicFacingUrlSSLForwarder4() {
HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b");
var serverVariables = new NameValueCollection();
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs
index 481a715..91cccf1 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MessageSerializerTests.cs
@@ -9,30 +9,30 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.Collections.Generic;
using System.Xml;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// Tests for the <see cref="MessageSerializer"/> class.
/// </summary>
- [TestClass()]
+ [TestFixture()]
public class MessageSerializerTests : MessagingTestBase {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SerializeNull() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage));
serializer.Serialize(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void GetInvalidMessageType() {
MessageSerializer.Get(typeof(string));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void GetNullType() {
MessageSerializer.Get(null);
}
- [TestMethod()]
+ [TestCase()]
public void SerializeTest() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage));
var message = GetStandardTestMessage(FieldFill.CompleteBeforeBindings);
@@ -52,13 +52,13 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.IsFalse(actual.ContainsKey("EmptyMember"));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void DeserializeNull() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage));
serializer.Deserialize(null, null);
}
- [TestMethod]
+ [TestCase]
public void DeserializeSimple() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage));
Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal);
@@ -81,7 +81,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// The element sorting rules are first inheritance order, then alphabetical order.
/// This test validates correct behavior on both.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void DeserializeVerifyElementOrdering() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestDerivedMessage));
Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal);
@@ -105,7 +105,7 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreEqual("privateValue", actual.PrivatePropertyAccessor);
}
- [TestMethod]
+ [TestCase]
public void DeserializeWithExtraFields() {
var serializer = MessageSerializer.Get(typeof(Mocks.TestMessage));
Dictionary<string, string> fields = new Dictionary<string, string>(StringComparer.Ordinal);
@@ -122,7 +122,7 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.IsNull(actual.EmptyMember);
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void DeserializeInvalidMessage() {
IProtocolMessage message = new Mocks.TestDirectedMessage();
var serializer = MessageSerializer.Get(message.GetType());
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs
index accb182..72f3359 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MessagingTestBase.cs
@@ -13,7 +13,7 @@ namespace DotNetOpenAuth.Test {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// The base class that all messaging test classes inherit from.
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test {
internal Channel Channel { get; set; }
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -156,7 +156,7 @@ namespace DotNetOpenAuth.Test {
IDirectedProtocolMessage requestMessage = this.Channel.ReadFromRequest(CreateHttpRequestInfo(method, fields));
Assert.IsNotNull(requestMessage);
- Assert.IsInstanceOfType(requestMessage, typeof(TestMessage));
+ Assert.IsInstanceOf<TestMessage>(requestMessage);
TestMessage actualMessage = (TestMessage)requestMessage;
Assert.AreEqual(expectedMessage.Age, actualMessage.Age);
Assert.AreEqual(expectedMessage.Name, actualMessage.Name);
@@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test {
}
IProtocolMessage requestMessage = this.Channel.ReadFromRequest(CreateHttpRequestInfo("GET", fields));
Assert.IsNotNull(requestMessage);
- Assert.IsInstanceOfType(requestMessage, typeof(TestSignedDirectedMessage));
+ Assert.IsInstanceOf<TestSignedDirectedMessage>(requestMessage);
TestSignedDirectedMessage actualMessage = (TestSignedDirectedMessage)requestMessage;
Assert.AreEqual(expectedMessage.Age, actualMessage.Age);
Assert.AreEqual(expectedMessage.Name, actualMessage.Name);
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
index 4fc89a7..2b0e8f9 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
@@ -15,11 +15,11 @@ namespace DotNetOpenAuth.Test.Messaging
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class MessagingUtilitiesTests : TestBase {
- [TestMethod]
+ [TestCase]
public void CreateQueryString() {
var args = new Dictionary<string, string>();
args.Add("a", "b");
@@ -27,17 +27,17 @@ namespace DotNetOpenAuth.Test.Messaging
Assert.AreEqual("a=b&c%2Fd=e%2Ff", MessagingUtilities.CreateQueryString(args));
}
- [TestMethod]
+ [TestCase]
public void CreateQueryStringEmptyCollection() {
Assert.AreEqual(0, MessagingUtilities.CreateQueryString(new Dictionary<string, string>()).Length);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CreateQueryStringNullDictionary() {
MessagingUtilities.CreateQueryString(null);
}
- [TestMethod]
+ [TestCase]
public void AppendQueryArgs() {
UriBuilder uri = new UriBuilder("http://baseline.org/page");
var args = new Dictionary<string, string>();
@@ -51,17 +51,17 @@ namespace DotNetOpenAuth.Test.Messaging
Assert.AreEqual("http://baseline.org/page?a=b&c%2Fd=e%2Ff&g=h", uri.Uri.AbsoluteUri);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void AppendQueryArgsNullUriBuilder() {
MessagingUtilities.AppendQueryArgs(null, new Dictionary<string, string>());
}
- [TestMethod]
+ [TestCase]
public void AppendQueryArgsNullDictionary() {
MessagingUtilities.AppendQueryArgs(new UriBuilder(), null);
}
- [TestMethod]
+ [TestCase]
public void ToDictionary() {
NameValueCollection nvc = new NameValueCollection();
nvc["a"] = "b";
@@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.Messaging
Assert.AreEqual(nvc["c"], actual["c"]);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void ToDictionaryWithNullKey() {
NameValueCollection nvc = new NameValueCollection();
nvc[null] = "a";
@@ -81,7 +81,7 @@ namespace DotNetOpenAuth.Test.Messaging
nvc.ToDictionary(true);
}
- [TestMethod]
+ [TestCase]
public void ToDictionaryWithSkippedNullKey() {
NameValueCollection nvc = new NameValueCollection();
nvc[null] = "a";
@@ -91,27 +91,27 @@ namespace DotNetOpenAuth.Test.Messaging
Assert.AreEqual(nvc["b"], dictionary["b"]);
}
- [TestMethod]
+ [TestCase]
public void ToDictionaryNull() {
Assert.IsNull(MessagingUtilities.ToDictionary(null));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void ApplyHeadersToResponseNullAspNetResponse() {
MessagingUtilities.ApplyHeadersToResponse(new WebHeaderCollection(), (HttpResponse)null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void ApplyHeadersToResponseNullListenerResponse() {
MessagingUtilities.ApplyHeadersToResponse(new WebHeaderCollection(), (HttpListenerResponse)null);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void ApplyHeadersToResponseNullHeaders() {
MessagingUtilities.ApplyHeadersToResponse(null, new HttpResponse(new StringWriter()));
}
- [TestMethod]
+ [TestCase]
public void ApplyHeadersToResponse() {
var headers = new WebHeaderCollection();
headers[HttpResponseHeader.ContentType] = "application/binary";
@@ -128,7 +128,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <remarks>
/// The tests in this method come from http://wiki.oauth.net/TestCases
/// </remarks>
- [TestMethod]
+ [TestCase]
public void EscapeUriDataStringRfc3986Tests() {
Assert.AreEqual("abcABC123", MessagingUtilities.EscapeUriDataStringRfc3986("abcABC123"));
Assert.AreEqual("-._~", MessagingUtilities.EscapeUriDataStringRfc3986("-._~"));
@@ -145,7 +145,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <summary>
/// Verifies the overall format of the multipart POST is correct.
/// </summary>
- [TestMethod]
+ [TestCase]
public void PostMultipart() {
var httpHandler = new TestWebRequestHandler();
bool callbackTriggered = false;
@@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <summary>
/// Verifies proper behavior of GetHttpVerb
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetHttpVerbTest() {
Assert.AreEqual("GET", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.GetRequest));
Assert.AreEqual("POST", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PostRequest));
@@ -192,7 +192,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <summary>
/// Verifies proper behavior of GetHttpVerb on invalid input.
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void GetHttpVerbOutOfRangeTest() {
MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PutRequest | HttpDeliveryMethods.PostRequest);
}
@@ -200,7 +200,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <summary>
/// Verifies proper behavior of GetHttpDeliveryMethod
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetHttpDeliveryMethodTest() {
Assert.AreEqual(HttpDeliveryMethods.GetRequest, MessagingUtilities.GetHttpDeliveryMethod("GET"));
Assert.AreEqual(HttpDeliveryMethods.PostRequest, MessagingUtilities.GetHttpDeliveryMethod("POST"));
@@ -212,7 +212,7 @@ namespace DotNetOpenAuth.Test.Messaging
/// <summary>
/// Verifies proper behavior of GetHttpDeliveryMethod for an unexpected input
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void GetHttpDeliveryMethodOutOfRangeTest() {
MessagingUtilities.GetHttpDeliveryMethod("UNRECOGNIZED");
}
diff --git a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
index 57614ba..08524b2 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
@@ -11,14 +11,14 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.IO;
using System.Net;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class MultipartPostPartTests : TestBase {
/// <summary>
/// Verifies that the Length property matches the length actually serialized.
/// </summary>
- [TestMethod]
+ [TestCase]
public void FormDataSerializeMatchesLength() {
var part = MultipartPostPart.CreateFormPart("a", "b");
VerifyLength(part);
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies that the length property matches the length actually serialized.
/// </summary>
- [TestMethod]
+ [TestCase]
public void FileSerializeMatchesLength() {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension(".txt");
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies file multiparts identify themselves as files and not merely form-data.
/// </summary>
- [TestMethod]
+ [TestCase]
public void FilePartAsFile() {
var part = MultipartPostPart.CreateFormFilePart("somename", "somefile", "plain/text", new MemoryStream());
Assert.AreEqual("file", part.ContentDisposition);
@@ -49,7 +49,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies MultiPartPost sends the right number of bytes.
/// </summary>
- [TestMethod]
+ [TestCase]
public void MultiPartPostAscii() {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension("txt");
@@ -64,7 +64,7 @@ namespace DotNetOpenAuth.Test.Messaging {
/// <summary>
/// Verifies MultiPartPost sends the right number of bytes.
/// </summary>
- [TestMethod]
+ [TestCase]
public void MultiPartPostMultiByteCharacters() {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension("txt");
@@ -94,9 +94,9 @@ namespace DotNetOpenAuth.Test.Messaging {
bool posted = false;
handler.Callback = req => {
foreach (string header in req.Headers) {
- TestContext.WriteLine("{0}: {1}", header, req.Headers[header]);
+ TestUtilities.TestLogger.InfoFormat("{0}: {1}", header, req.Headers[header]);
}
- TestContext.WriteLine(handler.RequestEntityAsString);
+ TestUtilities.TestLogger.InfoFormat(handler.RequestEntityAsString);
Assert.AreEqual(req.ContentLength, handler.RequestEntityStream.Length);
posted = true;
return null;
diff --git a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
index 2923af4..10045de 100644
--- a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs
@@ -9,14 +9,14 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.Net.Mime;
using System.Text;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OutgoingWebResponseTests {
/// <summary>
/// Verifies that setting the Body property correctly converts to a byte stream.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SetBodyToByteStream() {
var response = new OutgoingWebResponse();
string stringValue = "abc";
diff --git a/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs b/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs
index 430b929..c9e3d24 100644
--- a/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/ProtocolExceptionTests.cs
@@ -7,22 +7,22 @@
namespace DotNetOpenAuth.Test.Messaging {
using System;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ProtocolExceptionTests : TestBase {
- [TestMethod]
+ [TestCase]
public void CtorDefault() {
ProtocolException ex = new ProtocolException();
}
- [TestMethod]
+ [TestCase]
public void CtorWithTextMessage() {
ProtocolException ex = new ProtocolException("message");
Assert.AreEqual("message", ex.Message);
}
- [TestMethod]
+ [TestCase]
public void CtorWithTextMessageAndInnerException() {
Exception innerException = new Exception();
ProtocolException ex = new ProtocolException("message", innerException);
@@ -30,14 +30,14 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreSame(innerException, ex.InnerException);
}
- [TestMethod]
+ [TestCase]
public void CtorWithProtocolMessage() {
IProtocolMessage message = new Mocks.TestDirectedMessage();
ProtocolException ex = new ProtocolException("message", message);
Assert.AreSame(message, ex.FaultedMessage);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorWithNullProtocolMessage() {
new ProtocolException("message", (IProtocolMessage)null);
}
diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs
index 76c454a..e57df65 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDescriptionTests.cs
@@ -8,26 +8,26 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
using System;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class MessageDescriptionTests : MessagingTestBase {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullType() {
new MessageDescription(null, new Version(1, 0));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullVersion() {
new MessageDescription(typeof(Mocks.TestMessage), null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorNonMessageType() {
new MessageDescription(typeof(string), new Version(1, 0));
}
- [TestMethod]
+ [TestCase]
public void MultiVersionedMessageTest() {
var v10 = new MessageDescription(typeof(MultiVersionMessage), new Version(1, 0));
var v20 = new MessageDescription(typeof(MultiVersionMessage), new Version(2, 0));
diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs
index b9e7436..9e3f4c5 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessageDictionaryTests.cs
@@ -12,20 +12,20 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
using System.Xml;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class MessageDictionaryTests : MessagingTestBase {
private Mocks.TestMessage message;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
this.message = new Mocks.TestDirectedMessage();
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNull() {
this.MessageDescriptions.GetAccessor(null);
}
@@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.Values
/// </summary>
- [TestMethod]
+ [TestCase]
public void Values() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
Collection<string> expected = new Collection<string> {
@@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.Keys
/// </summary>
- [TestMethod]
+ [TestCase]
public void Keys() {
// We expect that non-nullable value type fields will automatically have keys
// in the dictionary for them.
@@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.Item
/// </summary>
- [TestMethod]
+ [TestCase]
public void Item() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
@@ -103,7 +103,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.IsReadOnly
/// </summary>
- [TestMethod]
+ [TestCase]
public void IsReadOnly() {
ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
Assert.IsFalse(target.IsReadOnly);
@@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.Count
/// </summary>
- [TestMethod]
+ [TestCase]
public void Count() {
ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target;
@@ -124,7 +124,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IEnumerable&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.GetEnumerator
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetEnumerator() {
IEnumerable<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target;
@@ -147,7 +147,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.IsTrue(keysLast == valuesLast && keysLast == actualLast);
}
- [TestMethod]
+ [TestCase]
public void GetEnumeratorUntyped() {
IEnumerable target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetDictionary = (IDictionary<string, string>)target;
@@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.TryGetValue
/// </summary>
- [TestMethod]
+ [TestCase]
public void TryGetValue() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
this.message.Name = "andrew";
@@ -194,7 +194,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.Remove
/// </summary>
- [TestMethod]
+ [TestCase]
public void RemoveTest1() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
this.message.Name = "andrew";
@@ -211,7 +211,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String>.ContainsKey
/// </summary>
- [TestMethod]
+ [TestCase]
public void ContainsKey() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
Assert.IsTrue(target.ContainsKey("age"), "Value type declared element should have a key.");
@@ -225,7 +225,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.IDictionary&lt;System.String,System.String&gt;.Add
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddByKeyAndValue() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
target.Add("extra", "value");
@@ -234,7 +234,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual("Andrew", this.message.Name);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void AddNullValue() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
target.Add("extra", null);
@@ -243,35 +243,35 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.Add
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddByKeyValuePair() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
target.Add(new KeyValuePair<string, string>("extra", "value"));
Assert.IsTrue(target.Contains(new KeyValuePair<string, string>("extra", "value")));
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void AddExtraFieldThatAlreadyExists() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
target.Add("extra", "value");
target.Add("extra", "value");
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void AddDeclaredValueThatAlreadyExists() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
target.Add("Name", "andrew");
target.Add("Name", "andrew");
}
- [TestMethod]
+ [TestCase]
public void DefaultReferenceTypeDeclaredPropertyHasNoKey() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
Assert.IsFalse(target.ContainsKey("Name"), "A null value should result in no key.");
Assert.IsFalse(target.Keys.Contains("Name"), "A null value should result in no key.");
}
- [TestMethod]
+ [TestCase]
public void RemoveStructDeclaredProperty() {
IDictionary<string, string> target = this.MessageDescriptions.GetAccessor(this.message);
this.message.Age = 5;
@@ -284,7 +284,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.Remove
/// </summary>
- [TestMethod]
+ [TestCase]
public void RemoveByKeyValuePair() {
ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
this.message.Name = "Andrew";
@@ -297,7 +297,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.CopyTo
/// </summary>
- [TestMethod]
+ [TestCase]
public void CopyTo() {
ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target;
@@ -314,7 +314,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.Contains
/// </summary>
- [TestMethod]
+ [TestCase]
public void ContainsKeyValuePair() {
ICollection<KeyValuePair<string, string>> target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target;
@@ -330,7 +330,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// A test for System.Collections.Generic.ICollection&lt;System.Collections.Generic.KeyValuePair&lt;System.String,System.String&lt;&lt;.Clear
/// </summary>
- [TestMethod]
+ [TestCase]
public void ClearValues() {
MessageDictionary target = this.MessageDescriptions.GetAccessor(this.message);
IDictionary<string, string> targetAsDictionary = (IDictionary<string, string>)target;
@@ -347,7 +347,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
/// <summary>
/// Verifies that the Clear method throws the expected exception.
/// </summary>
- [TestMethod, ExpectedException(typeof(NotSupportedException))]
+ [TestCase, ExpectedException(typeof(NotSupportedException))]
public void Clear() {
MessageDictionary target = this.MessageDescriptions.GetAccessor(this.message);
target.Clear();
diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
index 19e6a82..66237e7 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
@@ -12,42 +12,47 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class MessagePartTests : MessagingTestBase {
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void OptionalNonNullableStruct() {
this.ParameterizedMessageTypeTest(typeof(MessageWithNonNullableOptionalStruct));
}
- [TestMethod]
+ [TestCase]
public void RequiredNonNullableStruct() {
this.ParameterizedMessageTypeTest(typeof(MessageWithNonNullableRequiredStruct));
}
- [TestMethod]
+ [TestCase]
public void OptionalNullableStruct() {
- this.ParameterizedMessageTypeTest(typeof(MessageWithNullableOptionalStruct));
+ var message = new MessageWithNullableOptionalStruct();
+ var part = this.ParameterizedMessageTypeTest(message.GetType());
+
+ Assert.IsNull(part.GetValue(message));
+ part.SetValue(message, "3");
+ Assert.AreEqual("3", part.GetValue(message));
}
- [TestMethod]
+ [TestCase]
public void RequiredNullableStruct() {
this.ParameterizedMessageTypeTest(typeof(MessageWithNullableRequiredStruct));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullMember() {
new MessagePart(null, new MessagePartAttribute());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullAttribute() {
PropertyInfo field = typeof(MessageWithNullableOptionalStruct).GetProperty("OptionalInt", BindingFlags.NonPublic | BindingFlags.Instance);
new MessagePart(field, null);
}
- [TestMethod]
+ [TestCase]
public void SetValue() {
var message = new MessageWithNonNullableRequiredStruct();
MessagePart part = this.ParameterizedMessageTypeTest(message.GetType());
@@ -55,7 +60,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual(5, message.OptionalInt);
}
- [TestMethod]
+ [TestCase]
public void GetValue() {
var message = new MessageWithNonNullableRequiredStruct();
message.OptionalInt = 8;
@@ -63,7 +68,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual("8", part.GetValue(message));
}
- [TestMethod]
+ [TestCase]
public void Base64Member() {
var message = new MessageWithBase64EncodedString();
message.LastName = "andrew";
@@ -73,7 +78,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual("arnott", message.LastName);
}
- [TestMethod]
+ [TestCase]
public void ConstantFieldMemberValidValues() {
var message = new MessageWithConstantField();
MessagePart part = GetMessagePart(message.GetType(), "ConstantField");
@@ -82,20 +87,20 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual("abc", part.GetValue(message));
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void ConstantFieldMemberInvalidValues() {
var message = new MessageWithConstantField();
MessagePart part = GetMessagePart(message.GetType(), "ConstantField");
part.SetValue(message, "def");
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void NonFieldOrPropertyMember() {
MemberInfo method = typeof(MessageWithNullableOptionalStruct).GetMethod("Equals", BindingFlags.Public | BindingFlags.Instance);
new MessagePart(method, new MessagePartAttribute());
}
- [TestMethod]
+ [TestCase]
public void RequiredMinAndMaxVersions() {
Type messageType = typeof(MessageWithMinAndMaxVersionParts);
FieldInfo newIn2Field = messageType.GetField("NewIn2", BindingFlags.Public | BindingFlags.Instance);
diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/ValueMappingTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/ValueMappingTests.cs
index c4a79b5..60c8bc3 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Reflection/ValueMappingTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/ValueMappingTests.cs
@@ -7,18 +7,18 @@
namespace DotNetOpenAuth.Test.Messaging.Reflection {
using System;
using DotNetOpenAuth.Messaging.Reflection;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ValueMappingTests {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullToString() {
- new ValueMapping(null, str => new object());
+ new ValueMapping(null, null, str => new object());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullToObject() {
- new ValueMapping(obj => obj.ToString(), null);
+ new ValueMapping(obj => obj.ToString(), null, null);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs
index 89d165a..63be45a 100644
--- a/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/ResponseTests.cs
@@ -9,17 +9,17 @@ namespace DotNetOpenAuth.Test.Messaging {
using System.IO;
using System.Web;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ResponseTests : TestBase {
- [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ [TestCase, ExpectedException(typeof(InvalidOperationException))]
public void SendWithoutAspNetContext() {
HttpContext.Current = null;
new OutgoingWebResponse().Send();
}
- [TestMethod]
+ [TestCase]
public void Send() {
StringWriter writer = new StringWriter();
HttpRequest httpRequest = new HttpRequest("file", "http://server", string.Empty);
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
index 16386de..0bb35bc 100644
--- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingChannel.cs
@@ -14,7 +14,7 @@ namespace DotNetOpenAuth.Test.Mocks {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.Test.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
internal class CoordinatingChannel : Channel {
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs
index 0213a33..c18ea33 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs
@@ -83,7 +83,7 @@ namespace DotNetOpenAuth.Test.Mocks {
}
}
- internal void RegisterMockXrdsResponse(ServiceEndpoint endpoint) {
+ internal void RegisterMockXrdsResponse(IdentifierDiscoveryResult endpoint) {
Contract.Requires<ArgumentNullException>(endpoint != null);
string identityUri;
@@ -92,10 +92,10 @@ namespace DotNetOpenAuth.Test.Mocks {
} else {
identityUri = endpoint.UserSuppliedIdentifier ?? endpoint.ClaimedIdentifier;
}
- this.RegisterMockXrdsResponse(new Uri(identityUri), new ServiceEndpoint[] { endpoint });
+ this.RegisterMockXrdsResponse(new Uri(identityUri), new IdentifierDiscoveryResult[] { endpoint });
}
- internal void RegisterMockXrdsResponse(Uri respondingUri, IEnumerable<ServiceEndpoint> endpoints) {
+ internal void RegisterMockXrdsResponse(Uri respondingUri, IEnumerable<IdentifierDiscoveryResult> endpoints) {
Contract.Requires<ArgumentNullException>(endpoints != null);
StringBuilder xrds = new StringBuilder();
@@ -130,12 +130,12 @@ namespace DotNetOpenAuth.Test.Mocks {
this.RegisterMockResponse(respondingUri, ContentTypes.Xrds, xrds.ToString());
}
- internal void RegisterMockXrdsResponse(UriIdentifier directedIdentityAssignedIdentifier, ServiceEndpoint providerEndpoint) {
- ServiceEndpoint identityEndpoint = ServiceEndpoint.CreateForClaimedIdentifier(
+ internal void RegisterMockXrdsResponse(UriIdentifier directedIdentityAssignedIdentifier, IdentifierDiscoveryResult providerEndpoint) {
+ IdentifierDiscoveryResult identityEndpoint = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
directedIdentityAssignedIdentifier,
directedIdentityAssignedIdentifier,
- providerEndpoint.ProviderEndpoint,
- providerEndpoint.ProviderDescription,
+ providerEndpoint.ProviderLocalIdentifier,
+ new ProviderEndpointDescription(providerEndpoint.ProviderEndpoint, providerEndpoint.Capabilities),
10,
10);
this.RegisterMockXrdsResponse(identityEndpoint);
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
index 346dde9..9f032b8 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
@@ -18,13 +18,13 @@ namespace DotNetOpenAuth.Test.Mocks {
/// having a dependency on a hosted web site to actually perform discovery on.
/// </summary>
internal class MockIdentifier : Identifier {
- private IEnumerable<ServiceEndpoint> endpoints;
+ private IEnumerable<IdentifierDiscoveryResult> endpoints;
private MockHttpRequest mockHttpRequest;
private Identifier wrappedIdentifier;
- public MockIdentifier(Identifier wrappedIdentifier, MockHttpRequest mockHttpRequest, IEnumerable<ServiceEndpoint> endpoints)
+ public MockIdentifier(Identifier wrappedIdentifier, MockHttpRequest mockHttpRequest, IEnumerable<IdentifierDiscoveryResult> endpoints)
: base(wrappedIdentifier.OriginalString, false) {
Contract.Requires<ArgumentNullException>(wrappedIdentifier != null);
Contract.Requires<ArgumentNullException>(mockHttpRequest != null);
@@ -39,6 +39,10 @@ namespace DotNetOpenAuth.Test.Mocks {
mockHttpRequest.RegisterMockXrdsResponse(new Uri(wrappedIdentifier.ToString()), endpoints);
}
+ internal IEnumerable<IdentifierDiscoveryResult> DiscoveryEndpoints {
+ get { return this.endpoints; }
+ }
+
public override string ToString() {
return this.wrappedIdentifier.ToString();
}
@@ -51,10 +55,6 @@ namespace DotNetOpenAuth.Test.Mocks {
return this.wrappedIdentifier.GetHashCode();
}
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- return this.endpoints;
- }
-
internal override Identifier TrimFragment() {
return this;
}
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs
new file mode 100644
index 0000000..d74258d
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifierDiscoveryService.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="MockIdentifierDiscoveryService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Mocks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ internal class MockIdentifierDiscoveryService : IIdentifierDiscoveryService {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MockIdentifierDiscoveryService"/> class.
+ /// </summary>
+ public MockIdentifierDiscoveryService() {
+ }
+
+ #region IIdentifierDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ public IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ var mockIdentifier = identifier as MockIdentifier;
+ if (mockIdentifier == null) {
+ abortDiscoveryChain = false;
+ return Enumerable.Empty<IdentifierDiscoveryResult>();
+ }
+
+ abortDiscoveryChain = true;
+ return mockIdentifier.DiscoveryEndpoints;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockReplayProtectionBindingElement.cs b/src/DotNetOpenAuth.Test/Mocks/MockReplayProtectionBindingElement.cs
index 75281e2..96bd40d 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockReplayProtectionBindingElement.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockReplayProtectionBindingElement.cs
@@ -7,7 +7,7 @@
namespace DotNetOpenAuth.Test.Mocks {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
internal class MockReplayProtectionBindingElement : IChannelBindingElement {
private bool messageReceived;
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockTransformationBindingElement.cs b/src/DotNetOpenAuth.Test/Mocks/MockTransformationBindingElement.cs
index e88fe52..1db9c68 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockTransformationBindingElement.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockTransformationBindingElement.cs
@@ -10,7 +10,7 @@ namespace DotNetOpenAuth.Test.Mocks {
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
internal class MockTransformationBindingElement : IChannelBindingElement {
private string transform;
@@ -47,7 +47,7 @@ namespace DotNetOpenAuth.Test.Mocks {
MessageProtections? IChannelBindingElement.ProcessIncomingMessage(IProtocolMessage message) {
var testMessage = message as TestMessage;
if (testMessage != null) {
- StringAssert.StartsWith(testMessage.Name, this.transform);
+ StringAssert.StartsWith(this.transform, testMessage.Name);
testMessage.Name = testMessage.Name.Substring(this.transform.Length);
return MessageProtections.None;
}
diff --git a/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs
index c009a83..5584a7b 100644
--- a/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs
@@ -12,11 +12,11 @@ namespace DotNetOpenAuth.Test.OAuth {
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AppendixScenarios : TestBase {
- [TestMethod]
+ [TestCase]
public void SpecAppendixAExample() {
ServiceProviderDescription serviceDescription = new ServiceProviderDescription() {
RequestTokenEndpoint = new MessageReceivingEndpoint("https://photos.example.net/request_token", HttpDeliveryMethods.PostRequest),
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs
index fcdb5e8..a11c67d 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/HmacSha1SigningBindingElementTests.cs
@@ -8,11 +8,11 @@ namespace DotNetOpenAuth.Test.ChannelElements {
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class HmacSha1SigningBindingElementTests : MessagingTestBase {
- [TestMethod]
+ [TestCase]
public void SignatureTest() {
UnauthorizedTokenRequest message = SigningBindingElementBaseTests.CreateTestRequestTokenMessage(this.MessageDescriptions, null);
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
index b721fb7..c7b9f89 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -19,9 +19,9 @@ namespace DotNetOpenAuth.Test.ChannelElements {
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OAuthChannelTests : TestBase {
private OAuthChannel channel;
private OAuthChannel_Accessor accessor;
@@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
private SigningBindingElementBase signingElement;
private INonceStore nonceStore;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -41,32 +41,32 @@ namespace DotNetOpenAuth.Test.ChannelElements {
this.channel.WebRequestHandler = this.webRequestHandler;
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullSigner() {
new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullStore() {
new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), null, new InMemoryTokenManager(), new TestMessageFactory());
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullTokenManager() {
new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, new TestMessageFactory());
}
- [TestMethod]
+ [TestCase]
public void CtorSimpleConsumer() {
new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager());
}
- [TestMethod]
+ [TestCase]
public void CtorSimpleServiceProvider() {
new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager());
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestAuthorization() {
this.ParameterizedReceiveTest(HttpDeliveryMethods.AuthorizationHeaderRequest);
}
@@ -75,7 +75,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
/// Verifies that the OAuth ReadFromRequest method gathers parameters
/// from the Authorization header, the query string and the entity form data.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ReadFromRequestAuthorizationScattered() {
// Start by creating a standard POST HTTP request.
var fields = new Dictionary<string, string> {
@@ -99,24 +99,24 @@ namespace DotNetOpenAuth.Test.ChannelElements {
IDirectedProtocolMessage requestMessage = this.channel.ReadFromRequest(requestInfo);
Assert.IsNotNull(requestMessage);
- Assert.IsInstanceOfType(requestMessage, typeof(TestMessage));
+ Assert.IsInstanceOf<TestMessage>(requestMessage);
TestMessage testMessage = (TestMessage)requestMessage;
Assert.AreEqual(15, testMessage.Age);
Assert.AreEqual("Andrew", testMessage.Name);
Assert.AreEqual("http://hostb/pathB", testMessage.Location.AbsoluteUri);
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestForm() {
this.ParameterizedReceiveTest(HttpDeliveryMethods.PostRequest);
}
- [TestMethod]
+ [TestCase]
public void ReadFromRequestQueryString() {
this.ParameterizedReceiveTest(HttpDeliveryMethods.GetRequest);
}
- [TestMethod]
+ [TestCase]
public void SendDirectMessageResponse() {
IProtocolMessage message = new TestDirectedMessage {
Age = 15,
@@ -135,7 +135,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.AreEqual("http://hostb/pathB", body["Location"]);
}
- [TestMethod]
+ [TestCase]
public void ReadFromResponse() {
var fields = new Dictionary<string, string> {
{ "age", "15" },
@@ -157,18 +157,18 @@ namespace DotNetOpenAuth.Test.ChannelElements {
}
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void RequestNull() {
this.channel.Request(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void RequestNullRecipient() {
IDirectedProtocolMessage message = new TestDirectedMessage(MessageTransport.Direct);
this.channel.Request(message);
}
- [TestMethod, ExpectedException(typeof(NotSupportedException))]
+ [TestCase, ExpectedException(typeof(NotSupportedException))]
public void RequestBadPreferredScheme() {
TestDirectedMessage message = new TestDirectedMessage(MessageTransport.Direct);
message.Recipient = new Uri("http://localtest");
@@ -176,7 +176,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
this.channel.Request(message);
}
- [TestMethod]
+ [TestCase]
public void RequestUsingAuthorizationHeader() {
this.ParameterizedRequestTest(HttpDeliveryMethods.AuthorizationHeaderRequest);
}
@@ -184,7 +184,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
/// <summary>
/// Verifies that message parts can be distributed to the query, form, and Authorization header.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RequestUsingAuthorizationHeaderScattered() {
TestDirectedMessage request = new TestDirectedMessage(MessageTransport.Direct) {
Age = 15,
@@ -217,17 +217,17 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.AreEqual("appearinform=formish", this.webRequestHandler.RequestEntityAsString);
}
- [TestMethod]
+ [TestCase]
public void RequestUsingGet() {
this.ParameterizedRequestTest(HttpDeliveryMethods.GetRequest);
}
- [TestMethod]
+ [TestCase]
public void RequestUsingPost() {
this.ParameterizedRequestTest(HttpDeliveryMethods.PostRequest);
}
- [TestMethod]
+ [TestCase]
public void RequestUsingHead() {
this.ParameterizedRequestTest(HttpDeliveryMethods.HeadRequest);
}
@@ -235,7 +235,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
/// <summary>
/// Verifies that messages asking for special HTTP status codes get them.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SendDirectMessageResponseHonorsHttpStatusCodes() {
IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired);
OutgoingWebResponse directResponse = this.accessor.PrepareDirectResponse(message);
@@ -349,7 +349,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
IProtocolMessage response = this.channel.Request(request);
Assert.IsNotNull(response);
- Assert.IsInstanceOfType(response, typeof(TestMessage));
+ Assert.IsInstanceOf<TestMessage>(response);
TestMessage responseMessage = (TestMessage)response;
Assert.AreEqual(request.Age, responseMessage.Age);
Assert.AreEqual(request.Name, responseMessage.Name);
@@ -365,7 +365,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
};
IProtocolMessage requestMessage = this.channel.ReadFromRequest(CreateHttpRequestInfo(scheme, fields));
Assert.IsNotNull(requestMessage);
- Assert.IsInstanceOfType(requestMessage, typeof(TestMessage));
+ Assert.IsInstanceOf<TestMessage>(requestMessage);
TestMessage testMessage = (TestMessage)requestMessage;
Assert.AreEqual(15, testMessage.Age);
Assert.AreEqual("Andrew", testMessage.Name);
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs
index 01d51a3..b81eefa 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/PlaintextSigningBindingElementTest.cs
@@ -10,11 +10,11 @@ namespace DotNetOpenAuth.Test.ChannelElements {
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PlaintextSigningBindingElementTest {
- [TestMethod]
+ [TestCase]
public void HttpsSignatureGeneration() {
SigningBindingElementBase target = new PlaintextSigningBindingElement();
target.Channel = new TestChannel();
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.AreEqual("cs&ts", message.Signature);
}
- [TestMethod]
+ [TestCase]
public void HttpsSignatureVerification() {
MessageReceivingEndpoint endpoint = new MessageReceivingEndpoint("https://localtest", HttpDeliveryMethods.GetRequest);
ITamperProtectionChannelBindingElement target = new PlaintextSigningBindingElement();
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.IsNotNull(target.ProcessIncomingMessage(message));
}
- [TestMethod]
+ [TestCase]
public void HttpsSignatureVerificationNotApplicable() {
SigningBindingElementBase target = new PlaintextSigningBindingElement();
target.Channel = new TestChannel();
@@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.AreEqual(MessageProtections.None, target.ProcessIncomingMessage(message), "PLAINTEXT binding element should opt-out where it doesn't understand.");
}
- [TestMethod]
+ [TestCase]
public void HttpSignatureGeneration() {
SigningBindingElementBase target = new PlaintextSigningBindingElement();
target.Channel = new TestChannel();
@@ -68,7 +68,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
Assert.IsNull(message.Signature);
}
- [TestMethod]
+ [TestCase]
public void HttpSignatureVerification() {
SigningBindingElementBase target = new PlaintextSigningBindingElement();
target.Channel = new TestChannel();
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
index 6e566c8..c2ae65e 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
@@ -10,11 +10,11 @@ namespace DotNetOpenAuth.Test.ChannelElements {
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.OAuth.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class SigningBindingElementBaseTests : MessagingTestBase {
- [TestMethod]
+ [TestCase]
public void BaseSignatureStringTest() {
// Tests a message sent by HTTP GET, with no query string included in the endpoint.
UnauthorizedTokenRequest message = CreateTestRequestTokenMessage(
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs
index 40fc93e..715669a 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/UriOrOobEncodingTests.cs
@@ -10,13 +10,13 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
using System.Linq;
using System.Text;
using DotNetOpenAuth.OAuth.ChannelElements;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class UriOrOobEncodingTests : TestBase {
private UriOrOobEncoding encoding;
- [TestInitialize]
+ [SetUp]
public void Setup() {
this.encoding = new UriOrOobEncoding();
}
@@ -24,7 +24,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
/// <summary>
/// Verifies null value encoding
/// </summary>
- [TestMethod]
+ [TestCase]
public void NullValueEncoding() {
Assert.AreEqual("oob", this.encoding.EncodedNullValue);
}
@@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
/// <summary>
/// Verifies decoding "oob" results in a null uri.
/// </summary>
- [TestMethod]
+ [TestCase]
public void DecodeOobToNullUri() {
Assert.IsNull(this.encoding.Decode("oob"));
}
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
/// <summary>
/// Verifies that decoding an empty string generates an exception.
/// </summary>
- [TestMethod, ExpectedException(typeof(UriFormatException))]
+ [TestCase, ExpectedException(typeof(UriFormatException))]
public void DecodeEmptyStringFails() {
this.encoding.Decode(string.Empty);
}
@@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
/// <summary>
/// Verifies proper decoding/encoding of a Uri
/// </summary>
- [TestMethod]
+ [TestCase]
public void UriEncodeDecode() {
Uri original = new Uri("http://somehost/p?q=a#frag");
string encodedValue = this.encoding.Encode(original);
@@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
/// <summary>
/// Verifies failure to decode a relative Uri
/// </summary>
- [TestMethod, ExpectedException(typeof(UriFormatException))]
+ [TestCase, ExpectedException(typeof(UriFormatException))]
public void RelativeUriDecodeFails() {
this.encoding.Decode("../a/b");
}
diff --git a/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs b/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs
index ce8070b..f866990 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ProtocolTests.cs
@@ -6,27 +6,27 @@
namespace DotNetOpenAuth.Test {
using DotNetOpenAuth.OAuth;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ProtocolTests {
- [TestMethod]
+ [TestCase]
public void Default() {
Assert.AreSame(Protocol.V10a, Protocol.Default);
}
- [TestMethod]
+ [TestCase]
public void DataContractNamespace() {
Assert.AreEqual("http://oauth.net/core/1.0/", Protocol.V10.DataContractNamespace);
Assert.AreEqual("http://oauth.net/core/1.0/", Protocol.DataContractNamespaceV10);
}
- [TestMethod]
+ [TestCase]
public void AuthorizationHeaderScheme() {
Assert.AreEqual("OAuth", Protocol.AuthorizationHeaderScheme);
}
- [TestMethod]
+ [TestCase]
public void ParameterPrefix() {
Assert.AreEqual("oauth_", Protocol.ParameterPrefix);
}
diff --git a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs
index 760a9e9..4ed1c74 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderDescriptionTests.cs
@@ -8,17 +8,17 @@ namespace DotNetOpenAuth.Test {
using System;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// Tests for the <see cref="ServiceProviderEndpoints"/> class.
/// </summary>
- [TestClass]
+ [TestFixture]
public class ServiceProviderDescriptionTests : TestBase {
/// <summary>
/// A test for UserAuthorizationUri
/// </summary>
- [TestMethod]
+ [TestCase]
public void UserAuthorizationUriTest() {
ServiceProviderDescription target = new ServiceProviderDescription();
MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/authorization", HttpDeliveryMethods.GetRequest);
@@ -34,7 +34,7 @@ namespace DotNetOpenAuth.Test {
/// <summary>
/// A test for RequestTokenUri
/// </summary>
- [TestMethod]
+ [TestCase]
public void RequestTokenUriTest() {
var target = new ServiceProviderDescription();
MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/requesttoken", HttpDeliveryMethods.GetRequest);
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test {
/// Verifies that oauth parameters are not allowed in <see cref="ServiceProvider.RequestTokenUri"/>,
/// per section OAuth 1.0 section 4.1.
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void RequestTokenUriWithOAuthParametersTest() {
var target = new ServiceProviderDescription();
target.RequestTokenEndpoint = new MessageReceivingEndpoint("http://localhost/requesttoken?oauth_token=something", HttpDeliveryMethods.GetRequest);
@@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test {
/// <summary>
/// A test for AccessTokenUri
/// </summary>
- [TestMethod]
+ [TestCase]
public void AccessTokenUriTest() {
var target = new ServiceProviderDescription();
MessageReceivingEndpoint expected = new MessageReceivingEndpoint("http://localhost/accesstoken", HttpDeliveryMethods.GetRequest);
diff --git a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs
index 2a443ce..ceb9a60 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ServiceProviderTests.cs
@@ -11,14 +11,14 @@ namespace DotNetOpenAuth.Test.OAuth {
using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ServiceProviderTests : TestBase {
/// <summary>
/// Verifies the CreateVerificationCode method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void CreateVerificationCode() {
this.TestCode(VerificationCodeFormat.Numeric, 3, MessagingUtilities.Digits);
this.TestCode(VerificationCodeFormat.AlphaLower, 5, MessagingUtilities.LowercaseLetters);
@@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OAuth {
private void TestCode(VerificationCodeFormat format, int length, string allowableCharacters) {
string code = ServiceProvider.CreateVerificationCode(format, length);
- TestContext.WriteLine("{0} of length {2}: {1}", format, code, length);
+ TestUtilities.TestLogger.InfoFormat("{0} of length {2}: {1}", format, code, length);
Assert.AreEqual(length, code.Length);
foreach (char ch in code) {
Assert.IsTrue(allowableCharacters.Contains(ch));
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
index af3b1b1..8c2b5bd 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AssociationHandshakeTests.cs
@@ -12,21 +12,21 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociationHandshakeTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod]
+ [TestCase]
public void AssociateUnencrypted() {
this.ParameterizedAssociationTest(new Uri("https://host"));
}
- [TestMethod]
+ [TestCase]
public void AssociateDiffieHellmanOverHttp() {
this.ParameterizedAssociationTest(new Uri("http://host"));
}
@@ -38,7 +38,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Some OPs out there flatly refuse to do this, and the spec doesn't forbid
/// putting the two together, so we verify that DNOI can handle it.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void AssociateDiffieHellmanOverHttps() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -62,7 +62,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that the RP and OP can renegotiate an association type if the RP's
/// initial request for an association is for a type the OP doesn't support.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AssociateRenegotiateBitLength() {
Protocol protocol = Protocol.V20;
@@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.OpenId {
op.SecuritySettings.MaximumHashBitLength = 160; // Force OP to reject HMAC-SHA256
// Receive initial request for an HMAC-SHA256 association.
- AutoResponsiveRequest req = (AutoResponsiveRequest) op.GetRequest();
+ AutoResponsiveRequest req = (AutoResponsiveRequest)op.GetRequest();
AutoResponsiveRequest_Accessor reqAccessor = AutoResponsiveRequest_Accessor.AttachShadow(req);
AssociateRequest associateRequest = (AssociateRequest)reqAccessor.RequestMessage;
Assert.AreEqual(protocol.Args.SignatureAlgorithm.HMAC_SHA256, associateRequest.AssociationType);
@@ -110,7 +110,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <remarks>
/// Verifies OP's compliance with OpenID 2.0 section 8.4.1.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void OPRejectsHttpNoEncryptionAssociateRequests() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -131,7 +131,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that the OP rejects an associate request
/// when the HMAC and DH bit lengths do not match.
/// </summary>
- [TestMethod]
+ [TestCase]
public void OPRejectsMismatchingAssociationAndSessionTypes() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -154,7 +154,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <summary>
/// Verifies that the RP quietly rejects an OP that suggests an unknown association type.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RPRejectsUnrecognizedAssociationType() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -181,7 +181,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <remarks>
/// Verifies RP's compliance with OpenID 2.0 section 8.4.1.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void RPRejectsUnencryptedSuggestion() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -206,7 +206,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that the RP rejects an associate renegotiate request
/// when the HMAC and DH bit lengths do not match.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RPRejectsMismatchingAssociationAndSessionBitLengths() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -231,7 +231,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that the RP cannot get caught in an infinite loop if a bad OP
/// keeps sending it association retry messages.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RPOnlyRenegotiatesOnce() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -264,7 +264,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <summary>
/// Verifies security settings limit RP's acceptance of OP's counter-suggestion
/// </summary>
- [TestMethod]
+ [TestCase]
public void AssociateRenegotiateLimitedByRPSecuritySettings() {
Protocol protocol = Protocol.V20;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -284,7 +284,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that the RP can recover from an invalid or non-existent
/// response from the OP, for example in the HTTP timeout case.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AssociateQuietlyFailsAfterHttpError() {
this.MockResponder.RegisterMockNotFound(OPUri);
var rp = this.CreateRelyingParty();
@@ -318,9 +318,9 @@ namespace DotNetOpenAuth.Test.OpenId {
private void ParameterizedAssociationTest(
ProviderEndpointDescription opDescription,
string expectedAssociationType) {
- Protocol protocol = Protocol.Lookup(opDescription.ProtocolVersion);
+ Protocol protocol = Protocol.Lookup(Protocol.Lookup(opDescription.Version).ProtocolVersion);
bool expectSuccess = expectedAssociationType != null;
- bool expectDiffieHellman = !opDescription.Endpoint.IsTransportSecure();
+ bool expectDiffieHellman = !opDescription.Uri.IsTransportSecure();
Association rpAssociation = null, opAssociation;
AssociateSuccessfulResponse associateSuccessfulResponse = null;
AssociateUnsuccessfulResponse associateUnsuccessfulResponse = null;
@@ -337,7 +337,7 @@ namespace DotNetOpenAuth.Test.OpenId {
op.SendResponse(req);
});
coordinator.IncomingMessageFilter = message => {
- Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, opDescription.ProtocolVersion);
+ Assert.AreSame(opDescription.Version, message.Version, "The message was recognized as version {0} but was expected to be {1}.", message.Version, Protocol.Lookup(opDescription.Version).ProtocolVersion);
var associateSuccess = message as AssociateSuccessfulResponse;
var associateFailed = message as AssociateUnsuccessfulResponse;
if (associateSuccess != null) {
@@ -348,7 +348,7 @@ namespace DotNetOpenAuth.Test.OpenId {
}
};
coordinator.OutgoingMessageFilter = message => {
- Assert.AreSame(opDescription.ProtocolVersion, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.ProtocolVersion);
+ Assert.AreEqual(opDescription.Version, message.Version, "The message was for version {0} but was expected to be for {1}.", message.Version, opDescription.Version);
};
coordinator.Run();
@@ -356,7 +356,7 @@ namespace DotNetOpenAuth.Test.OpenId {
if (expectSuccess) {
Assert.IsNotNull(rpAssociation);
- Assert.AreSame(rpAssociation, associationManagerAccessor.associationStore.GetAssociation(opDescription.Endpoint, rpAssociation.Handle));
+ Assert.AreSame(rpAssociation, associationManagerAccessor.associationStore.GetAssociation(opDescription.Uri, rpAssociation.Handle));
opAssociation = coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, rpAssociation.Handle);
Assert.IsNotNull(opAssociation, "The Provider should have stored the association.");
@@ -367,15 +367,15 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsTrue(MessagingUtilities.AreEquivalent(opAssociation.SecretKey, rpAssociation.SecretKey));
if (expectDiffieHellman) {
- Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateDiffieHellmanResponse));
+ Assert.IsInstanceOf<AssociateDiffieHellmanResponse>(associateSuccessfulResponse);
var diffieHellmanResponse = (AssociateDiffieHellmanResponse)associateSuccessfulResponse;
Assert.IsFalse(MessagingUtilities.AreEquivalent(diffieHellmanResponse.EncodedMacKey, rpAssociation.SecretKey), "Key should have been encrypted.");
} else {
- Assert.IsInstanceOfType(associateSuccessfulResponse, typeof(AssociateUnencryptedResponse));
+ Assert.IsInstanceOf<AssociateUnencryptedResponse>(associateSuccessfulResponse);
var unencryptedResponse = (AssociateUnencryptedResponse)associateSuccessfulResponse;
}
} else {
- Assert.IsNull(associationManagerAccessor.associationStore.GetAssociation(opDescription.Endpoint, new RelyingPartySecuritySettings()));
+ Assert.IsNull(associationManagerAccessor.associationStore.GetAssociation(opDescription.Uri, new RelyingPartySecuritySettings()));
Assert.IsNull(coordinator.Provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, new ProviderSecuritySettings()));
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs
index 6881255..a70189f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AssociationTests.cs
@@ -12,16 +12,16 @@ namespace DotNetOpenAuth.Test.OpenId {
using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociationTests : OpenIdTestBase {
private static readonly TimeSpan deltaDateTime = TimeSpan.FromSeconds(2);
private static readonly HashAlgorithm sha1 = DiffieHellmanUtilities.Lookup(Protocol.Default, Protocol.Default.Args.SessionType.DH_SHA1);
private byte[] sha1Secret;
private byte[] sha1Secret2;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId {
this.sha1Secret2[1] = 0xcc;
}
- [TestMethod]
+ [TestCase]
public void Properties() {
string handle = "somehandle";
TimeSpan lifetime = TimeSpan.FromMinutes(2);
@@ -49,7 +49,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual(0, assoc.Issued.Millisecond, "No milliseconds because this can be cut off in conversions.");
}
- [TestMethod]
+ [TestCase]
public void Sign() {
Association assoc1 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h1", this.sha1Secret, TimeSpan.FromMinutes(2));
Association assoc2 = HmacShaAssociation.Create(Protocol.Default, Protocol.Default.Args.SignatureAlgorithm.HMAC_SHA1, "h2", this.sha1Secret2, TimeSpan.FromMinutes(2));
diff --git a/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs b/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs
index a0c4770..b3d7e4d 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AssociationsTests.cs
@@ -11,31 +11,31 @@ namespace DotNetOpenAuth.Test.OpenId {
using System.Security.Cryptography;
using System.Text;
using DotNetOpenAuth.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociationsTests : OpenIdTestBase {
private static readonly HashAlgorithm sha1 = DiffieHellmanUtilities.Lookup(Protocol.Default, Protocol.Default.Args.SessionType.DH_SHA1);
private byte[] sha1Secret;
private Associations assocs;
- [TestInitialize]
+ [TestFixtureSetUp]
public override void SetUp() {
this.sha1Secret = new byte[sha1.HashSize / 8];
this.assocs = new Associations();
}
- [TestMethod]
+ [TestCase]
public void GetNonexistentHandle() {
Assert.IsNull(this.assocs.Get("someinvalidhandle"));
}
- [TestMethod]
+ [TestCase]
public void RemoveNonexistentHandle() {
Assert.IsFalse(this.assocs.Remove("someinvalidhandle"));
}
- [TestMethod]
+ [TestCase]
public void HandleLifecycle() {
Association a = HmacShaAssociation.Create(
Protocol.Default,
@@ -50,7 +50,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(this.assocs.Remove(a.Handle));
}
- [TestMethod]
+ [TestCase]
public void Best() {
Association a = HmacShaAssociation.Create(
Protocol.Default,
diff --git a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
index 7de2a8b..27db93e 100644
--- a/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/AuthenticationTests.cs
@@ -14,16 +14,16 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AuthenticationTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod]
+ [TestCase]
public void SharedAssociationPositive() {
this.ParameterizedAuthenticationTest(true, true, false);
}
@@ -31,17 +31,17 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <summary>
/// Verifies that a shared association protects against tampering.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SharedAssociationTampered() {
this.ParameterizedAuthenticationTest(true, true, true);
}
- [TestMethod]
+ [TestCase]
public void SharedAssociationNegative() {
this.ParameterizedAuthenticationTest(true, false, false);
}
- [TestMethod]
+ [TestCase]
public void PrivateAssociationPositive() {
this.ParameterizedAuthenticationTest(false, true, false);
}
@@ -49,17 +49,17 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <summary>
/// Verifies that a private association protects against tampering.
/// </summary>
- [TestMethod]
+ [TestCase]
public void PrivateAssociationTampered() {
this.ParameterizedAuthenticationTest(false, true, true);
}
- [TestMethod]
+ [TestCase]
public void NoAssociationNegative() {
this.ParameterizedAuthenticationTest(false, false, false);
}
- [TestMethod]
+ [TestCase]
public void UnsolicitedAssertion() {
this.MockResponder.RegisterMockRPDiscovery();
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Test.OpenId {
coordinator.Run();
}
- [TestMethod]
+ [TestCase]
public void UnsolicitedAssertionRejected() {
this.MockResponder.RegisterMockRPDiscovery();
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.OpenId {
/// Verifies that delegating identifiers are rejected in unsolicited assertions
/// when the appropriate security setting is set.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnsolicitedDelegatingIdentifierRejection() {
this.MockResponder.RegisterMockRPDiscovery();
OpenIdCoordinator coordinator = new OpenIdCoordinator(
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
index 29797dc..5edd51f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
@@ -18,15 +18,15 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
using DotNetOpenAuth.Test.OpenId.Extensions;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ExtensionsBindingElementTests : OpenIdTestBase {
private StandardOpenIdExtensionFactory factory;
private ExtensionsBindingElement rpElement;
private IProtocolMessageWithExtensions request;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
this.request = new SignedResponseRequest(Protocol.Default.Version, OpenIdTestBase.OPUri, AuthenticationRequestMode.Immediate);
}
- [TestMethod]
+ [TestCase]
public void RoundTripFullStackTest() {
IOpenIdMessageExtension request = new MockOpenIdExtension("requestPart", "requestData");
IOpenIdMessageExtension response = new MockOpenIdExtension("responsePart", "responseData");
@@ -47,12 +47,12 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
new IOpenIdMessageExtension[] { response });
}
- [TestMethod]
+ [TestCase]
public void ExtensionFactory() {
Assert.AreSame(this.factory, this.rpElement.ExtensionFactory);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void PrepareMessageForSendingNull() {
this.rpElement.ProcessOutgoingMessage(null);
}
@@ -60,13 +60,13 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that false is returned when a non-extendable message is sent.
/// </summary>
- [TestMethod]
+ [TestCase]
public void PrepareMessageForSendingNonExtendableMessage() {
IProtocolMessage request = new AssociateDiffieHellmanRequest(Protocol.Default.Version, OpenIdTestBase.OPUri);
Assert.IsNull(this.rpElement.ProcessOutgoingMessage(request));
}
- [TestMethod]
+ [TestCase]
public void PrepareMessageForSending() {
this.request.Extensions.Add(new MockOpenIdExtension("part", "extra"));
Assert.IsNotNull(this.rpElement.ProcessOutgoingMessage(this.request));
@@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
Assert.AreEqual("extra", this.request.ExtraData["openid." + alias + ".data"]);
}
- [TestMethod]
+ [TestCase]
public void PrepareMessageForReceiving() {
this.request.ExtraData["openid.ns.mock"] = MockOpenIdExtension.MockTypeUri;
this.request.ExtraData["openid.mock.Part"] = "part";
@@ -91,7 +91,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that extension responses are included in the OP's signature.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ExtensionResponsesAreSigned() {
Protocol protocol = Protocol.Default;
var op = this.CreateProvider();
@@ -113,7 +113,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that unsigned extension responses (where any or all fields are unsigned) are ignored.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ExtensionsAreIdentifiedAsSignedOrUnsigned() {
Protocol protocol = Protocol.Default;
OpenIdCoordinator coordinator = new OpenIdCoordinator(
@@ -144,7 +144,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// OpenID Authentication 2.0 section 12 states that
/// "A namespace MUST NOT be assigned more than one alias in the same message".
/// </remarks>
- [TestMethod]
+ [TestCase]
public void TwoExtensionsSameTypeUri() {
IOpenIdMessageExtension request1 = new MockOpenIdExtension("requestPart1", "requestData1");
IOpenIdMessageExtension request2 = new MockOpenIdExtension("requestPart2", "requestData2");
@@ -154,8 +154,8 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
new IOpenIdMessageExtension[] { request1, request2 },
new IOpenIdMessageExtension[0]);
Assert.Fail("Expected ProtocolException not thrown.");
- } catch (AssertFailedException ex) {
- Assert.IsInstanceOfType(ex.InnerException, typeof(ProtocolException));
+ } catch (AssertionException ex) {
+ Assert.IsInstanceOf<ProtocolException>(ex.InnerException);
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs
index 92170c4..75ac503 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/KeyValueFormEncodingTests.cs
@@ -14,9 +14,9 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.ChannelElements;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class KeyValueFormEncodingTests : TestBase {
private Dictionary<string, string> sampleData = new Dictionary<string, string> {
{ "key1", "value1" },
@@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
Both = 0x3,
}
- [TestMethod]
+ [TestCase]
public void BasicEncodingTest() {
byte[] kvfBytes = KeyValueFormEncoding.GetBytes(this.sampleData);
string responseString = Encoding.UTF8.GetString(kvfBytes);
@@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
}
}
- [TestMethod]
+ [TestCase]
public void EncodeDecode() {
this.KVDictTest(UTF8Encoding.UTF8.GetBytes(string.Empty), new Dictionary<string, string>(), TestMode.Both);
@@ -117,35 +117,35 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
this.KVDictTest(UTF8Encoding.UTF8.GetBytes("east:west\nnorth:south"), d10, TestMode.Decoder);
}
- [TestMethod, ExpectedException(typeof(FormatException))]
+ [TestCase, ExpectedException(typeof(FormatException))]
public void NoValue() {
this.Illegal("x\n", KeyValueFormConformanceLevel.OpenId11);
}
- [TestMethod, ExpectedException(typeof(FormatException))]
+ [TestCase, ExpectedException(typeof(FormatException))]
public void NoValueLoose() {
Dictionary<string, string> d = new Dictionary<string, string>();
this.KVDictTest(Encoding.UTF8.GetBytes("x\n"), d, TestMode.Decoder);
}
- [TestMethod, ExpectedException(typeof(FormatException))]
+ [TestCase, ExpectedException(typeof(FormatException))]
public void EmptyLine() {
this.Illegal("x:b\n\n", KeyValueFormConformanceLevel.OpenId20);
}
- [TestMethod]
+ [TestCase]
public void EmptyLineLoose() {
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("x", "b");
this.KVDictTest(Encoding.UTF8.GetBytes("x:b\n\n"), d, TestMode.Decoder);
}
- [TestMethod, ExpectedException(typeof(FormatException))]
+ [TestCase, ExpectedException(typeof(FormatException))]
public void LastLineNotTerminated() {
this.Illegal("x:y\na:b", KeyValueFormConformanceLevel.OpenId11);
}
- [TestMethod]
+ [TestCase]
public void LastLineNotTerminatedLoose() {
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("x", "y");
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs
index 385cd19..97a40e8 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/OpenIdChannelTests.cs
@@ -18,16 +18,16 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OpenIdChannelTests : TestBase {
private static readonly TimeSpan maximumMessageAge = TimeSpan.FromHours(3); // good for tests, too long for production
private OpenIdChannel channel;
private OpenIdChannel_Accessor accessor;
private Mocks.TestWebRequestHandler webHandler;
- [TestInitialize]
+ [SetUp]
public void Setup() {
this.webHandler = new Mocks.TestWebRequestHandler();
this.channel = new OpenIdChannel(new AssociationMemoryStore<Uri>(), new NonceMemoryStore(maximumMessageAge), new RelyingPartySecuritySettings());
@@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
this.channel.WebRequestHandler = this.webHandler;
}
- [TestMethod]
+ [TestCase]
public void Ctor() {
// Verify that the channel stack includes the expected types.
// While other binding elements may be substituted for these, we'd then have
@@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that the channel sends direct message requests as HTTP POST requests.
/// </summary>
- [TestMethod]
+ [TestCase]
public void DirectRequestsUsePost() {
IDirectedProtocolMessage requestMessage = new Mocks.TestDirectedMessage(MessageTransport.Direct) {
Recipient = new Uri("http://host"),
@@ -61,7 +61,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
};
HttpWebRequest httpRequest = this.accessor.CreateHttpRequest(requestMessage);
Assert.AreEqual("POST", httpRequest.Method);
- StringAssert.Contains(this.webHandler.RequestEntityAsString, "Name=Andrew");
+ StringAssert.Contains("Name=Andrew", this.webHandler.RequestEntityAsString);
}
/// <summary>
@@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// class is verified elsewhere. We're only checking that the KVF class is being used by the
/// <see cref="OpenIdChannel.SendDirectMessageResponse"/> method.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void DirectResponsesSentUsingKeyValueForm() {
IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired);
MessageDictionary messageFields = this.MessageDescriptions.GetAccessor(message);
@@ -90,7 +90,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that direct message responses are read in using the Key Value Form decoder.
/// </summary>
- [TestMethod]
+ [TestCase]
public void DirectResponsesReceivedAsKeyValueForm() {
var fields = new Dictionary<string, string> {
{ "var1", "value1" },
@@ -105,7 +105,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that messages asking for special HTTP status codes get them.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SendDirectMessageResponseHonorsHttpStatusCodes() {
IProtocolMessage message = MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired);
OutgoingWebResponse directResponse = this.accessor.PrepareDirectResponse(message);
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
index 3ab6559..6160680 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
@@ -12,16 +12,16 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class SigningBindingElementTests : OpenIdTestBase {
/// <summary>
/// Verifies that the signatures generated match Known Good signatures.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SignaturesMatchKnownGood() {
- Protocol protocol = Protocol.Default;
+ Protocol protocol = Protocol.V20;
var settings = new ProviderSecuritySettings();
var store = new AssociationMemoryStore<AssociationRelyingPartyType>();
byte[] associationSecret = Convert.FromBase64String("rsSwv1zPWfjPRQU80hciu8FPDC+GONAMJQ/AvSo1a2M=");
@@ -42,7 +42,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
/// <summary>
/// Verifies that all parameters in ExtraData in signed responses are signed.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SignedResponsesIncludeExtraDataInSignature() {
Protocol protocol = Protocol.Default;
SigningBindingElement sbe = new SigningBindingElement(new AssociationMemoryStore<AssociationRelyingPartyType>(), new ProviderSecuritySettings());
diff --git a/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs
index 426e19a..9e89b03 100644
--- a/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/DiffieHellmanTests.cs
@@ -9,12 +9,12 @@ namespace DotNetOpenAuth.Test.OpenId {
using System.IO;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
using Org.Mentalis.Security.Cryptography;
- [TestClass]
+ [TestFixture]
public class DiffieHellmanTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void Test() {
string s1 = Test1();
string s2 = Test1();
@@ -22,7 +22,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreNotEqual(s1, s2, "Secret keys should NOT be the same.");
}
- [TestMethod, Timeout(15000)]
+ [TestCase, Timeout(15000), Category("Slow"), Category("Performance")]
public void TestPublic() {
TextReader reader = new StringReader(OpenIdTestBase.LoadEmbeddedFile("dhpriv.txt"));
@@ -30,7 +30,7 @@ namespace DotNetOpenAuth.Test.OpenId {
string line;
int lineNumber = 0;
while ((line = reader.ReadLine()) != null) {
- TestContext.WriteLine("\tLine {0}", ++lineNumber);
+ TestUtilities.TestLogger.InfoFormat("\tLine {0}", ++lineNumber);
string[] parts = line.Trim().Split(' ');
byte[] x = Convert.FromBase64String(parts[0]);
DiffieHellmanManaged dh = new DiffieHellmanManaged(AssociateDiffieHellmanRequest.DefaultMod, AssociateDiffieHellmanRequest.DefaultGen, x);
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithBadXrds.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithBadXrds.html
new file mode 100644
index 0000000..e695116
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithBadXrds.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <meta http-equiv="X-XRDS-Location" content="http://localhost/xrds-notfound.xml"/>
+ <link rel="openid2.provider" href="http://a/b" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithEmptyXrds.html b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithEmptyXrds.html
new file mode 100644
index 0000000..97ad7dc
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/htmldiscovery/html20provWithEmptyXrds.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Untitled Page</title>
+ <meta http-equiv="X-XRDS-Location" content="http://localhost/xrds-irrelevant.xml"/>
+ <link rel="openid2.provider" href="http://a/b" />
+</head>
+<body>
+</body>
+</html>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20dual.xml b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20dual.xml
new file mode 100644
index 0000000..9e6a66b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Discovery/xrdsdiscovery/xrds20dual.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="10">
+ <Type>http://specs.openid.net/auth/2.0/signon</Type>
+ <Type>http://specs.openid.net/auth/2.0/server</Type>
+ <URI>http://a/b</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs
new file mode 100644
index 0000000..1050b4b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/UriDiscoveryServiceTests.cs
@@ -0,0 +1,303 @@
+//-----------------------------------------------------------------------
+// <copyright file="UriDiscoveryServiceTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Text;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class UriDiscoveryServiceTests : OpenIdTestBase {
+ [TestCase]
+ public void DiscoveryWithRedirects() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, false);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+
+ // don't require secure SSL discovery for this test.
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, false);
+ Assert.AreEqual(1, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestCase]
+ public void DiscoverRequireSslWithSecureRedirects() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ // All redirects should be secure.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri secureMidpointUri = new Uri("https://localhost/secureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
+ Assert.AreEqual(1, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestCase, ExpectedException(typeof(ProtocolException))]
+ public void DiscoverRequireSslWithInsecureRedirect() {
+ Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
+
+ // Add a couple of chained redirect pages that lead to the claimedId.
+ // Include an insecure HTTP jump in those redirects to verify that
+ // the ultimate endpoint is never found as a result of high security profile.
+ Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
+ Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
+ this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
+ this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
+ this.Discover(userSuppliedIdentifier);
+ }
+
+ [TestCase]
+ public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+ Uri secureClaimedUri = new Uri("https://localhost/secureId");
+
+ string html = string.Format("<html><head><meta http-equiv='X-XRDS-Location' content='{0}'/></head><body></body></html>", insecureXrdsSource);
+ this.MockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
+ Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestCase]
+ public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+
+ string html = "<html><head></head><body></body></html>";
+ WebHeaderCollection headers = new WebHeaderCollection {
+ { "X-XRDS-Location", insecureXrdsSource }
+ };
+ this.MockResponder.RegisterMockResponse(VanityUriSsl, VanityUriSsl, "text/html", headers, html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
+ Assert.AreEqual(0, this.Discover(userSuppliedIdentifier).Count());
+ }
+
+ [TestCase]
+ public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() {
+ var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
+ string html = string.Format(
+ @"
+ <html><head>
+ <meta http-equiv='X-XRDS-Location' content='{0}'/> <!-- this one will be insecure and ignored -->
+ <link rel='openid2.provider' href='{1}' />
+ <link rel='openid2.local_id' href='{2}' />
+ </head><body></body></html>",
+ HttpUtility.HtmlEncode(insecureXrdsSource),
+ HttpUtility.HtmlEncode(OPUriSsl.AbsoluteUri),
+ HttpUtility.HtmlEncode(OPLocalIdentifiersSsl[1].AbsoluteUri));
+ this.MockResponder.RegisterMockResponse(VanityUriSsl, "text/html", html);
+
+ Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
+
+ // We verify that the XRDS was ignored and the LINK tags were used
+ // because the XRDS OP-LocalIdentifier uses different local identifiers.
+ Assert.AreEqual(OPLocalIdentifiersSsl[1].AbsoluteUri, this.Discover(userSuppliedIdentifier).Single().ProviderLocalIdentifier.ToString());
+ }
+
+ [TestCase]
+ public void DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds() {
+ var insecureEndpoint = GetServiceEndpoint(0, ProtocolVersion.V20, 10, false);
+ var secureEndpoint = GetServiceEndpoint(1, ProtocolVersion.V20, 20, true);
+ UriIdentifier secureClaimedId = new UriIdentifier(VanityUriSsl, true);
+ this.MockResponder.RegisterMockXrdsResponse(secureClaimedId, new IdentifierDiscoveryResult[] { insecureEndpoint, secureEndpoint });
+ Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, this.Discover(secureClaimedId).Single().ProviderLocalIdentifier);
+ }
+
+ [TestCase]
+ public void XrdsDirectDiscovery_10() {
+ this.FailDiscoverXrds("xrds-irrelevant");
+ this.DiscoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b");
+ this.DiscoverXrds("xrds11", ProtocolVersion.V11, null, "http://a/b");
+ this.DiscoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b");
+ }
+
+ [TestCase]
+ public void XrdsDirectDiscovery_20() {
+ this.DiscoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b");
+ }
+
+ [TestCase]
+ public void HtmlDiscover_11() {
+ this.DiscoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b");
+ this.DiscoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html10del");
+
+ // Verify that HTML discovery generates the 1.x endpoints when appropriate
+ this.DiscoverHtml("html2010", ProtocolVersion.V11, "http://g/h", "http://e/f");
+ this.DiscoverHtml("html1020", ProtocolVersion.V11, "http://g/h", "http://e/f");
+ this.DiscoverHtml("html2010combinedA", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedB", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b");
+ }
+
+ [TestCase]
+ public void HtmlDiscover_20() {
+ this.DiscoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b");
+ this.DiscoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html20del");
+ this.DiscoverHtml("html2010", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html1020", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.DiscoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d", "http://a/b");
+ this.FailDiscoverHtml("html20relative");
+ }
+
+ [TestCase]
+ public void XrdsDiscoveryFromHead() {
+ this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
+ this.DiscoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b");
+ }
+
+ [TestCase]
+ public void XrdsDiscoveryFromHttpHeader() {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add("X-XRDS-Location", new Uri("http://localhost/xrds1020.xml").AbsoluteUri);
+ this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
+ this.DiscoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, "http://a/b", headers);
+ }
+
+ /// <summary>
+ /// Verifies HTML discovery proceeds if an XRDS document is referenced that doesn't contain OpenID endpoints.
+ /// </summary>
+ [TestCase]
+ public void HtmlDiscoveryProceedsIfXrdsIsEmpty() {
+ this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds-irrelevant.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds-irrelevant.xml"));
+ this.DiscoverHtml("html20provWithEmptyXrds", ProtocolVersion.V20, null, "http://a/b");
+ }
+
+ /// <summary>
+ /// Verifies HTML discovery proceeds if the XRDS that is referenced cannot be found.
+ /// </summary>
+ [TestCase]
+ public void HtmlDiscoveryProceedsIfXrdsIsBadOrMissing() {
+ this.DiscoverHtml("html20provWithBadXrds", ProtocolVersion.V20, null, "http://a/b");
+ }
+
+ /// <summary>
+ /// Verifies that a dual identifier yields only one service endpoint by default.
+ /// </summary>
+ [TestCase]
+ public void DualIdentifierOffByDefault() {
+ this.MockResponder.RegisterMockResponse(VanityUri, "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds20dual.xml"));
+ var results = this.Discover(VanityUri).ToList();
+ Assert.AreEqual(1, results.Count(r => r.ClaimedIdentifier == r.Protocol.ClaimedIdentifierForOPIdentifier), "OP Identifier missing from discovery results.");
+ Assert.AreEqual(1, results.Count, "Unexpected additional services discovered.");
+ }
+
+ /// <summary>
+ /// Verifies that a dual identifier yields two service endpoints when that feature is turned on.
+ /// </summary>
+ [TestCase]
+ public void DualIdentifier() {
+ this.MockResponder.RegisterMockResponse(VanityUri, "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds20dual.xml"));
+ var rp = this.CreateRelyingParty(true);
+ rp.Channel.WebRequestHandler = this.RequestHandler;
+ rp.SecuritySettings.AllowDualPurposeIdentifiers = true;
+ var results = rp.Discover(VanityUri).ToList();
+ Assert.AreEqual(1, results.Count(r => r.ClaimedIdentifier == r.Protocol.ClaimedIdentifierForOPIdentifier), "OP Identifier missing from discovery results.");
+ Assert.AreEqual(1, results.Count(r => r.ClaimedIdentifier == VanityUri), "Claimed identifier missing from discovery results.");
+ Assert.AreEqual(2, results.Count, "Unexpected additional services discovered.");
+ }
+
+ private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect) {
+ this.Discover(url, version, expectedLocalId, providerEndpoint, expectSreg, useRedirect, null);
+ }
+
+ private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
+ Protocol protocol = Protocol.Lookup(version);
+ Uri baseUrl = new Uri("http://localhost/");
+ UriIdentifier claimedId = new Uri(baseUrl, url);
+ UriIdentifier userSuppliedIdentifier = new Uri(baseUrl, "Discovery/htmldiscovery/redirect.aspx?target=" + url);
+ if (expectedLocalId == null) {
+ expectedLocalId = claimedId;
+ }
+ Identifier idToDiscover = useRedirect ? userSuppliedIdentifier : claimedId;
+
+ string contentType;
+ if (url.EndsWith("html")) {
+ contentType = "text/html";
+ } else if (url.EndsWith("xml")) {
+ contentType = "application/xrds+xml";
+ } else {
+ throw new InvalidOperationException();
+ }
+ this.MockResponder.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType, headers ?? new WebHeaderCollection(), LoadEmbeddedFile(url));
+
+ IdentifierDiscoveryResult expected = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ claimedId,
+ expectedLocalId,
+ new ProviderEndpointDescription(new Uri(providerEndpoint), new string[] { protocol.ClaimedIdentifierServiceTypeURI }), // services aren't checked by Equals
+ null,
+ null);
+
+ IdentifierDiscoveryResult se = this.Discover(idToDiscover).FirstOrDefault(ep => ep.Equals(expected));
+ Assert.IsNotNull(se, url + " failed to be discovered.");
+
+ // Do extra checking of service type URIs, which aren't included in
+ // the ServiceEndpoint.Equals method.
+ Assert.AreEqual(expectSreg ? 2 : 1, se.Capabilities.Count);
+ Assert.IsTrue(se.Capabilities.Contains(protocol.ClaimedIdentifierServiceTypeURI));
+ Assert.AreEqual(expectSreg, se.IsExtensionSupported<ClaimsRequest>());
+ }
+
+ private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
+ this.DiscoverXrds(page, version, expectedLocalId, providerEndpoint, null);
+ }
+
+ private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, WebHeaderCollection headers) {
+ if (!page.Contains(".")) {
+ page += ".xml";
+ }
+ this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, false, headers);
+ this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, true, headers);
+ }
+
+ private void DiscoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool useRedirect) {
+ this.Discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, providerEndpoint, false, useRedirect);
+ }
+
+ private void DiscoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
+ string page = scenario + ".html";
+ this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, false);
+ this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, true);
+ }
+
+ private void FailDiscover(string url) {
+ UriIdentifier userSuppliedId = new Uri(new Uri("http://localhost"), url);
+
+ this.MockResponder.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html", LoadEmbeddedFile(url));
+
+ Assert.AreEqual(0, this.Discover(userSuppliedId).Count()); // ... but that no endpoint info is discoverable
+ }
+
+ private void FailDiscoverHtml(string scenario) {
+ this.FailDiscover("/Discovery/htmldiscovery/" + scenario + ".html");
+ }
+
+ private void FailDiscoverXrds(string scenario) {
+ this.FailDiscover("/Discovery/xrdsdiscovery/" + scenario + ".xml");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs
new file mode 100644
index 0000000..5d914f5
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/DiscoveryServices/XriDiscoveryProxyServiceTests.cs
@@ -0,0 +1,394 @@
+//-----------------------------------------------------------------------
+// <copyright file="XriDiscoveryProxyServiceTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.DiscoveryServices {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class XriDiscoveryProxyServiceTests : OpenIdTestBase {
+ [TestCase]
+ public void Discover() {
+ string xrds = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*Arnott</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:03:24.000Z</Expires>
+ <ProviderID>xri://=</ProviderID>
+ <LocalID>!9b72.7dd1.50a9.5ccd</LocalID>
+ <CanonicalID>=!9B72.7DD1.50A9.5CCD</CanonicalID>
+
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='default' select='false'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null' select='false'/>
+ <URI append='qxri' priority='1'>http://1id.com/contact/</URI>
+
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <URI append='qxri' priority='1'>http://1id.com/</URI>
+ </Service>
+
+ <Service priority='10'>
+ <ProviderID>xri://!!1008</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='10'>http://1id.com/sso</URI>
+ </Service>
+</XRD>";
+ Dictionary<string, string> mocks = new Dictionary<string, string> {
+ { "https://xri.net/=Arnott?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
+ { "https://xri.net/=!9B72.7DD1.50A9.5CCD?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
+ };
+ this.MockResponder.RegisterMockXrdsResponses(mocks);
+
+ string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
+ IdentifierDiscoveryResult se = this.VerifyCanonicalId("=Arnott", expectedCanonicalId);
+ Assert.AreEqual(Protocol.V10, Protocol.Lookup(se.Version));
+ Assert.AreEqual("http://1id.com/sso", se.ProviderEndpoint.ToString());
+ Assert.AreEqual(se.ClaimedIdentifier, se.ProviderLocalIdentifier);
+ Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay);
+ }
+
+ [TestCase]
+ public void DiscoverCommunityInameCanonicalIDs() {
+ string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*llli</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:21:06.000Z</Expires>
+ <ProviderID>xri://@</ProviderID>
+ <LocalID>!72cd.a072.157e.a9c6</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6</CanonicalID>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type match='null' select='false'/>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path match='default'/>
+ <Path>(+index)</Path>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI priority='10'>http://resolve.ezibroker.net/resolve/@llli/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+</XRD>
+";
+ string llliAreaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*area</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:07.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA0C</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI>http://resolve.ezibroker.net/resolve/@llli*area/</URI>
+ </Service>
+</XRD>";
+ string llliAreaCanadaUnattachedResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*canada.unattached</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:08.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA41</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType>application/xrds+xml;trust=none</MediaType>
+ <URI>http://resolve.ezibroker.net/resolve/@llli*area*canada.unattached/</URI>
+ </Service>
+</XRD>";
+ string llliAreaCanadaUnattachedAdaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*ada</Query>
+ <Status cid='verified' code='100'>SUCCESS</Status>
+ <ServerStatus code='100'>SUCCESS</ServerStatus>
+ <Expires>2008-07-15T01:21:10.000Z</Expires>
+ <ProviderID>xri://!!1003</ProviderID>
+ <LocalID>0000.0000.3B9A.CA01</LocalID>
+ <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01</CanonicalID>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <URI append='none' priority='1'>https://login.llli.org/server/</URI>
+ </Service>
+ <Service>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
+ </Service>
+ <Service priority='1'>
+ <ProviderID>xri://!!1003!103</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path>(+index)</Path>
+ <Path match='default'/>
+ <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
+ </Service>
+</XRD>";
+ string webResponse = @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*Web</Query>
+ <Status ceid='off' cid='verified' code='100'/>
+ <Expires>2008-07-14T02:21:12.000Z</Expires>
+ <ProviderID>xri://=</ProviderID>
+ <LocalID>!91f2.8153.f600.ae24</LocalID>
+ <CanonicalID>=!91F2.8153.F600.AE24</CanonicalID>
+ <Service priority='10'>
+ <Type select='true'>xri://+i-service*(+locator)*($v*1.0)</Type>
+ <Path select='true'>(+locator)</Path>
+ <MediaType match='default' select='false'/>
+ <URI append='qxri'>http://locator.fullxri.com/locator/</URI>
+ </Service>
+ <Service priority='10'>
+ <ProviderID>xri://=web</ProviderID>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <Type select='true'>xri://$res*auth*($v*2.0)</Type>
+ <MediaType select='true'>application/xrds+xml</MediaType>
+ <URI append='qxri' priority='1'>https://resolve.freexri.com/ns/=web/</URI>
+ <URI append='qxri' priority='2'>http://resolve.freexri.com/ns/=web/</URI>
+ </Service>
+ <Service priority='10'>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Type select='true'>http://specs.openid.net/auth/2.0/signon</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default' select='false'/>
+ <MediaType match='default' select='false'/>
+ <URI append='none' priority='2'>http://authn.fullxri.com/authentication/</URI>
+ <URI append='none' priority='1'>https://authn.fullxri.com/authentication/</URI>
+ </Service>
+ <Service priority='10'>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null' select='false'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null' select='false'/>
+ <MediaType match='default' select='false'/>
+ <URI append='qxri'>http://contact.fullxri.com/contact/</URI>
+ </Service>
+ <KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
+ <X509Data>
+ <X509Certificate>
+MIIExzCCA6+gAwIBAgIJAM+MlFr0Sth6MA0GCSqGSIb3DQEBBQUAMIGdMR8wHQYD
+VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
+CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
+YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
+YWluLmVkdTAeFw0wNjA4MTcxOTU5NTNaFw0xMTA4MTYxOTU5NTNaMIGdMR8wHQYD
+VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
+CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
+YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
+YWluLmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6uFqas4dK6
+A2wTZL0viRQNJrPyFnFBDSZGib/2ijhgzed/vvmZIBM9sFpwahcuR5hvyKUe37/c
+/RSZXoNDi/eiNOx4qb0l9UB6bd8qvc4V1PnLE7L+ZYcmwrvTKm4x8qXMgEv1wca2
+FPsreHNPdLiTUZ8v0tDTWi3Mgi7y47VTzJaTkcfmO1nL6xAtln5sLdH0PbMM3LAp
+T1d3nwI3VdbhqqZ+6+OKEuC8gk5iH4lfrbr6C9bYS6vzIKrotHpZ3N2aIC3NMjJD
+PMw/mfCuADfRNlHXgZW+0zyUkwGTMDea8qgsoAMWJGdeTIw8I1I3RhnbgLzdsNQl
+b/1ZXx1uJRUCAwEAAaOCAQYwggECMB0GA1UdDgQWBBQe+xSjYTrlfraJARjMxscb
+j36jvDCB0gYDVR0jBIHKMIHHgBQe+xSjYTrlfraJARjMxscbj36jvKGBo6SBoDCB
+nTEfMB0GA1UEAxMWU3VwZXJ2aWxsYWluOiBUaGUgUm9vdDELMAkGA1UEBhMCVVMx
+ETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZHb3RoYW0xIDAeBgNVBAoTF1N1
+cGVydmlsbGFpbiBVbml2ZXJzaXR5MScwJQYJKoZIhvcNAQkBFhhwZW5ndWluQHN1
+cGVydmlsbGFpbi5lZHWCCQDPjJRa9ErYejAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
+DQEBBQUAA4IBAQC4SPBDGYAxfbXd8N5OvG0drM7a5hjXfcCZpiILlPSRpxp79yh7
+I5vVWxBxUfolwbei7PTBVy7CE27SUbSICeqWjcDCfjNjiZk6mLS80rm/TdLrHSyM
++Ujlw9MGcBGaLI+sdziDUMtTQDpeAyQTaGVbh1mx5874Hlo1VXqGYNo0RwR+iLfs
+x48VuO6GbWVyxtktkE2ypz1KLWiyI056YynydRvuBCBHeRqGUixPlH9CrmeSCP2S
+sfbiKnMOGXjIYbvbsTAMdW2iqg6IWa/fgxhvZoAXChM9bkhisJQc0qD0J5TJQwgr
+uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+</XRD>";
+ this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ { "https://xri.net/@llli?_xrd_r=application/xrd%2Bxml;sep=false", llliResponse },
+ { "https://xri.net/@llli*area?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaResponse },
+ { "https://xri.net/@llli*area*canada.unattached?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedResponse },
+ { "https://xri.net/@llli*area*canada.unattached*ada?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedAdaResponse },
+ { "https://xri.net/=Web?_xrd_r=application/xrd%2Bxml;sep=false", webResponse },
+ });
+ this.VerifyCanonicalId("@llli", "@!72CD.A072.157E.A9C6");
+ this.VerifyCanonicalId("@llli*area", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C");
+ this.VerifyCanonicalId("@llli*area*canada.unattached", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41");
+ this.VerifyCanonicalId("@llli*area*canada.unattached*ada", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01");
+ this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24");
+ }
+
+ [TestCase]
+ public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
+ this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
+ { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*andrew.arnott</Query>
+ <Status cid='absent' code='100'>Success</Status>
+ <ServerStatus code='100'>Success</ServerStatus>
+ <Expires>2008-07-14T03:30:59.722Z</Expires>
+ <ProviderID>=!91F2.8153.F600.AE24</ProviderID>
+ <Service>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
+ <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://contact.freexri.com/contact/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path select='true'>(+index)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://authn.freexri.com/authentication/</URI>
+ <URI append='none' priority='1'>https://authn.freexri.com/authentication/</URI>
+ </Service>
+ <ServedBy>OpenXRI</ServedBy>
+</XRD>" },
+ { "https://xri.net/@id*andrewarnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
+<XRD xmlns='xri://$xrd*($v*2.0)'>
+ <Query>*andrewarnott</Query>
+ <Status cid='absent' code='100'>Success</Status>
+ <ServerStatus code='100'>Success</ServerStatus>
+ <Expires>2008-07-14T03:31:00.466Z</Expires>
+ <ProviderID>@!B1E8.C27B.E41C.25C3</ProviderID>
+ <Service>
+ <Type select='true'>http://openid.net/signon/1.0</Type>
+ <Path select='true'>(+login)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
+ <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
+ <Type match='null'/>
+ <Path select='true'>(+contact)</Path>
+ <Path match='null'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://contact.freexri.com/contact/</URI>
+ </Service>
+ <Service>
+ <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
+ <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
+ <Path select='true'>(+index)</Path>
+ <Path match='default'/>
+ <MediaType match='default'/>
+ <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
+ </Service>
+ <ServedBy>OpenXRI</ServedBy>
+</XRD>" },
+ });
+ // Consistent with spec section 7.3.2.3, we do not permit
+ // delegation on XRI discovery when there is no CanonicalID present.
+ this.VerifyCanonicalId("=Web*andrew.arnott", null);
+ this.VerifyCanonicalId("@id*andrewarnott", null);
+ }
+
+ private IdentifierDiscoveryResult VerifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
+ var se = this.Discover(iname).FirstOrDefault();
+ if (expectedClaimedIdentifier != null) {
+ Assert.IsNotNull(se);
+ Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname);
+ Assert.IsTrue(se.Capabilities.Count > 0);
+ } else {
+ Assert.IsNull(se);
+ }
+ return se;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs
index fa05e94..3433cfa 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeExchangeRoundtripTests.cs
@@ -7,16 +7,16 @@
namespace DotNetOpenAuth.Test.OpenId.Extensions {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AttributeExchangeRoundtripTests : OpenIdTestBase {
private const string NicknameTypeUri = WellKnownAttributes.Name.Alias;
private const string EmailTypeUri = WellKnownAttributes.Contact.Email;
private const string IncrementingAttribute = "http://incatt";
private int incrementingAttributeValue = 1;
- [TestMethod]
+ [TestCase]
public void Fetch() {
var request = new FetchRequest();
request.Attributes.Add(new AttributeRequest(NicknameTypeUri));
@@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
ExtensionTestUtilities.Roundtrip(Protocol.Default, new[] { request }, new[] { response });
}
- [TestMethod]
+ [TestCase]
public void Store() {
var request = new StoreRequest();
var newAttribute = new AttributeValues(
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs
index 48b5727..5cc8ec1 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeRequestTests.cs
@@ -8,11 +8,11 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using System;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.Test.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AttributeRequestTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void CtorDefault() {
AttributeRequest req = new AttributeRequest();
Assert.AreEqual(1, req.Count);
@@ -20,27 +20,27 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.IsFalse(req.IsRequired);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorEmptyTypeUri() {
new AttributeRequest(string.Empty);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorNullTypeUri() {
new AttributeRequest(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
+ [TestCase, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CtorCountZero() {
new AttributeRequest(WellKnownAttributes.Contact.Email, false, 0);
}
- [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
+ [TestCase, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void CtorCountNegative() {
new AttributeRequest(WellKnownAttributes.Contact.Email, false, -1);
}
- [TestMethod]
+ [TestCase]
public void CtorFull() {
var req = new AttributeRequest(WellKnownAttributes.Contact.Email, true, 5);
Assert.AreEqual(WellKnownAttributes.Contact.Email, req.TypeUri);
@@ -48,19 +48,19 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual(5, req.Count);
}
- [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
+ [TestCase, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void SetCountZero() {
var req = new AttributeRequest();
req.Count = 0;
}
- [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
+ [TestCase, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void SetCountNegative() {
var req = new AttributeRequest();
req.Count = -1;
}
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var req1 = new AttributeRequest();
var req2 = new AttributeRequest();
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs
index 1f7e17c..6c28461 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/AttributeValuesTests.cs
@@ -10,11 +10,11 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
using System.Linq;
using System.Text;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AttributeValuesTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void Ctor() {
var att = new AttributeValues();
Assert.IsNull(att.TypeUri);
@@ -37,7 +37,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies the Equals method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var att1 = new AttributeValues();
var att2 = new AttributeValues();
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs
index 43eba3f..2388798 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchRequestTests.cs
@@ -9,35 +9,35 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using System.IO;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.Test.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class FetchRequestTests : OpenIdTestBase {
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void AddAttributeRequestNull() {
new FetchRequest().Attributes.Add(null);
}
- [TestMethod]
+ [TestCase]
public void AddAttributeRequest() {
var req = new FetchRequest();
req.Attributes.Add(new AttributeRequest() { TypeUri = "http://someUri" });
}
- [TestMethod]
+ [TestCase]
public void AddAttributeRequestStrangeUri() {
var req = new FetchRequest();
req.Attributes.Add(new AttributeRequest() { TypeUri = "=someUri*who*knows*but*this*is*legal" });
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void AddAttributeRequestAgain() {
var req = new FetchRequest();
req.Attributes.Add(new AttributeRequest() { TypeUri = "http://UriTwice" });
req.Attributes.Add(new AttributeRequest() { TypeUri = "http://UriTwice" });
}
- [TestMethod]
+ [TestCase]
public void RespondSimpleValue() {
var req = new AttributeRequest();
req.TypeUri = "http://someType";
@@ -47,7 +47,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual("value", resp.Values[0]);
}
- [TestMethod]
+ [TestCase]
public void RespondTwoValues() {
var req = new AttributeRequest();
req.TypeUri = "http://someType";
@@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual("value2", resp.Values[1]);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void RespondTooManyValues() {
var req = new AttributeRequest();
req.TypeUri = "http://someType";
@@ -67,7 +67,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
req.Respond("value1", "value2");
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void RespondNull() {
var req = new AttributeRequest();
req.TypeUri = "http://someType";
@@ -75,7 +75,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
req.Respond(null);
}
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var req1 = new FetchRequest();
var req2 = new FetchRequest();
@@ -100,7 +100,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that the class is serializable.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Serializable() {
var fetch = new FetchRequest();
fetch.Attributes.AddRequired("http://someAttribute");
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs
index d7082c3..c545a46 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/FetchResponseTests.cs
@@ -9,37 +9,37 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using System.IO;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.Test.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class FetchResponseTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void AddAttribute() {
var response = new FetchResponse();
response.Attributes.Add(new AttributeValues("http://someattribute", "Value1"));
}
- [TestMethod]
+ [TestCase]
public void AddTwoAttributes() {
var response = new FetchResponse();
response.Attributes.Add(new AttributeValues("http://someattribute", "Value1"));
response.Attributes.Add(new AttributeValues("http://someOtherAttribute", "Value2"));
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void AddAttributeTwice() {
var response = new FetchResponse();
response.Attributes.Add(new AttributeValues("http://someattribute", "Value1"));
response.Attributes.Add(new AttributeValues("http://someattribute", "Value1"));
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void AddAttributeNull() {
var response = new FetchResponse();
response.Attributes.Add(null);
}
- [TestMethod]
+ [TestCase]
public void GetAttributeValue() {
var response = new FetchResponse();
@@ -55,7 +55,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual("a", response.GetAttributeValue("http://someattribute3"));
}
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var response1 = new FetchResponse();
var response2 = new FetchResponse();
@@ -80,7 +80,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that the class is serializable.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Serializable() {
var fetch = new FetchResponse();
fetch.Attributes.Add("http://someAttribute", "val1", "val2");
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs
index b11c469..fc486aa 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreRequestTests.cs
@@ -12,14 +12,14 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class StoreRequestTests {
/// <summary>
/// Verifies the constructor behavior.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Ctor() {
var req = new StoreRequest();
Assert.IsFalse(req.Attributes.Any());
@@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies the AddAttribute method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddAttributeByValue() {
var req = new StoreRequest();
AttributeValues value = new AttributeValues();
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies the AddAttribute method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddAttributeByPrimitives() {
var req = new StoreRequest();
req.Attributes.Add("http://att1", "value1", "value2");
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies the Equals method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var req1 = new StoreRequest();
var req2 = new StoreRequest();
@@ -71,7 +71,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies that the class is serializable.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Serializable() {
var store = new StoreRequest();
store.Attributes.Add("http://someAttribute", "val1", "val2");
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs
index 4e432e1..564ef7f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/AttributeExchange/StoreResponseTests.cs
@@ -7,14 +7,14 @@
namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
using System.IO;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class StoreResponseTests {
/// <summary>
/// Verifies the constructor's behavior.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Ctor() {
var response = new StoreResponse();
Assert.IsTrue(response.Succeeded, "The default status should be Succeeded.");
@@ -28,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies the Equals method.
/// </summary>
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
var response1 = new StoreResponse();
var response2 = new StoreResponse();
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Verifies that the class is serializable.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Serializable() {
var store = new StoreResponse();
store.Succeeded = false;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs
index 1fb3160..1b1dd49 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperOPTests.cs
@@ -14,14 +14,14 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ExtensionsInteropHelperOPTests : OpenIdTestBase {
private AuthenticationRequest request;
private IList<IExtensionMessage> extensions;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -36,7 +36,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies no extensions appear as no extensions
/// </summary>
- [TestMethod]
+ [TestCase]
public void NoRequestedExtensions() {
var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.request);
Assert.IsNull(sreg);
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreSame(sregResponse, extensions.Single());
}
- [TestMethod]
+ [TestCase]
public void NegativeResponse() {
this.request.IsAuthenticated = false;
ExtensionsInteropHelper.ConvertSregToMatchRequest(this.request);
@@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies sreg coming in is seen as sreg.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregWithSreg() {
var sregInjected = new ClaimsRequest(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns) {
Nickname = DemandLevel.Request,
@@ -81,7 +81,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies AX coming in looks like sreg.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregWithAX() {
this.ParameterizedAXTest(AXAttributeFormats.AXSchemaOrg);
}
@@ -89,7 +89,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies AX coming in looks like sreg.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregWithAXSchemaOpenIdNet() {
this.ParameterizedAXTest(AXAttributeFormats.SchemaOpenIdNet);
}
@@ -97,7 +97,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies sreg and AX in one request has a preserved sreg request.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregWithBothSregAndAX() {
var sregInjected = new ClaimsRequest(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns) {
Nickname = DemandLevel.Request,
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs
index 7edec09..44a629a 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPRequestTests.cs
@@ -5,20 +5,21 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Test.OpenId.Extensions {
+ using System.Collections.ObjectModel;
using System.Linq;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions;
using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ExtensionsInteropHelperRPRequestTests : OpenIdTestBase {
private AuthenticationRequest authReq;
private ClaimsRequest sreg;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -41,7 +42,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that without an Sreg extension to copy from, no AX extension request is added.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SpreadSregToAXNoExtensions() {
ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg);
Assert.AreEqual(0, this.authReq.AppliedExtensions.Count());
@@ -50,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that Sreg requests are correctly copied to axschema.org AX requests.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SpreadSregToAXBasic() {
this.authReq.AddExtension(this.sreg);
ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg);
@@ -69,7 +70,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that sreg can spread to multiple AX schemas.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SpreadSregToAxMultipleSchemas() {
this.authReq.AddExtension(this.sreg);
ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg | AXAttributeFormats.SchemaOpenIdNet);
@@ -82,7 +83,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies no spread if the OP advertises sreg support.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SpreadSregToAxNoOpIfOPSupportsSreg() {
this.authReq.AddExtension(this.sreg);
this.InjectAdvertisedTypeUri(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns);
@@ -93,7 +94,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies a targeted AX request if the OP advertises a recognized type URI format.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SpreadSregToAxTargetedAtOPFormat() {
this.authReq.AddExtension(this.sreg);
this.InjectAdvertisedTypeUri(WellKnownAttributes.Name.FullName);
@@ -106,7 +107,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that TransformAXFormat correctly translates AX schema Type URIs.
/// </summary>
- [TestMethod]
+ [TestCase]
public void TransformAXFormatTest() {
Assert.AreEqual(WellKnownAttributes.Name.Alias, ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.AXSchemaOrg));
Assert.AreEqual("http://schema.openid.net/namePerson/friendly", ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet));
@@ -118,11 +119,9 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// </summary>
/// <param name="typeUri">The type URI.</param>
private void InjectAdvertisedTypeUri(string typeUri) {
- var serviceEndpoint = ServiceEndpoint_Accessor.AttachShadow(((ServiceEndpoint)this.authReq.Provider));
- serviceEndpoint.ProviderDescription = ProviderEndpointDescription_Accessor.AttachShadow(
- new ProviderEndpointDescription(
- serviceEndpoint.ProviderDescription.Endpoint,
- serviceEndpoint.ProviderDescription.Capabilities.Concat(new[] { typeUri })));
+ var serviceEndpoint = (IdentifierDiscoveryResult)this.authReq.Provider;
+ serviceEndpoint.SetCapabilitiesForTestHook(
+ new ReadOnlyCollection<string>(serviceEndpoint.Capabilities.Concat(new[] { typeUri }).ToList()));
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs
index 655e616..7b528d0 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperRPResponseTests.cs
@@ -13,14 +13,14 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ExtensionsInteropHelperRPResponseTests : OpenIdTestBase {
private IAuthenticationResponse response;
private IList<IExtensionMessage> extensions;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that with no extensions present, UnifyExtensionsAsSreg returns an empty ClaimsResponse.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregNoExtensions() {
var sreg = ExtensionsInteropHelper.UnifyExtensionsAsSreg(this.response, true);
Assert.IsNotNull(sreg);
@@ -42,7 +42,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies that with sreg and AX extensions present, the sreg extension is returned.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregWithSreg() {
var sregInjected = new ClaimsResponse {
Nickname = "andy",
@@ -59,7 +59,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies UnifyExtensionsAsSreg correctly converts AX to sreg.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsAsSregFromAXSchemaOrg() {
var axInjected = new FetchResponse();
axInjected.Attributes.Add(WellKnownAttributes.Name.Alias, "nate");
@@ -71,7 +71,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Verifies UnifyExtensionsAsSreg correctly converts AX in a non-standard format to sreg.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UnifyExtensionsasSregFromSchemaOpenIdNet() {
var axInjected = new FetchResponse();
axInjected.Attributes.Add(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet), "nate");
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs
index 75737ab..6f35f85 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PapeRoundTripTests.cs
@@ -9,18 +9,18 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy;
using DotNetOpenAuth.Test.OpenId.Extensions;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PapeRoundTripTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void Trivial() {
var request = new PolicyRequest();
var response = new PolicyResponse();
ExtensionTestUtilities.Roundtrip(Protocol.Default, new[] { request }, new[] { response });
}
- [TestMethod]
+ [TestCase]
public void Full() {
var request = new PolicyRequest();
request.MaximumAuthenticationAge = TimeSpan.FromMinutes(10);
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs
index 303c747..d75eccc 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequestTests.cs
@@ -13,11 +13,11 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PolicyRequestTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void Ctor() {
PolicyRequest req = new PolicyRequest();
Assert.IsNull(req.MaximumAuthenticationAge);
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(0, req.PreferredPolicies.Count);
}
- [TestMethod]
+ [TestCase]
public void MaximumAuthenticationAgeTest() {
PolicyRequest req = new PolicyRequest();
req.MaximumAuthenticationAge = TimeSpan.FromHours(1);
@@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.IsNull(req.MaximumAuthenticationAge);
}
- [TestMethod]
+ [TestCase]
public void AddPolicies() {
PolicyRequest resp = new PolicyRequest();
resp.PreferredPolicies.Add(AuthenticationPolicies.MultiFactor);
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(AuthenticationPolicies.PhishingResistant, resp.PreferredPolicies[1]);
}
- [TestMethod]
+ [TestCase]
public void AddPolicyMultipleTimes() {
// Although this isn't really the desired behavior (we'd prefer to see an
// exception thrown), since we're using a List<string> internally we can't
@@ -57,7 +57,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(2, resp.PreferredPolicies.Count);
}
- [TestMethod]
+ [TestCase]
public void AddAuthLevelTypes() {
PolicyRequest req = new PolicyRequest();
req.PreferredAuthLevelTypes.Add(Constants.AssuranceLevels.NistTypeUri);
@@ -65,7 +65,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.IsTrue(req.PreferredAuthLevelTypes.Contains(Constants.AssuranceLevels.NistTypeUri));
}
- [TestMethod]
+ [TestCase]
public void EqualsTest() {
PolicyRequest req = new PolicyRequest();
PolicyRequest req2 = new PolicyRequest();
@@ -104,7 +104,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(req, req2);
}
- [TestMethod]
+ [TestCase]
public void Serialize() {
PolicyRequest req = new PolicyRequest();
IMessageWithEvents reqEvents = req;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs
index e0faaac..7491e21 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponseTests.cs
@@ -12,15 +12,15 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PolicyResponseTests : OpenIdTestBase {
private static readonly DateTime someLocalTime = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Local);
private static readonly DateTime someUtcTime = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Utc);
private static readonly DateTime someUnspecifiedTime = new DateTime(2008, 1, 1, 1, 1, 1, 0, DateTimeKind.Unspecified);
- [TestMethod]
+ [TestCase]
public void Ctor() {
PolicyResponse resp = new PolicyResponse();
Assert.IsNotNull(resp.ActualPolicies);
@@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.IsNull(resp.NistAssuranceLevel);
}
- [TestMethod]
+ [TestCase]
public void AddPolicies() {
PolicyResponse resp = new PolicyResponse();
resp.ActualPolicies.Add(AuthenticationPolicies.MultiFactor);
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(AuthenticationPolicies.PhishingResistant, resp.ActualPolicies[1]);
}
- [TestMethod]
+ [TestCase]
public void AddPolicyMultipleTimes() {
// Although this isn't really the desired behavior (we'd prefer to see an
// exception thrown), since we're using a List<string> internally we can't
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(2, resp.ActualPolicies.Count);
}
- [TestMethod]
+ [TestCase]
public void AuthenticationTimeUtcConvertsToUtc() {
PolicyResponse resp = new PolicyResponse();
resp.AuthenticationTimeUtc = someLocalTime;
@@ -60,20 +60,20 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(someLocalTime.ToUniversalTime(), resp.AuthenticationTimeUtc.Value);
}
- [TestMethod]
+ [TestCase]
public void AuthenticationTimeUtcSetUtc() {
PolicyResponse resp = new PolicyResponse();
resp.AuthenticationTimeUtc = someUtcTime;
Assert.AreEqual(someUtcTime, resp.AuthenticationTimeUtc);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void AuthenticationTimeUtcSetUnspecified() {
PolicyResponse resp = new PolicyResponse();
resp.AuthenticationTimeUtc = someUnspecifiedTime;
}
- [TestMethod]
+ [TestCase]
public void AuthenticationTimeUtcSetNull() {
PolicyResponse resp = new PolicyResponse();
resp.AuthenticationTimeUtc = null;
@@ -84,7 +84,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.IsNull(resp.AuthenticationTimeUtc);
}
- [TestMethod]
+ [TestCase]
public void NistAssuranceLevelSetVarious() {
PolicyResponse resp = new PolicyResponse();
resp.NistAssuranceLevel = NistAssuranceLevel.Level1;
@@ -95,7 +95,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(NistAssuranceLevel.InsufficientForLevel1, resp.NistAssuranceLevel);
}
- [TestMethod]
+ [TestCase]
public void AssuranceLevels() {
PolicyResponse resp = new PolicyResponse();
Assert.AreEqual(0, resp.AssuranceLevels.Count);
@@ -108,7 +108,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.IsNull(resp.NistAssuranceLevel);
}
- [TestMethod]
+ [TestCase]
public void EqualsTest() {
PolicyResponse resp = new PolicyResponse();
PolicyResponse resp2 = new PolicyResponse();
@@ -164,7 +164,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.ProviderAuthenticationPolicy {
Assert.AreEqual(resp, resp2);
}
- [TestMethod]
+ [TestCase]
public void Serialize() {
PolicyResponse resp = new PolicyResponse();
IMessageWithEvents respEvents = resp;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs
index 3af54d3..f7a948e 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsRequestTests.cs
@@ -8,11 +8,11 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ClaimsRequestTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void CreateResponse() {
// some unofficial type URIs...
this.ParameterizedTypeUriPreservedTest("http://openid.net/sreg/1.0");
@@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
this.ParameterizedTypeUriPreservedTest("http://openid.net/extensions/sreg/1.1");
}
- [TestMethod]
+ [TestCase]
public void RequiredOptionalLists() {
ClaimsRequest req = new ClaimsRequest();
MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(req);
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual("nickname,postcode", dictionary["required"]);
}
- [TestMethod]
+ [TestCase]
public void EqualityTests() {
ClaimsRequest req1 = new ClaimsRequest();
ClaimsRequest req2 = new ClaimsRequest();
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs
index 6dbfa4f..0bdc36e 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/SimpleRegistration/ClaimsResponseTests.cs
@@ -12,18 +12,18 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ClaimsResponseTests {
- [TestMethod]
+ [TestCase]
public void EmptyMailAddress() {
ClaimsResponse response = new ClaimsResponse(Constants.sreg_ns);
response.Email = string.Empty;
Assert.IsNull(response.MailAddress);
}
- [TestMethod, Ignore] // serialization no longer supported
+ [TestCase, Ignore("serialization no longer supported")]
public void BinarySerialization() {
ClaimsResponse fields = this.GetFilledData();
MemoryStream ms = new MemoryStream();
@@ -35,7 +35,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual(fields, fields2);
}
- [TestMethod, Ignore] // serialization no longer supported
+ [TestCase, Ignore("serialization no longer supported")]
public void XmlSerialization() {
ClaimsResponse fields = this.GetFilledData();
MemoryStream ms = new MemoryStream();
@@ -47,7 +47,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreEqual(fields, fields2);
}
- [TestMethod]
+ [TestCase]
public void EqualityTest() {
ClaimsResponse fields1 = this.GetFilledData();
@@ -95,7 +95,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.AreNotEqual(fields1, fields2);
}
- [TestMethod]
+ [TestCase]
public void Birthdates() {
var response = new ClaimsResponse();
// Verify that they both start out as null
@@ -124,7 +124,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
Assert.IsFalse(response.BirthDate.HasValue);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void InvalidRawBirthdate() {
var response = new ClaimsResponse();
response.BirthDateRaw = "2008";
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs
index 7a60a32..389fa5d 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/UI/UIRequestTests.cs
@@ -8,19 +8,36 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI {
using System.Globalization;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId.Extensions.UI;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class UIRequestTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void Defaults() {
- UIRequest request = new UIRequest();
+ var request = new UIRequest();
Assert.AreEqual("popup", request.Mode);
Assert.AreEqual(1, request.LanguagePreference.Length);
Assert.AreEqual(CultureInfo.CurrentUICulture, request.LanguagePreference[0]);
+ Assert.IsFalse(request.Icon.HasValue);
+ }
+
+ [TestCase]
+ public void IconEncodingDecoding()
+ {
+ var request = new UIRequest();
+ MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(request);
+ Assert.IsFalse(dictionary.ContainsKey("icon"));
+
+ Assert.IsFalse(request.Icon.HasValue);
+ dictionary["icon"] = "true";
+ Assert.IsTrue(request.Icon.Value);
+
+ dictionary.ClearValues();
+ request.Icon = true;
+ Assert.AreEqual("true", dictionary["icon"]);
}
- [TestMethod]
+ [TestCase]
public void LanguagePreferenceEncodingDecoding() {
var request = new UIRequest();
MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(request);
@@ -42,7 +59,7 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions.UI {
Assert.AreEqual(new CultureInfo("es-ES"), request.LanguagePreference[1]);
}
- [TestMethod]
+ [TestCase]
public void ModeEncoding() {
var request = new UIRequest();
MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(request);
diff --git a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
index cc02265..01e2fdc 100644
--- a/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/IdentifierTests.cs
@@ -9,23 +9,23 @@ namespace DotNetOpenAuth.Test.OpenId {
using System.Collections.Generic;
using System.Linq;
using DotNetOpenAuth.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class IdentifierTests {
private string uri = "http://www.yahoo.com/";
private string uriNoScheme = "www.yahoo.com";
private string uriHttps = "https://www.yahoo.com/";
private string xri = "=arnott*andrew";
- [TestMethod]
+ [TestCase]
public void TryParseNoThrow() {
Identifier id;
Assert.IsFalse(Identifier.TryParse(null, out id));
Assert.IsFalse(Identifier.TryParse(string.Empty, out id));
}
- [TestMethod]
+ [TestCase]
public void TryParse() {
Identifier id;
Assert.IsTrue(Identifier.TryParse("http://host/path", out id));
@@ -34,16 +34,16 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual("=arnott", id.ToString());
}
- [TestMethod]
+ [TestCase]
public void Parse() {
- Assert.IsInstanceOfType(Identifier.Parse(this.uri), typeof(UriIdentifier));
- Assert.IsInstanceOfType(Identifier.Parse(this.xri), typeof(XriIdentifier));
+ Assert.IsInstanceOf<UriIdentifier>(Identifier.Parse(this.uri));
+ Assert.IsInstanceOf<XriIdentifier>(Identifier.Parse(this.xri));
}
/// <summary>
/// Tests conformance with 2.0 spec section 7.2#2
/// </summary>
- [TestMethod]
+ [TestCase]
public void ParseEndUserSuppliedXriIdentifer() {
List<char> symbols = new List<char>(XriIdentifier.GlobalContextSymbols);
symbols.Add('(');
@@ -52,35 +52,35 @@ namespace DotNetOpenAuth.Test.OpenId {
prefixes.AddRange(symbols.Select(s => "xri://" + s.ToString()));
foreach (string prefix in prefixes) {
var id = Identifier.Parse(prefix + "andrew");
- Assert.IsInstanceOfType(id, typeof(XriIdentifier));
+ Assert.IsInstanceOf<XriIdentifier>(id);
}
}
/// <summary>
/// Verifies conformance with 2.0 spec section 7.2#3
/// </summary>
- [TestMethod]
+ [TestCase]
public void ParseEndUserSuppliedUriIdentifier() {
// verify a fully-qualified Uri
var id = Identifier.Parse(this.uri);
- Assert.IsInstanceOfType(id, typeof(UriIdentifier));
+ Assert.IsInstanceOf<UriIdentifier>(id);
Assert.AreEqual(this.uri, ((UriIdentifier)id).Uri.AbsoluteUri);
// verify an HTTPS Uri
id = Identifier.Parse(this.uriHttps);
- Assert.IsInstanceOfType(id, typeof(UriIdentifier));
+ Assert.IsInstanceOf<UriIdentifier>(id);
Assert.AreEqual(this.uriHttps, ((UriIdentifier)id).Uri.AbsoluteUri);
// verify that if the scheme is missing it is added automatically
id = Identifier.Parse(this.uriNoScheme);
- Assert.IsInstanceOfType(id, typeof(UriIdentifier));
+ Assert.IsInstanceOf<UriIdentifier>(id);
Assert.AreEqual(this.uri, ((UriIdentifier)id).Uri.AbsoluteUri);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void ParseNull() {
Identifier.Parse(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void ParseEmpty() {
Identifier.Parse(string.Empty);
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs
index a8648ac..b091062 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateDiffieHellmanRequestTests.cs
@@ -8,24 +8,24 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using System;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociateDiffieHellmanRequestTests {
private static readonly Uri Recipient = new Uri("http://host");
private AssociateDiffieHellmanRequest request;
- [TestInitialize]
+ [SetUp]
public void Setup() {
this.request = new AssociateDiffieHellmanRequest(Protocol.V20.Version, Recipient);
}
- [TestMethod]
+ [TestCase]
public void Ctor() {
Assert.AreEqual(Recipient, this.request.Recipient);
}
- [TestMethod]
+ [TestCase]
public void Mode() {
Assert.AreEqual("associate", this.request.Mode);
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs
index 0957118..f3c18d9 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateRequestTests.cs
@@ -11,31 +11,31 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociateRequestTests : OpenIdTestBase {
private readonly Protocol protocol = Protocol.V20;
private Uri secureRecipient = new Uri("https://hi");
private Uri insecureRecipient = new Uri("http://hi");
private AssociateRequest request;
- [TestInitialize]
+ [SetUp]
public void Setup() {
this.request = new AssociateUnencryptedRequest(this.protocol.Version, this.secureRecipient);
}
- [TestMethod]
+ [TestCase]
public void ConstructorTest() {
Assert.AreEqual(this.secureRecipient, this.request.Recipient);
}
- [TestMethod]
+ [TestCase]
public void Mode() {
Assert.AreEqual(this.protocol.Args.Mode.associate, this.request.Mode);
}
- [TestMethod]
+ [TestCase]
public void MessagePartsTest() {
this.request.AssociationType = this.protocol.Args.SignatureAlgorithm.HMAC_SHA1;
this.request.SessionType = this.protocol.Args.SessionType.NoEncryption;
@@ -51,26 +51,26 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual(this.protocol.Args.SessionType.NoEncryption, dict[this.protocol.openid.session_type]);
}
- [TestMethod]
+ [TestCase]
public void ValidMessageTest() {
this.request = new AssociateUnencryptedRequest(Protocol.V20.Version, this.secureRecipient);
this.request.AssociationType = this.protocol.Args.SignatureAlgorithm.HMAC_SHA1;
this.request.EnsureValidMessage();
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void InvalidMessageTest() {
this.request = new AssociateUnencryptedRequest(Protocol.V20.Version, this.insecureRecipient);
this.request.AssociationType = this.protocol.Args.SignatureAlgorithm.HMAC_SHA1;
this.request.EnsureValidMessage(); // no-encryption only allowed for secure channels.
}
- [TestMethod]
+ [TestCase]
public void RequiredProtection() {
Assert.AreEqual(MessageProtections.None, this.request.RequiredProtection);
}
- [TestMethod]
+ [TestCase]
public void Transport() {
Assert.AreEqual(MessageTransport.Direct, this.request.Transport);
}
@@ -78,7 +78,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
/// <summary>
/// Verifies security settings limit RP's initial associate request
/// </summary>
- [TestMethod]
+ [TestCase]
public void AssociateRequestDeterminedBySecuritySettings() {
Protocol protocol = Protocol.V20;
SecuritySettings securitySettings = new RelyingPartySecuritySettings();
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs
index 1f5e87c..37be1cb 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnencryptedResponseTests.cs
@@ -9,20 +9,20 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociateUnencryptedResponseTests : OpenIdTestBase {
private AssociateUnencryptedResponse response;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
var request = new AssociateUnencryptedRequest(Protocol.V20.Version, new Uri("http://host"));
this.response = new AssociateUnencryptedResponse(request.Version, request);
}
- [TestMethod]
+ [TestCase]
public void ParameterNames() {
this.response.AssociationHandle = "HANDLE";
this.response.AssociationType = "HMAC-SHA1";
@@ -38,12 +38,12 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual("50", fields["expires_in"]);
}
- [TestMethod]
+ [TestCase]
public void RequiredProtection() {
Assert.AreEqual(MessageProtections.None, this.response.RequiredProtection);
}
- [TestMethod]
+ [TestCase]
public void Transport() {
Assert.AreEqual(MessageTransport.Direct, this.response.Transport);
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs
index a6a691d..9b76473 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/AssociateUnsuccessfulResponseTests.cs
@@ -9,20 +9,20 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AssociateUnsuccessfulResponseTests : OpenIdTestBase {
private AssociateUnsuccessfulResponse response;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
var request = new AssociateUnencryptedRequest(Protocol.V20.Version, new Uri("http://host"));
this.response = new AssociateUnsuccessfulResponse(request.Version, request);
}
- [TestMethod]
+ [TestCase]
public void ParameterNames() {
this.response.ErrorMessage = "Some Error";
this.response.AssociationType = "HMAC-SHA1";
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs
index 96a2e23..d2d2cc4 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationRequestTests.cs
@@ -6,16 +6,37 @@
namespace DotNetOpenAuth.Test.OpenId.Messages {
using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Messages;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class CheckAuthenticationRequestTests : OpenIdTestBase {
- [TestInitialize]
- public override void SetUp() {
- base.SetUp();
+ /// <summary>
+ /// Verifies that the check_auth request is sent preserving EXACTLY (non-normalized)
+ /// what is in the positive assertion.
+ /// </summary>
+ /// <remarks>
+ /// This is very important because any normalization
+ /// (like changing https://host:443/ to https://host/) in the message will invalidate the signature
+ /// and cause the authentication to inappropriately fail.
+ /// Designed to verify fix to Trac #198.
+ /// </remarks>
+ [TestCase]
+ public void ExactPositiveAssertionPreservation() {
+ var rp = CreateRelyingParty(true);
+
+ // Initialize the positive assertion response with some data that is NOT in normalized form.
+ var positiveAssertion = new PositiveAssertionResponse(Protocol.Default.Version, RPUri)
+ {
+ ClaimedIdentifier = "https://HOST:443/a",
+ ProviderEndpoint = new Uri("https://anotherHOST:443/b"),
+ };
+
+ var checkAuth = new CheckAuthenticationRequest(positiveAssertion, rp.Channel);
+ var actual = rp.Channel.MessageDescriptions.GetAccessor(checkAuth);
+ Assert.AreEqual("https://HOST:443/a", actual["openid.claimed_id"]);
+ Assert.AreEqual("https://anotherHOST:443/b", actual["openid.op_endpoint"]);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs
index 1e773bd..cbe6638 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckAuthenticationResponseTests.cs
@@ -12,16 +12,16 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class CheckAuthenticationResponseTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod]
+ [TestCase]
public void IsValid() {
Protocol protocol = Protocol.Default;
var request = new CheckAuthenticationRequest(protocol.Version, OPUri);
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs
index 2c9ea12..e33a191 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/CheckIdRequestTests.cs
@@ -12,11 +12,11 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class CheckIdRequestTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs
index 02fa7df..039748f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/DirectErrorResponseTests.cs
@@ -10,13 +10,13 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class DirectErrorResponseTests : OpenIdTestBase {
private DirectErrorResponse response;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -24,7 +24,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
this.response = new DirectErrorResponse(request.Version, request);
}
- [TestMethod]
+ [TestCase]
public void ParameterNames() {
this.response.ErrorMessage = "Some Error";
this.response.Contact = "Andrew Arnott";
@@ -42,7 +42,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
/// Verifies that error messages are created as HTTP 400 errors,
/// per OpenID 2.0 section 5.1.2.2.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ErrorMessagesAsHttp400() {
var httpStatusMessage = (IHttpDirectResponse)this.response;
Assert.AreEqual(HttpStatusCode.BadRequest, httpStatusMessage.HttpStatusCode);
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs
index fdb08eb..c9fb535 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectErrorResponseTests.cs
@@ -10,25 +10,25 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class IndirectErrorResponseTests : OpenIdTestBase {
private IndirectErrorResponse response;
- [TestInitialize]
+ [SetUp]
public void Setup() {
CheckIdRequest request = new CheckIdRequest(Protocol.V20.Version, OPUri, AuthenticationRequestMode.Immediate);
request.ReturnTo = RPUri;
this.response = new IndirectErrorResponse(request);
}
- [TestMethod]
+ [TestCase]
public void Ctor() {
Assert.AreEqual(RPUri, this.response.Recipient);
}
- [TestMethod]
+ [TestCase]
public void ParameterNames() {
this.response.ErrorMessage = "Some Error";
this.response.Contact = "Andrew Arnott";
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs
index 8b0937a..ad6b15d 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/IndirectSignedResponseTests.cs
@@ -16,9 +16,9 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class IndirectSignedResponseTests : OpenIdTestBase {
private const string CreationDateString = "2005-05-15T17:11:51Z";
private readonly DateTime creationDate = DateTime.Parse(CreationDateString, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
private IndirectSignedResponse unsolicited;
private Protocol protocol;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
this.unsolicited = new IndirectSignedResponse(this.protocol.Version, RPUri);
}
- [TestMethod]
+ [TestCase]
public void CtorFromRequest() {
Assert.AreEqual(this.protocol.Args.Mode.id_res, this.response.Mode);
Assert.AreEqual(this.request.Version, this.response.Version);
@@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.IsTrue(DateTime.UtcNow - ((ITamperResistantOpenIdMessage)this.response).UtcCreationDate < TimeSpan.FromSeconds(5));
}
- [TestMethod]
+ [TestCase]
public void CtorUnsolicited() {
Assert.AreEqual(this.protocol.Args.Mode.id_res, this.unsolicited.Mode);
Assert.AreEqual(this.protocol.Version, this.unsolicited.Version);
@@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual(OPUri, this.unsolicited.ProviderEndpoint);
}
- [TestMethod]
+ [TestCase]
public void ResponseNonceSetter() {
const string HybridValue = CreationDateString + "UNIQUE";
var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response);
@@ -74,7 +74,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.IsNull(responseReplay.Nonce);
}
- [TestMethod]
+ [TestCase]
public void ResponseNonceGetter() {
var responseAccessor = IndirectSignedResponse_Accessor.AttachShadow(this.response);
IReplayProtectedProtocolMessage responseReplay = this.response;
@@ -86,7 +86,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual(this.creationDate, responseReplay.UtcCreationDate);
}
- [TestMethod]
+ [TestCase]
public void UtcCreationDateConvertsToUniversal() {
IReplayProtectedProtocolMessage responseReplay = this.response;
DateTime local = DateTime.Parse("1982-01-01", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
@@ -109,7 +109,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual(this.creationDate.Hour, utcCreationDate.Hour, "The hour should match since both times are UTC time.");
}
- [TestMethod]
+ [TestCase]
public void ReturnToDoesNotMatchRecipient() {
// Make sure its valid first, so we know that when it's invalid
// it is due to our tampering.
@@ -127,24 +127,24 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
}
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void GetReturnToArgumentNullKey() {
this.response.GetReturnToArgument(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void GetReturnToArgumentEmptyKey() {
this.response.GetReturnToArgument(string.Empty);
}
- [TestMethod]
+ [TestCase]
public void GetReturnToArgumentDoesNotReturnExtraArgs() {
this.response.ExtraData["a"] = "b";
Assert.IsNull(this.response.GetReturnToArgument("a"));
Assert.AreEqual(0, this.response.GetReturnToParameterNames().Count());
}
- [TestMethod]
+ [TestCase]
public void GetReturnToArgumentAndNames() {
UriBuilder returnToBuilder = new UriBuilder(this.response.ReturnTo);
returnToBuilder.AppendQueryArgs(new Dictionary<string, string> { { "a", "b" } });
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs
index 7876732..c35780d 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/NegativeAssertionResponseTests.cs
@@ -13,16 +13,16 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class NegativeAssertionResponseTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod]
+ [TestCase]
public void Mode() {
var setupRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Setup);
setupRequestV1.ReturnTo = RPUri;
@@ -45,14 +45,14 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.IsFalse(new NegativeAssertionResponse(setupRequestV2).Immediate);
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void UserSetupUrlRequiredInV1Immediate() {
var immediateRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Immediate);
immediateRequestV1.ReturnTo = RPUri;
new NegativeAssertionResponse(immediateRequestV1).EnsureValidMessage();
}
- [TestMethod]
+ [TestCase]
public void UserSetupUrlSetForV1Immediate() {
var immediateRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Immediate);
immediateRequestV1.ReturnTo = RPUri;
@@ -61,7 +61,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
response.EnsureValidMessage();
}
- [TestMethod]
+ [TestCase]
public void UserSetupUrlNotRequiredInV1SetupOrV2() {
var setupRequestV1 = new CheckIdRequest(Protocol.V10.Version, OPUri, AuthenticationRequestMode.Setup);
setupRequestV1.ReturnTo = RPUri;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs
index faa6a91..90d24b1 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/PositiveAssertionResponseTests.cs
@@ -15,9 +15,9 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PositiveAssertionResponseTests : OpenIdTestBase {
private const string CreationDateString = "2005-05-15T17:11:51Z";
private readonly DateTime creationDate = DateTime.Parse(CreationDateString, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
@@ -26,7 +26,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
private PositiveAssertionResponse unsolicited;
private Protocol protocol;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -38,7 +38,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
this.unsolicited = new PositiveAssertionResponse(this.protocol.Version, RPUri);
}
- [TestMethod]
+ [TestCase]
public void CtorFromRequest() {
Assert.AreEqual(this.protocol.Args.Mode.id_res, this.response.Mode);
Assert.AreEqual(this.request.Version, this.response.Version);
@@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
Assert.AreEqual(OPUri, this.response.ProviderEndpoint);
}
- [TestMethod]
+ [TestCase]
public void CtorUnsolicited() {
Assert.AreEqual(this.protocol.Args.Mode.id_res, this.unsolicited.Mode);
Assert.AreEqual(this.protocol.Version, this.unsolicited.Version);
@@ -60,7 +60,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
/// <summary>
/// Verifies that local_id and claimed_id can either be null or specified.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ClaimedIdAndLocalIdSpecifiedIsValid() {
this.response.LocalIdentifier = "http://local";
this.response.ClaimedIdentifier = "http://claimedid";
diff --git a/src/DotNetOpenAuth.Test/OpenId/Messages/SignedResponseRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Messages/SignedResponseRequestTests.cs
index 0177685..bc95f8b 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Messages/SignedResponseRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Messages/SignedResponseRequestTests.cs
@@ -10,9 +10,9 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class SignedResponseRequestTests : OpenIdTestBase {
private Uri providerEndpoint;
private SignedResponseRequest immediatev1;
@@ -20,7 +20,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
private SignedResponseRequest immediatev2;
private SignedResponseRequest setupv2;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -55,7 +55,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
/// This test does not test all the realm-return_to matching rules as that is done in the Realm tests.
/// This test merely checks that the compatibility match occurs at all.
/// </remarks>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void RealmReturnToMismatchV2() {
this.setupv2.Realm = "http://somehost/";
this.setupv2.ReturnTo = new Uri("http://someotherhost/");
@@ -66,7 +66,7 @@ namespace DotNetOpenAuth.Test.OpenId.Messages {
/// Verifies that the validation check throws if the return_to and the realm
/// values are not compatible.
/// </summary>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void RealmReturnToMismatchV1() {
this.setupv1.Realm = "http://somehost/";
this.setupv1.ReturnTo = new Uri("http://someotherhost/");
diff --git a/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs b/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs
index 49bb32c..17ab090 100644
--- a/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/NonIdentityTests.cs
@@ -9,11 +9,11 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class NonIdentityTests : OpenIdTestBase {
- [TestMethod]
+ [TestCase]
public void ExtensionOnlyChannelLevel() {
Protocol protocol = Protocol.V20;
AuthenticationRequestMode mode = AuthenticationRequestMode.Setup;
@@ -25,12 +25,12 @@ namespace DotNetOpenAuth.Test.OpenId {
},
op => {
var request = op.Channel.ReadFromRequest<SignedResponseRequest>();
- Assert.IsNotInstanceOfType(request, typeof(CheckIdRequest));
+ Assert.IsNotInstanceOf<CheckIdRequest>(request);
});
coordinator.Run();
}
- [TestMethod]
+ [TestCase]
public void ExtensionOnlyFacadeLevel() {
Protocol protocol = Protocol.V20;
var coordinator = new OpenIdCoordinator(
@@ -48,7 +48,7 @@ namespace DotNetOpenAuth.Test.OpenId {
var request = (IAnonymousRequest)op.GetRequest();
request.IsApproved = true;
- Assert.IsNotInstanceOfType(request, typeof(CheckIdRequest));
+ Assert.IsNotInstanceOf<CheckIdRequest>(request);
op.SendResponse(request);
});
coordinator.Run();
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
index 0f9d472..d4884e8 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdCoordinator.cs
@@ -57,10 +57,12 @@ namespace DotNetOpenAuth.Test.OpenId {
private void EnsurePartiesAreInitialized() {
if (this.RelyingParty == null) {
this.RelyingParty = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore());
+ this.RelyingParty.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
}
if (this.Provider == null) {
this.Provider = new OpenIdProvider(new StandardProviderApplicationStore());
+ this.Provider.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
index 5034b7e..c7df99a 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.Test.OpenId {
using System;
+ using System.Collections.Generic;
using System.IO;
using System.Reflection;
using DotNetOpenAuth.Configuration;
@@ -15,7 +16,7 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
public class OpenIdTestBase : TestBase {
internal IDirectWebRequestHandler RequestHandler;
@@ -61,7 +62,7 @@ namespace DotNetOpenAuth.Test.OpenId {
protected ProviderSecuritySettings ProviderSecuritySettings { get; private set; }
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -74,7 +75,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Identifier.EqualityOnStrings = true;
}
- [TestCleanup]
+ [TearDown]
public override void Cleanup() {
base.Cleanup();
@@ -116,17 +117,17 @@ namespace DotNetOpenAuth.Test.OpenId {
}
}
- internal static ServiceEndpoint GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl) {
+ internal static IdentifierDiscoveryResult GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl) {
return GetServiceEndpoint(user, providerVersion, servicePriority, useSsl, false);
}
- internal static ServiceEndpoint GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl, bool delegating) {
+ internal static IdentifierDiscoveryResult GetServiceEndpoint(int user, ProtocolVersion providerVersion, int servicePriority, bool useSsl, bool delegating) {
var providerEndpoint = new ProviderEndpointDescription(
useSsl ? OpenIdTestBase.OPUriSsl : OpenIdTestBase.OPUri,
new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI });
var local_id = useSsl ? OPLocalIdentifiersSsl[user] : OPLocalIdentifiers[user];
var claimed_id = delegating ? (useSsl ? VanityUriSsl : VanityUri) : local_id;
- return ServiceEndpoint.CreateForClaimedIdentifier(
+ return IdentifierDiscoveryResult.CreateForClaimedIdentifier(
claimed_id,
claimed_id,
local_id,
@@ -176,6 +177,12 @@ namespace DotNetOpenAuth.Test.OpenId {
}
}
+ internal IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier) {
+ var rp = this.CreateRelyingParty(true);
+ rp.Channel.WebRequestHandler = this.RequestHandler;
+ return rp.Discover(identifier);
+ }
+
protected Realm GetMockRealm(bool useSsl) {
var rpDescription = new RelyingPartyEndpointDescription(useSsl ? RPUriSsl : RPUri, new string[] { Protocol.V20.RPReturnToTypeURI });
return new MockRealm(useSsl ? RPRealmUriSsl : RPRealmUri, rpDescription);
@@ -190,9 +197,21 @@ namespace DotNetOpenAuth.Test.OpenId {
}
protected Identifier GetMockIdentifier(ProtocolVersion providerVersion, bool useSsl, bool delegating) {
- ServiceEndpoint se = GetServiceEndpoint(0, providerVersion, 10, useSsl, delegating);
+ var se = GetServiceEndpoint(0, providerVersion, 10, useSsl, delegating);
UriIdentifier identityUri = (UriIdentifier)se.ClaimedIdentifier;
- return new MockIdentifier(identityUri, this.MockResponder, new ServiceEndpoint[] { se });
+ return new MockIdentifier(identityUri, this.MockResponder, new IdentifierDiscoveryResult[] { se });
+ }
+
+ protected Identifier GetMockDualIdentifier() {
+ Protocol protocol = Protocol.Default;
+ var opDesc = new ProviderEndpointDescription(OPUri, protocol.Version);
+ var dualResults = new IdentifierDiscoveryResult[] {
+ IdentifierDiscoveryResult.CreateForClaimedIdentifier(VanityUri.AbsoluteUri, OPLocalIdentifiers[0], opDesc, 10, 10),
+ IdentifierDiscoveryResult.CreateForProviderIdentifier(protocol.ClaimedIdentifierForOPIdentifier, opDesc, 20, 20),
+ };
+
+ Identifier dualId = new MockIdentifier(VanityUri, this.MockResponder, dualResults);
+ return dualId;
}
/// <summary>
@@ -211,6 +230,7 @@ namespace DotNetOpenAuth.Test.OpenId {
protected OpenIdRelyingParty CreateRelyingParty(bool stateless) {
var rp = new OpenIdRelyingParty(stateless ? null : new StandardRelyingPartyApplicationStore());
rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ rp.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
return rp;
}
@@ -221,6 +241,7 @@ namespace DotNetOpenAuth.Test.OpenId {
protected OpenIdProvider CreateProvider() {
var op = new OpenIdProvider(new StandardProviderApplicationStore());
op.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+ op.DiscoveryServices.Add(new MockIdentifierDiscoveryService());
return op;
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdUtilitiesTests.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdUtilitiesTests.cs
new file mode 100644
index 0000000..fefb852
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdUtilitiesTests.cs
@@ -0,0 +1,20 @@
+//-----------------------------------------------------------------------
+// <copyright file="OpenIdUtilitiesTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.Messages;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class OpenIdUtilitiesTests : OpenIdTestBase {
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs
index 14fef91..1df4c9e 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/AnonymousRequestTests.cs
@@ -9,14 +9,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AnonymousRequestTests : OpenIdTestBase {
/// <summary>
/// Verifies that IsApproved controls which response message is returned.
/// </summary>
- [TestMethod]
+ [TestCase]
public void IsApprovedDeterminesReturnedMessage() {
var op = CreateProvider();
Protocol protocol = Protocol.V20;
@@ -27,11 +27,11 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
Assert.IsFalse(anonReq.IsApproved.HasValue);
anonReq.IsApproved = false;
- Assert.IsInstanceOfType(anonReq.Response, typeof(NegativeAssertionResponse));
+ Assert.IsInstanceOf<NegativeAssertionResponse>(anonReq.Response);
anonReq.IsApproved = true;
- Assert.IsInstanceOfType(anonReq.Response, typeof(IndirectSignedResponse));
- Assert.IsNotInstanceOfType(anonReq.Response, typeof(PositiveAssertionResponse));
+ Assert.IsInstanceOf<IndirectSignedResponse>(anonReq.Response);
+ Assert.IsNotInstanceOf<PositiveAssertionResponse>(anonReq.Response);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs
index accbd97..dc5b3e3 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/AuthenticationRequestTest.cs
@@ -10,14 +10,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AuthenticationRequestTest : OpenIdTestBase {
/// <summary>
/// Verifies the user_setup_url is set properly for immediate negative responses.
/// </summary>
- [TestMethod]
+ [TestCase]
public void UserSetupUrl() {
// Construct a V1 immediate request
Protocol protocol = Protocol.V11;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs
index d308271..9bb8095 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/HostProcessedRequestTests.cs
@@ -9,16 +9,16 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class HostProcessedRequestTests : OpenIdTestBase {
private Protocol protocol;
private OpenIdProvider provider;
private CheckIdRequest checkIdRequest;
private AuthenticationRequest request;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -30,12 +30,12 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
this.request = new AuthenticationRequest(this.provider, this.checkIdRequest);
}
- [TestMethod]
+ [TestCase]
public void IsReturnUrlDiscoverableNoResponse() {
Assert.AreEqual(RelyingPartyDiscoveryResult.NoServiceDocument, this.request.IsReturnUrlDiscoverable(this.provider));
}
- [TestMethod]
+ [TestCase]
public void IsReturnUrlDiscoverableValidResponse() {
this.MockResponder.RegisterMockRPDiscovery();
this.request = new AuthenticationRequest(this.provider, this.checkIdRequest);
@@ -46,7 +46,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// Verifies that when discovery would be performed over standard HTTP and RequireSsl
/// is set, that discovery fails.
/// </summary>
- [TestMethod]
+ [TestCase]
public void IsReturnUrlDiscoverableNotSsl() {
this.provider.SecuritySettings.RequireSsl = true;
this.MockResponder.RegisterMockRPDiscovery();
@@ -56,7 +56,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies that when discovery would be performed over HTTPS that discovery succeeds.
/// </summary>
- [TestMethod]
+ [TestCase]
public void IsReturnUrlDiscoverableRequireSsl() {
this.MockResponder.RegisterMockRPDiscovery();
this.checkIdRequest.Realm = RPRealmUriSsl;
@@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
Assert.AreEqual(RelyingPartyDiscoveryResult.Success, this.request.IsReturnUrlDiscoverable(this.provider));
}
- [TestMethod]
+ [TestCase]
public void IsReturnUrlDiscoverableValidButNoMatch() {
this.MockResponder.RegisterMockRPDiscovery();
this.provider.SecuritySettings.RequireSsl = false; // reset for another failure test case
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
index 8528aa7..75d871c 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
@@ -15,13 +15,13 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Test.Hosting;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OpenIdProviderTests : OpenIdTestBase {
private OpenIdProvider provider;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -31,7 +31,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies that the constructor throws an exception if the app store is null.
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNull() {
new OpenIdProvider(null);
}
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies that the SecuritySettings property throws when set to null.
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SecuritySettingsSetNull() {
this.provider.SecuritySettings = null;
}
@@ -47,25 +47,25 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies the SecuritySettings property can be set to a new instance.
/// </summary>
- [TestMethod]
+ [TestCase]
public void SecuritySettings() {
var newSettings = new ProviderSecuritySettings();
this.provider.SecuritySettings = newSettings;
Assert.AreSame(newSettings, this.provider.SecuritySettings);
}
- [TestMethod]
+ [TestCase]
public void ExtensionFactories() {
var factories = this.provider.ExtensionFactories;
Assert.IsNotNull(factories);
Assert.AreEqual(1, factories.Count);
- Assert.IsInstanceOfType(factories[0], typeof(StandardOpenIdExtensionFactory));
+ Assert.IsInstanceOf<StandardOpenIdExtensionFactory>(factories[0]);
}
/// <summary>
/// Verifies the Channel property.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ChannelGetter() {
Assert.IsNotNull(this.provider.Channel);
}
@@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies the GetRequest method throws outside an HttpContext.
/// </summary>
- [TestMethod, ExpectedException(typeof(InvalidOperationException))]
+ [TestCase, ExpectedException(typeof(InvalidOperationException))]
public void GetRequestNoContext() {
HttpContext.Current = null;
this.provider.GetRequest();
@@ -82,7 +82,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies GetRequest throws on null input.
/// </summary>
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void GetRequestNull() {
this.provider.GetRequest(null);
}
@@ -90,7 +90,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
/// <summary>
/// Verifies that GetRequest correctly returns the right messages.
/// </summary>
- [TestMethod]
+ [TestCase]
public void GetRequest() {
HttpRequestInfo httpInfo = new HttpRequestInfo();
httpInfo.UrlBeforeRewriting = new Uri("http://someUri");
@@ -104,13 +104,13 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
},
op => {
IRequest request = op.GetRequest();
- Assert.IsInstanceOfType(request, typeof(AutoResponsiveRequest));
+ Assert.IsInstanceOf<AutoResponsiveRequest>(request);
op.SendResponse(request);
});
coordinator.Run();
}
- [TestMethod]
+ [TestCase]
public void BadRequestsGenerateValidErrorResponses() {
var coordinator = new OpenIdCoordinator(
rp => {
@@ -127,7 +127,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
coordinator.Run();
}
- [TestMethod]
+ [TestCase, Category("HostASPNET")]
public void BadRequestsGenerateValidErrorResponsesHosted() {
try {
using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
index 9f4727d..7984b58 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
@@ -18,28 +18,28 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture, Category("Performance")]
public class PerformanceTests : OpenIdTestBase {
private const string SharedAssociationHandle = "handle";
private static readonly TimeSpan TestRunTime = TimeSpan.FromSeconds(3);
private OpenIdProvider provider;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
SuspendLogging();
this.provider = CreateProvider();
}
- [TestCleanup]
+ [TearDown]
public override void Cleanup() {
ResumeLogging();
base.Cleanup();
}
- [TestMethod]
+ [TestCase]
public void AssociateDH() {
var associateRequest = this.CreateAssociateRequest(OPUri);
Stopwatch timer = new Stopwatch();
@@ -48,15 +48,15 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
IRequest request = this.provider.GetRequest(associateRequest);
var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOfType(response.OriginalMessage, typeof(AssociateSuccessfulResponse));
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
}
timer.Stop();
double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestContext.WriteLine("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
+ 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);
}
- [TestMethod]
+ [TestCase]
public void AssociateClearText() {
var associateRequest = this.CreateAssociateRequest(OPUriSsl); // SSL will cause a plaintext association
Stopwatch timer = new Stopwatch();
@@ -65,29 +65,29 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
IRequest request = this.provider.GetRequest(associateRequest);
var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOfType(response.OriginalMessage, typeof(AssociateSuccessfulResponse));
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
}
timer.Stop();
double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestContext.WriteLine("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
+ 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);
}
- [TestMethod]
+ [TestCase]
public void CheckIdSharedHmacSha1Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA1;
double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestContext.WriteLine("{0} executions per second.", executionsPerSecond);
+ TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
Assert.IsTrue(executionsPerSecond > 500, "Too slow ({0} > 500 executions per second required.)", executionsPerSecond);
}
- [TestMethod]
+ [TestCase]
public void CheckIdSharedHmacSha256Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA256;
double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestContext.WriteLine("{0} executions per second.", executionsPerSecond);
+ TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
Assert.IsTrue(executionsPerSecond > 400, "Too slow ({0} > 400 executions per second required.)", executionsPerSecond);
}
@@ -110,11 +110,11 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
request.IsAuthenticated = true;
var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOfType(response.OriginalMessage, typeof(PositiveAssertionResponse));
+ Assert.IsInstanceOf<PositiveAssertionResponse>(response.OriginalMessage);
}
timer.Stop();
double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestContext.WriteLine("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
+ TestUtilities.TestLogger.InfoFormat("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
return executionsPerSecond;
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs b/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs
index 089265f..65185fc 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ProviderEndpointDescriptionTests.cs
@@ -6,57 +6,23 @@
namespace DotNetOpenAuth.Test.OpenId {
using System;
+ using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class ProviderEndpointDescriptionTests : OpenIdTestBase {
- private ProviderEndpointDescription se;
-
- private string[] v20TypeUris = { Protocol.V20.ClaimedIdentifierServiceTypeURI };
-
- [TestInitialize]
- public override void SetUp() {
- base.SetUp();
-
- this.se = new ProviderEndpointDescription(OPUri, Protocol.V20.Version);
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
- public void IsExtensionSupportedNullType() {
- this.se.IsExtensionSupported((Type)null);
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentException))]
- public void IsExtensionSupportedNullString() {
- this.se.IsExtensionSupported((string)null);
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentException))]
- public void IsExtensionSupportedEmptyString() {
- this.se.IsExtensionSupported(string.Empty);
+ [TestCase]
+ public void NonNullCapabilities() {
+ var epd = new ProviderEndpointDescription(OPUri, Protocol.Default.Version);
+ Assert.IsNotNull(epd.Capabilities);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
- public void IsExtensionSupportedNullExtension() {
- this.se.IsExtensionSupported((IOpenIdMessageExtension)null);
- }
-
- [TestMethod]
- public void IsExtensionSupported() {
- this.se = new ProviderEndpointDescription(OPUri, this.v20TypeUris);
- Assert.IsFalse(this.se.IsExtensionSupported<ClaimsRequest>());
- Assert.IsFalse(this.se.IsExtensionSupported(new ClaimsRequest()));
- Assert.IsFalse(this.se.IsExtensionSupported("http://someextension/typeuri"));
-
- this.se = new ProviderEndpointDescription(
- OPUri,
- new[] { Protocol.V20.ClaimedIdentifierServiceTypeURI, "http://someextension", Constants.sreg_ns });
- Assert.IsTrue(this.se.IsExtensionSupported<ClaimsRequest>());
- Assert.IsTrue(this.se.IsExtensionSupported(new ClaimsRequest()));
- Assert.IsTrue(this.se.IsExtensionSupported("http://someextension"));
+ [TestCase, ExpectedException(typeof(ProtocolException))]
+ public void ProtocolDetectionWithoutClues() {
+ new ProviderEndpointDescription(OPUri, new[] { Protocol.V20.HtmlDiscoveryLocalIdKey }); // random type URI irrelevant to detection
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs
index e062e12..fceb15a 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RealmTests.cs
@@ -7,11 +7,11 @@
namespace DotNetOpenAuth.Test {
using System;
using DotNetOpenAuth.OpenId;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class RealmTests {
- [TestMethod]
+ [TestCase]
public void ValidRealmsTest() {
// Just create these. If any are determined to be invalid,
// an exception should be thrown that would fail this test.
@@ -26,67 +26,67 @@ namespace DotNetOpenAuth.Test {
new Realm("http://*.guest.myopenid.com/");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(ArgumentNullException))]
public void InvalidRealmNullString() {
new Realm((string)null);
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(ArgumentNullException))]
public void InvalidRealmNullUri() {
new Realm((Uri)null);
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmEmpty() {
new Realm(string.Empty);
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmBadProtocol() {
new Realm("asdf://www.microsoft.com/");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmNoScheme() {
new Realm("www.guy.com");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmBadWildcard1() {
new Realm("http://*www.my.com");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmBadWildcard2() {
new Realm("http://www.*.com");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmBadWildcard3() {
new Realm("http://www.my.*/");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmTwoWildcards1() {
new Realm("http://**.my.com");
}
- [TestMethod]
+ [TestCase]
[ExpectedException(typeof(UriFormatException))]
public void InvalidRealmTwoWildcards2() {
new Realm("http://*.*.my.com");
}
- [TestMethod]
+ [TestCase]
public void IsSaneTest() {
Assert.IsTrue(new Realm("http://www.myopenid.com").IsSane);
Assert.IsTrue(new Realm("http://myopenid.com").IsSane);
@@ -98,7 +98,7 @@ namespace DotNetOpenAuth.Test {
Assert.IsFalse(new Realm("http://*.co.uk").IsSane);
}
- [TestMethod]
+ [TestCase]
public void IsUrlWithinRealmTests() {
/*
* The openid.return_to URL MUST descend from the openid.trust_root, or the
@@ -166,7 +166,7 @@ namespace DotNetOpenAuth.Test {
Assert.IsFalse(new Realm("http://www.my.com/abc").Contains("http://www.my.com/ABC"));
}
- [TestMethod]
+ [TestCase]
public void ImplicitConversionFromStringTests() {
Realm realm = "http://host";
Assert.AreEqual("host", realm.Host);
@@ -174,7 +174,7 @@ namespace DotNetOpenAuth.Test {
Assert.IsNull(realm);
}
- [TestMethod]
+ [TestCase]
public void ImplicitConversionToStringTests() {
Realm realm = new Realm("http://host/");
string realmString = realm;
@@ -184,7 +184,7 @@ namespace DotNetOpenAuth.Test {
Assert.IsNull(realmString);
}
- [TestMethod]
+ [TestCase]
public void ImplicitConverstionFromUriTests() {
Uri uri = new Uri("http://host");
Realm realm = uri;
@@ -194,7 +194,7 @@ namespace DotNetOpenAuth.Test {
Assert.IsNull(realm);
}
- [TestMethod]
+ [TestCase]
public void EqualsTest() {
Realm testRealm1a = new Realm("http://www.yahoo.com");
Realm testRealm1b = new Realm("http://www.yahoo.com");
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs
index 0ddc76b..001f3fa 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/AuthenticationRequestTests.cs
@@ -16,9 +16,10 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.Test.Mocks;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class AuthenticationRequestTests : OpenIdTestBase {
private readonly Realm realm = new Realm("http://localhost/rp.aspx");
private readonly Identifier claimedId = "http://claimedId";
@@ -26,7 +27,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
private readonly Protocol protocol = Protocol.Default;
private Uri returnTo;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
this.returnTo = new Uri("http://localhost/rp.aspx");
@@ -35,9 +36,9 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies IsDirectedIdentity returns true when appropriate.
/// </summary>
- [TestMethod]
+ [TestCase]
public void IsDirectedIdentity() {
- IAuthenticationRequest_Accessor iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
+ var iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
Assert.IsFalse(iauthRequest.IsDirectedIdentity);
iauthRequest = this.CreateAuthenticationRequest(IdentifierSelect, IdentifierSelect);
@@ -47,9 +48,9 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies ClaimedIdentifier behavior.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ClaimedIdentifier() {
- IAuthenticationRequest_Accessor iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.delegatedLocalId);
+ var iauthRequest = this.CreateAuthenticationRequest(this.claimedId, this.delegatedLocalId);
Assert.AreEqual(this.claimedId, iauthRequest.ClaimedIdentifier);
iauthRequest = this.CreateAuthenticationRequest(IdentifierSelect, IdentifierSelect);
@@ -59,16 +60,16 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies ProviderVersion behavior.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ProviderVersion() {
var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
- Assert.AreEqual(this.protocol.Version, authRequest.endpoint.Protocol.Version);
+ Assert.AreEqual(this.protocol.Version, authRequest.DiscoveryResult.Version);
}
/// <summary>
/// Verifies RedirectingResponse.
/// </summary>
- [TestMethod]
+ [TestCase]
public void CreateRequestMessage() {
OpenIdCoordinator coordinator = new OpenIdCoordinator(
rp => {
@@ -106,7 +107,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies that delegating authentication requests are filtered out when configured to do so.
/// </summary>
- [TestMethod]
+ [TestCase]
public void CreateFiltersDelegatingIdentifiers() {
Identifier id = GetMockIdentifier(ProtocolVersion.V20, false, true);
var rp = CreateRelyingParty();
@@ -122,9 +123,9 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies the Provider property returns non-null.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Provider() {
- IAuthenticationRequest_Accessor authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
+ var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
Assert.IsNotNull(authRequest.Provider);
Assert.AreEqual(OPUri, authRequest.Provider.Uri);
Assert.AreEqual(this.protocol.Version, authRequest.Provider.Version);
@@ -133,9 +134,9 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies that AddCallbackArguments adds query arguments to the return_to URL of the message.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddCallbackArgument() {
- IAuthenticationRequest_Accessor authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
+ var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
Assert.AreEqual(this.returnTo, authRequest.ReturnToUrl);
authRequest.AddCallbackArguments("p1", "v1");
var req = (SignedResponseRequest)authRequest.RedirectingResponse.OriginalMessage;
@@ -147,12 +148,12 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that AddCallbackArguments replaces pre-existing parameter values
/// rather than appending them.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AddCallbackArgumentClearsPreviousArgument() {
UriBuilder returnToWithArgs = new UriBuilder(this.returnTo);
returnToWithArgs.AppendQueryArgs(new Dictionary<string, string> { { "p1", "v1" } });
this.returnTo = returnToWithArgs.Uri;
- IAuthenticationRequest_Accessor authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
+ var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
authRequest.AddCallbackArguments("p1", "v2");
var req = (SignedResponseRequest)authRequest.RedirectingResponse.OriginalMessage;
NameValueCollection query = HttpUtility.ParseQueryString(req.ReturnTo.Query);
@@ -162,32 +163,48 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies identity-less checkid_* request behavior.
/// </summary>
- [TestMethod]
+ [TestCase]
public void NonIdentityRequest() {
- IAuthenticationRequest_Accessor authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
+ var authRequest = this.CreateAuthenticationRequest(this.claimedId, this.claimedId);
authRequest.IsExtensionOnly = true;
Assert.IsTrue(authRequest.IsExtensionOnly);
var req = (SignedResponseRequest)authRequest.RedirectingResponse.OriginalMessage;
- Assert.IsNotInstanceOfType(req, typeof(CheckIdRequest), "An unexpected SignedResponseRequest derived type was generated.");
+ Assert.IsNotInstanceOf<CheckIdRequest>(req, "An unexpected SignedResponseRequest derived type was generated.");
+ }
+
+ /// <summary>
+ /// Verifies that discovery on identifiers that serve as OP identifiers and claimed identifiers
+ /// only generate OP Identifier auth requests.
+ /// </summary>
+ [TestCase]
+ public void DualIdentifierUsedOnlyAsOPIdentifierForAuthRequest() {
+ var rp = this.CreateRelyingParty(true);
+ var results = AuthenticationRequest.Create(GetMockDualIdentifier(), rp, this.realm, this.returnTo, false).ToList();
+ Assert.AreEqual(1, results.Count);
+ Assert.IsTrue(results[0].IsDirectedIdentity);
+
+ // Also test when dual identiifer support is turned on.
+ rp.SecuritySettings.AllowDualPurposeIdentifiers = true;
+ results = AuthenticationRequest.Create(GetMockDualIdentifier(), rp, this.realm, this.returnTo, false).ToList();
+ Assert.AreEqual(1, results.Count);
+ Assert.IsTrue(results[0].IsDirectedIdentity);
}
/// <summary>
/// Verifies that authentication requests are generated first for OPs that respond
/// to authentication requests.
/// </summary>
- [TestMethod, Ignore]
+ [TestCase, Ignore("Not yet implemented")]
public void UnresponsiveProvidersComeLast() {
// TODO: code here
Assert.Inconclusive("Not yet implemented.");
}
- private AuthenticationRequest_Accessor CreateAuthenticationRequest(Identifier claimedIdentifier, Identifier providerLocalIdentifier) {
+ private AuthenticationRequest CreateAuthenticationRequest(Identifier claimedIdentifier, Identifier providerLocalIdentifier) {
ProviderEndpointDescription providerEndpoint = new ProviderEndpointDescription(OPUri, this.protocol.Version);
- ServiceEndpoint endpoint = ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerEndpoint, 10, 5);
- ServiceEndpoint_Accessor endpointAccessor = ServiceEndpoint_Accessor.AttachShadow(endpoint);
+ IdentifierDiscoveryResult endpoint = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerEndpoint, 10, 5);
OpenIdRelyingParty rp = this.CreateRelyingParty();
- AuthenticationRequest_Accessor authRequest = new AuthenticationRequest_Accessor(endpointAccessor, this.realm, this.returnTo, rp);
- return authRequest;
+ return AuthenticationRequest.CreateForTest(endpoint, this.realm, this.returnTo, rp);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs
index a82634a..43d056f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/FailedAuthenticationResponseTests.cs
@@ -12,14 +12,14 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class FailedAuthenticationResponseTests : OpenIdTestBase {
private FailedAuthenticationResponse response;
private ProtocolException exception;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -27,12 +27,12 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
this.response = new FailedAuthenticationResponse(this.exception);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNull() {
new FailedAuthenticationResponse(null);
}
- [TestMethod]
+ [TestCase]
public void CommonProperties() {
Assert.AreEqual(AuthenticationStatus.Failed, this.response.Status);
Assert.AreSame(this.exception, this.response.Exception);
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.IsNull(this.response.FriendlyIdentifierForDisplay);
}
- [TestMethod]
+ [TestCase]
public void CommonMethods() {
Assert.IsNull(this.response.GetExtension<ClaimsRequest>());
Assert.IsNull(this.response.GetExtension(typeof(ClaimsRequest)));
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs
new file mode 100644
index 0000000..896cf57
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/IdentifierDiscoveryResultTests.cs
@@ -0,0 +1,199 @@
+//-----------------------------------------------------------------------
+// <copyright file="IdentifierDiscoveryResultTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.Messages;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Messaging;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class IdentifierDiscoveryResultTests : OpenIdTestBase {
+ private UriIdentifier claimedId = new UriIdentifier("http://claimedid.justatest.com");
+ private XriIdentifier claimedXri = new XriIdentifier("=!9B72.7DD1.50A9.5CCD");
+ private XriIdentifier userSuppliedXri = new XriIdentifier("=Arnot");
+ private Uri providerEndpoint = new Uri("http://someprovider.com");
+ private Identifier localId = "http://localid.someprovider.com";
+ private string[] v20TypeUris = { Protocol.V20.ClaimedIdentifierServiceTypeURI };
+ private string[] v11TypeUris = { Protocol.V11.ClaimedIdentifierServiceTypeURI };
+ private int servicePriority = 10;
+ private int uriPriority = 10;
+
+ [SetUp]
+ public override void SetUp() {
+ base.SetUp();
+ }
+
+ [TestCase]
+ public void Ctor() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreEqual(this.claimedId, se.ClaimedIdentifier);
+ Assert.AreSame(this.providerEndpoint, se.ProviderEndpoint);
+ Assert.AreSame(this.localId, se.ProviderLocalIdentifier);
+ CollectionAssert<string>.AreEquivalent(this.v20TypeUris, se.Capabilities);
+ Assert.AreEqual(this.servicePriority, se.ServicePriority);
+ }
+
+ [TestCase]
+ public void CtorImpliedLocalIdentifier() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, null, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreEqual(this.claimedId, se.ClaimedIdentifier);
+ Assert.AreSame(this.providerEndpoint, se.ProviderEndpoint);
+ Assert.AreSame(this.claimedId, se.ProviderLocalIdentifier);
+ CollectionAssert<string>.AreEquivalent(this.v20TypeUris, se.Capabilities);
+ }
+
+ [TestCase]
+ public void ProtocolDetection() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreSame(Protocol.V20, se.Protocol);
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ this.claimedId,
+ this.localId,
+ new ProviderEndpointDescription(this.providerEndpoint, new[] { Protocol.V20.OPIdentifierServiceTypeURI }),
+ this.servicePriority,
+ this.uriPriority);
+ Assert.AreSame(Protocol.V20, se.Protocol);
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v11TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreSame(Protocol.V11, se.Protocol);
+ }
+
+ [TestCase]
+ public void EqualsTests() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ IdentifierDiscoveryResult se2 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), (int?)null, (int?)null);
+ Assert.AreEqual(se2, se);
+ Assert.AreNotEqual(se, null);
+ Assert.AreNotEqual(null, se);
+
+ IdentifierDiscoveryResult se3 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(new UriIdentifier(this.claimedId + "a"), this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreNotEqual(se, se3);
+ se3 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(new Uri(this.providerEndpoint.AbsoluteUri + "a"), this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreNotEqual(se, se3);
+ se3 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId + "a", new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreNotEqual(se, se3);
+ se3 = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v11TypeUris), this.servicePriority, this.uriPriority);
+ Assert.AreNotEqual(se, se3);
+
+ // make sure that Collection<T>.Contains works as desired.
+ var list = new List<IdentifierDiscoveryResult>();
+ list.Add(se);
+ Assert.IsTrue(list.Contains(se2));
+ }
+
+ [TestCase]
+ public void GetFriendlyIdentifierForDisplay() {
+ Uri providerEndpoint = new Uri("http://someprovider");
+ Identifier localId = "someuser";
+ string[] serviceTypeUris = new string[] {
+ Protocol.V20.ClaimedIdentifierServiceTypeURI,
+ };
+ IdentifierDiscoveryResult se;
+
+ // strip of protocol, port, query and fragment
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ "http://someprovider.somedomain.com:79/someuser?query#frag",
+ localId,
+ new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
+ null,
+ null);
+ Assert.AreEqual("someprovider.somedomain.com/someuser", se.FriendlyIdentifierForDisplay);
+
+ // unescape characters
+ Uri foreignUri = new Uri("http://server崎/村");
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(foreignUri, localId, new ProviderEndpointDescription(providerEndpoint, serviceTypeUris), null, null);
+ Assert.AreEqual("server崎/村", se.FriendlyIdentifierForDisplay);
+
+ // restore user supplied identifier to XRIs
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
+ new XriIdentifier("=Arnott崎村"),
+ localId,
+ new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
+ null,
+ null);
+ Assert.AreEqual("=Arnott崎村", se.FriendlyIdentifierForDisplay);
+
+ // If UserSuppliedIdentifier is the same as the ClaimedIdentifier, don't display it twice...
+ se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
+ new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
+ localId,
+ new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
+ null,
+ null);
+ Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", se.FriendlyIdentifierForDisplay);
+ }
+
+ [TestCase]
+ public void IsTypeUriPresent() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ Assert.IsTrue(se.IsTypeUriPresent(Protocol.Default.ClaimedIdentifierServiceTypeURI));
+ Assert.IsFalse(se.IsTypeUriPresent("http://someother"));
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void IsTypeUriPresentNull() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ se.IsTypeUriPresent(null);
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void IsTypeUriPresentEmpty() {
+ IdentifierDiscoveryResult se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
+ se.IsTypeUriPresent(string.Empty);
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
+ public void IsExtensionSupportedNullType() {
+ var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null);
+ se.IsExtensionSupported((Type)null);
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void IsTypeUriPresentNullString() {
+ var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null);
+ se.IsTypeUriPresent((string)null);
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void IsTypeUriPresentEmptyString() {
+ var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null);
+ se.IsTypeUriPresent(string.Empty);
+ }
+
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
+ public void IsExtensionSupportedNullExtension() {
+ var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null);
+ se.IsExtensionSupported((IOpenIdMessageExtension)null);
+ }
+
+ [TestCase]
+ public void IsExtensionSupported() {
+ var se = IdentifierDiscoveryResult.CreateForProviderIdentifier(OPUri, new ProviderEndpointDescription(OPUri, this.v20TypeUris), null, null);
+ Assert.IsFalse(se.IsExtensionSupported<ClaimsRequest>());
+ Assert.IsFalse(se.IsExtensionSupported(new ClaimsRequest()));
+ Assert.IsFalse(se.IsTypeUriPresent("http://someextension/typeuri"));
+
+ se = IdentifierDiscoveryResult.CreateForProviderIdentifier(
+ OPUri,
+ new ProviderEndpointDescription(OPUri, new[] { Protocol.V20.ClaimedIdentifierServiceTypeURI, "http://someextension", Constants.sreg_ns }),
+ null,
+ null);
+ Assert.IsTrue(se.IsExtensionSupported<ClaimsRequest>());
+ Assert.IsTrue(se.IsExtensionSupported(new ClaimsRequest()));
+ Assert.IsTrue(se.IsTypeUriPresent("http://someextension"));
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs
index acf537e..dbb4a42 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/NegativeAuthenticationResponseTests.cs
@@ -13,16 +13,16 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class NegativeAuthenticationResponseTests : OpenIdTestBase {
private const string UserSuppliedIdentifier = "=arnott";
private Protocol protocol;
private NegativeAssertionResponse responseMessage;
private NegativeAuthenticationResponse response;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
@@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
this.response = new NegativeAuthenticationResponse(this.responseMessage);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNull() {
new NegativeAuthenticationResponse(null);
}
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies that immediate/setup modes are correctly detected.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ImmediateVsSetupModes() {
this.responseMessage = new NegativeAssertionResponse(this.protocol.Version, RPUri, this.protocol.Args.Mode.cancel);
this.response = new NegativeAuthenticationResponse(this.responseMessage);
@@ -55,17 +55,17 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
this.responseMessage.ExtraData[AuthenticationRequest.UserSuppliedIdentifierParameterName] = UserSuppliedIdentifier;
this.response = new NegativeAuthenticationResponse(this.responseMessage);
Assert.AreEqual(AuthenticationStatus.SetupRequired, this.response.Status);
- Assert.AreEqual<string>(UserSuppliedIdentifier, this.response.UserSuppliedIdentifier);
+ Assert.AreEqual(UserSuppliedIdentifier, (string)this.response.UserSuppliedIdentifier);
}
- [TestMethod]
+ [TestCase]
public void CommonProperties() {
Assert.IsNull(this.response.Exception);
Assert.IsNull(this.response.ClaimedIdentifier);
Assert.IsNull(this.response.FriendlyIdentifierForDisplay);
}
- [TestMethod]
+ [TestCase]
public void CommonMethods() {
Assert.IsNull(this.response.GetExtension<ClaimsRequest>());
Assert.IsNull(this.response.GetExtension(typeof(ClaimsRequest)));
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
index f6a57e7..b0ec395 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
@@ -12,40 +12,40 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Extensions;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OpenIdRelyingPartyTests : OpenIdTestBase {
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod]
+ [TestCase]
public void CreateRequestDumbMode() {
- var rp = new OpenIdRelyingParty(null);
+ var rp = this.CreateRelyingParty(true);
Identifier id = this.GetMockIdentifier(ProtocolVersion.V20);
var authReq = rp.CreateRequest(id, RPRealmUri, RPUri);
CheckIdRequest requestMessage = (CheckIdRequest)authReq.RedirectingResponse.OriginalMessage;
Assert.IsNull(requestMessage.AssociationHandle);
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void SecuritySettingsSetNull() {
var rp = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore());
rp.SecuritySettings = null;
}
- [TestMethod]
+ [TestCase]
public void ExtensionFactories() {
var rp = new OpenIdRelyingParty(null);
var factories = rp.ExtensionFactories;
Assert.IsNotNull(factories);
Assert.AreEqual(1, factories.Count);
- Assert.IsInstanceOfType(factories[0], typeof(StandardOpenIdExtensionFactory));
+ Assert.IsInstanceOf<StandardOpenIdExtensionFactory>(factories[0]);
}
- [TestMethod]
+ [TestCase]
public void CreateRequest() {
var rp = this.CreateRelyingParty();
StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
@@ -54,7 +54,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.IsNotNull(req);
}
- [TestMethod]
+ [TestCase]
public void CreateRequests() {
var rp = this.CreateRelyingParty();
StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
@@ -63,7 +63,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.AreEqual(1, requests.Count());
}
- [TestMethod]
+ [TestCase]
public void CreateRequestsWithEndpointFilter() {
var rp = this.CreateRelyingParty();
StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
@@ -78,7 +78,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.AreEqual(0, requests.Count());
}
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void CreateRequestOnNonOpenID() {
Uri nonOpenId = new Uri("http://www.microsoft.com/");
var rp = this.CreateRelyingParty();
@@ -86,7 +86,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
rp.CreateRequest(nonOpenId, RPRealmUri, RPUri);
}
- [TestMethod]
+ [TestCase]
public void CreateRequestsOnNonOpenID() {
Uri nonOpenId = new Uri("http://www.microsoft.com/");
var rp = this.CreateRelyingParty();
@@ -99,7 +99,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that incoming positive assertions throw errors if they come from
/// OPs that are not approved by <see cref="OpenIdRelyingParty.EndpointFilter"/>.
/// </summary>
- [TestMethod]
+ [TestCase]
public void AssertionWithEndpointFilter() {
var coordinator = new OpenIdCoordinator(
rp => {
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs
index 67255e3..2c70e0f 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdTextBoxTests.cs
@@ -6,14 +6,14 @@
namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class OpenIdTextBoxTests : OpenIdTestBase {
/// <summary>
/// Verifies that the Text and Identifier properties interact correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void IdentifierTextInteraction() {
var box = new OpenIdTextBox();
Assert.AreEqual(string.Empty, box.Text);
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs
index 1418513..b0586a6 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAnonymousResponseTests.cs
@@ -10,14 +10,14 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PositiveAnonymousResponseTests : OpenIdTestBase {
private readonly Realm realm = new Realm("http://localhost/rp.aspx");
private readonly Uri returnTo = new Uri("http://localhost/rp.aspx");
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies that the Status property returns the correct value.
/// </summary>
- [TestMethod]
+ [TestCase]
public void CtorAndProperties() {
var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);
var ext = new ClaimsResponse();
@@ -43,7 +43,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies the Provider property.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ProviderTest() {
var responseMessage = new IndirectSignedResponse(Protocol.V20.Version, this.returnTo);
responseMessage.ProviderEndpoint = OPUri;
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs
new file mode 100644
index 0000000..e069c44
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="PositiveAuthenticationResponseSnapshotTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Runtime.Serialization;
+ using System.Runtime.Serialization.Formatters.Binary;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Messages;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using Moq;
+
+ [TestClass]
+ public class PositiveAuthenticationResponseSnapshotTests : OpenIdTestBase {
+ /// <summary>
+ /// Verifies that the PositiveAuthenticationResponseSnapshot is serializable,
+ /// as required by the <see cref="OpenIdRelyingPartyAjaxControlBase"/> class.
+ /// </summary>
+ [TestMethod]
+ public void Serializable() {
+ var response = new Mock<IAuthenticationResponse>(MockBehavior.Strict);
+ response.Setup(o => o.ClaimedIdentifier).Returns(VanityUri);
+ response.Setup(o => o.FriendlyIdentifierForDisplay).Returns(VanityUri.AbsoluteUri);
+ response.Setup(o => o.Status).Returns(AuthenticationStatus.Authenticated);
+ response.Setup(o => o.Provider).Returns(new ProviderEndpointDescription(OPUri, Protocol.Default.Version));
+ response.Setup(o => o.GetUntrustedCallbackArguments()).Returns(new Dictionary<string, string>());
+ response.Setup(o => o.GetCallbackArguments()).Returns(new Dictionary<string, string>());
+ var snapshot = new PositiveAuthenticationResponseSnapshot(response.Object);
+ MemoryStream ms = new MemoryStream();
+ IFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(ms, snapshot);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
index 701bcae..25b0607 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
@@ -12,14 +12,15 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using DotNetOpenAuth.Test.Mocks;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class PositiveAuthenticationResponseTests : OpenIdTestBase {
private readonly Realm realm = new Realm("http://localhost/rp.aspx");
private readonly Uri returnTo = new Uri("http://localhost/rp.aspx");
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
@@ -27,7 +28,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// <summary>
/// Verifies good, positive assertions are accepted.
/// </summary>
- [TestMethod]
+ [TestCase]
public void Valid() {
PositiveAssertionResponse assertion = this.GetPositiveAssertion();
ClaimsResponse extension = new ClaimsResponse();
@@ -37,8 +38,8 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
var authResponseAccessor = PositiveAuthenticationResponse_Accessor.AttachShadow(authResponse);
Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status);
Assert.IsNull(authResponse.Exception);
- Assert.AreEqual<string>(assertion.ClaimedIdentifier, authResponse.ClaimedIdentifier);
- Assert.AreEqual<string>(authResponse.Endpoint.FriendlyIdentifierForDisplay, authResponse.FriendlyIdentifierForDisplay);
+ Assert.AreEqual((string)assertion.ClaimedIdentifier, (string)authResponse.ClaimedIdentifier);
+ Assert.AreEqual(authResponse.Endpoint.FriendlyIdentifierForDisplay, authResponse.FriendlyIdentifierForDisplay);
Assert.AreSame(extension, authResponse.GetUntrustedExtension(typeof(ClaimsResponse)));
Assert.AreSame(extension, authResponse.GetUntrustedExtension<ClaimsResponse>());
Assert.IsNull(authResponse.GetCallbackArgument("a"));
@@ -46,11 +47,37 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
}
/// <summary>
+ /// Verifies that discovery verification of a positive assertion can match a dual identifier.
+ /// </summary>
+ [TestCase]
+ public void DualIdentifierMatchesInAssertionVerification() {
+ PositiveAssertionResponse assertion = this.GetPositiveAssertion(true);
+ ClaimsResponse extension = new ClaimsResponse();
+ assertion.Extensions.Add(extension);
+ var rp = CreateRelyingParty();
+ rp.SecuritySettings.AllowDualPurposeIdentifiers = true;
+ new PositiveAuthenticationResponse(assertion, rp); // this will throw if it fails to find a match
+ }
+
+ /// <summary>
+ /// Verifies that discovery verification of a positive assertion cannot match a dual identifier
+ /// if the default settings are in place.
+ /// </summary>
+ [TestCase, ExpectedException(typeof(ProtocolException))]
+ public void DualIdentifierNoMatchInAssertionVerificationByDefault() {
+ PositiveAssertionResponse assertion = this.GetPositiveAssertion(true);
+ ClaimsResponse extension = new ClaimsResponse();
+ assertion.Extensions.Add(extension);
+ var rp = CreateRelyingParty();
+ new PositiveAuthenticationResponse(assertion, rp); // this will throw if it fails to find a match
+ }
+
+ /// <summary>
/// Verifies that the RP rejects signed solicited assertions by an OP that
/// makes up a claimed Id that was not part of the original request, and
/// that the OP has no authority to assert positively regarding.
/// </summary>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void SpoofedClaimedIdDetectionSolicited() {
PositiveAssertionResponse assertion = this.GetPositiveAssertion();
assertion.ProviderEndpoint = new Uri("http://rogueOP");
@@ -63,7 +90,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that the RP rejects positive assertions with HTTP Claimed
/// Cdentifiers when RequireSsl is set to true.
/// </summary>
- [TestMethod, ExpectedException(typeof(ProtocolException))]
+ [TestCase, ExpectedException(typeof(ProtocolException))]
public void InsecureIdentifiersRejectedWithRequireSsl() {
PositiveAssertionResponse assertion = this.GetPositiveAssertion();
var rp = CreateRelyingParty();
@@ -71,7 +98,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
var authResponse = new PositiveAuthenticationResponse(assertion, rp);
}
- [TestMethod]
+ [TestCase]
public void GetCallbackArguments() {
PositiveAssertionResponse assertion = this.GetPositiveAssertion();
var rp = CreateRelyingParty();
@@ -94,10 +121,34 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.IsNull(authResponse.GetCallbackArgument("a"));
}
+ /// <summary>
+ /// Verifies that certain problematic claimed identifiers pass through to the RP response correctly.
+ /// </summary>
+ [TestCase]
+ public void ProblematicClaimedId() {
+ var providerEndpoint = new ProviderEndpointDescription(OpenIdTestBase.OPUri, Protocol.Default.Version);
+ string claimed_id = BaseMockUri + "a./b.";
+ var se = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimed_id, claimed_id, providerEndpoint, null, null);
+ UriIdentifier identityUri = (UriIdentifier)se.ClaimedIdentifier;
+ var mockId = new MockIdentifier(identityUri, this.MockResponder, new IdentifierDiscoveryResult[] { se });
+
+ var positiveAssertion = this.GetPositiveAssertion();
+ positiveAssertion.ClaimedIdentifier = mockId;
+ positiveAssertion.LocalIdentifier = mockId;
+ var rp = CreateRelyingParty();
+ var authResponse = new PositiveAuthenticationResponse(positiveAssertion, rp);
+ Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status);
+ Assert.AreEqual(claimed_id, authResponse.ClaimedIdentifier.ToString());
+ }
+
private PositiveAssertionResponse GetPositiveAssertion() {
+ return this.GetPositiveAssertion(false);
+ }
+
+ private PositiveAssertionResponse GetPositiveAssertion(bool dualIdentifier) {
Protocol protocol = Protocol.Default;
PositiveAssertionResponse assertion = new PositiveAssertionResponse(protocol.Version, this.returnTo);
- assertion.ClaimedIdentifier = this.GetMockIdentifier(protocol.ProtocolVersion, false);
+ assertion.ClaimedIdentifier = dualIdentifier ? this.GetMockDualIdentifier() : this.GetMockIdentifier(protocol.ProtocolVersion, false);
assertion.LocalIdentifier = OPLocalIdentifiers[0];
assertion.ReturnTo = this.returnTo;
assertion.ProviderEndpoint = OPUri;
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs
index 851939e..2f6d218 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/RelyingPartySecuritySettingsTests.cs
@@ -10,20 +10,20 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using System.Linq;
using System.Text;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class RelyingPartySecuritySettingsTests : OpenIdTestBase {
private RelyingPartySecuritySettings settings;
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
this.settings = new RelyingPartySecuritySettings();
}
- [TestMethod]
+ [TestCase]
public void Defaults() {
Assert.IsFalse(this.settings.RejectUnsolicitedAssertions);
Assert.IsFalse(this.settings.RequireSsl, "Default should be to not require SSL.");
@@ -33,7 +33,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that the <see cref="RelyingPartySecuritySettings.RequireSsl"/> property
/// getter/setter are implemented correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RequireSsl() {
this.settings.RequireSsl = true;
Assert.IsTrue(this.settings.RequireSsl);
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that the <see cref="RelyingPartySecuritySettings.RequireDirectedIdentity"/>
/// property getter/setter are implemented correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RequireDirectedIdentity() {
this.settings.RequireDirectedIdentity = true;
Assert.IsTrue(this.settings.RequireDirectedIdentity);
@@ -57,7 +57,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
/// Verifies that the <see cref="RelyingPartySecuritySettings.RequireAssociation"/>
/// property getter/setter are implemented correctly.
/// </summary>
- [TestMethod]
+ [TestCase]
public void RequireAssociation() {
this.settings.RequireAssociation = true;
Assert.IsTrue(this.settings.RequireAssociation);
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/ServiceEndpointTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/ServiceEndpointTests.cs
deleted file mode 100644
index ff15aa3..0000000
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/ServiceEndpointTests.cs
+++ /dev/null
@@ -1,195 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="ServiceEndpointTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
- using DotNetOpenAuth.OpenId.Messages;
- using DotNetOpenAuth.OpenId.RelyingParty;
- using DotNetOpenAuth.Test.Messaging;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class ServiceEndpointTests : OpenIdTestBase {
- private UriIdentifier claimedId = new UriIdentifier("http://claimedid.justatest.com");
- private XriIdentifier claimedXri = new XriIdentifier("=!9B72.7DD1.50A9.5CCD");
- private XriIdentifier userSuppliedXri = new XriIdentifier("=Arnot");
- private Uri providerEndpoint = new Uri("http://someprovider.com");
- private Identifier localId = "http://localid.someprovider.com";
- private string[] v20TypeUris = { Protocol.V20.ClaimedIdentifierServiceTypeURI };
- private string[] v11TypeUris = { Protocol.V11.ClaimedIdentifierServiceTypeURI };
- private int servicePriority = 10;
- private int uriPriority = 10;
-
- [TestMethod]
- public void Ctor() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreEqual(this.claimedId, se.ClaimedIdentifier);
- Assert.AreSame(this.providerEndpoint, se.ProviderEndpoint);
- Assert.AreSame(this.localId, se.ProviderLocalIdentifier);
- CollectionAssert<string>.AreEquivalent(this.v20TypeUris, se.ProviderSupportedServiceTypeUris);
- Assert.AreEqual(this.servicePriority, ((IXrdsProviderEndpoint)se).ServicePriority);
- }
-
- [TestMethod]
- public void CtorImpliedLocalIdentifier() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, null, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreEqual(this.claimedId, se.ClaimedIdentifier);
- Assert.AreSame(this.providerEndpoint, se.ProviderEndpoint);
- Assert.AreSame(this.claimedId, se.ProviderLocalIdentifier);
- CollectionAssert<string>.AreEquivalent(this.v20TypeUris, se.ProviderSupportedServiceTypeUris);
- }
-
- [TestMethod]
- public void ProtocolDetection() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreSame(Protocol.V20, se.Protocol);
- se = ServiceEndpoint.CreateForClaimedIdentifier(
- this.claimedId,
- this.localId,
- new ProviderEndpointDescription(this.providerEndpoint, new[] { Protocol.V20.OPIdentifierServiceTypeURI }),
- this.servicePriority,
- this.uriPriority);
- Assert.AreSame(Protocol.V20, se.Protocol);
- se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v11TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreSame(Protocol.V11, se.Protocol);
- }
-
- [TestMethod, ExpectedException(typeof(ProtocolException))]
- public void ProtocolDetectionWithoutClues() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(
- this.claimedId,
- this.localId,
- new ProviderEndpointDescription(this.providerEndpoint, new[] { Protocol.V20.HtmlDiscoveryLocalIdKey }), // random type URI irrelevant to detection
- this.servicePriority,
- this.uriPriority);
- }
-
- [TestMethod]
- public void SerializationWithUri() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- StringBuilder sb = new StringBuilder();
- using (StringWriter sw = new StringWriter(sb)) {
- se.Serialize(sw);
- }
- using (StringReader sr = new StringReader(sb.ToString())) {
- ServiceEndpoint se2 = ServiceEndpoint.Deserialize(sr);
- Assert.AreEqual(se, se2);
- Assert.AreEqual(se.Protocol.Version, se2.Protocol.Version, "Particularly interested in this, since type URIs are not serialized but version info is.");
- Assert.AreEqual(se.UserSuppliedIdentifier, se2.UserSuppliedIdentifier);
- Assert.AreEqual(se.FriendlyIdentifierForDisplay, se2.FriendlyIdentifierForDisplay);
- }
- }
-
- [TestMethod]
- public void SerializationWithXri() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- StringBuilder sb = new StringBuilder();
- using (StringWriter sw = new StringWriter(sb)) {
- se.Serialize(sw);
- }
- using (StringReader sr = new StringReader(sb.ToString())) {
- ServiceEndpoint se2 = ServiceEndpoint.Deserialize(sr);
- Assert.AreEqual(se, se2);
- Assert.AreEqual(se.Protocol.Version, se2.Protocol.Version, "Particularly interested in this, since type URIs are not serialized but version info is.");
- Assert.AreEqual(se.UserSuppliedIdentifier, se2.UserSuppliedIdentifier);
- Assert.AreEqual(se.FriendlyIdentifierForDisplay, se2.FriendlyIdentifierForDisplay);
- }
- }
-
- [TestMethod]
- public void EqualsTests() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- ServiceEndpoint se2 = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), (int?)null, (int?)null);
- Assert.AreEqual(se2, se);
- Assert.AreNotEqual(se, null);
- Assert.AreNotEqual(null, se);
-
- ServiceEndpoint se3 = ServiceEndpoint.CreateForClaimedIdentifier(new UriIdentifier(this.claimedId + "a"), this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreNotEqual(se, se3);
- se3 = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(new Uri(this.providerEndpoint.AbsoluteUri + "a"), this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreNotEqual(se, se3);
- se3 = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId + "a", new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreNotEqual(se, se3);
- se3 = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedId, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v11TypeUris), this.servicePriority, this.uriPriority);
- Assert.AreNotEqual(se, se3);
-
- // make sure that Collection<T>.Contains works as desired.
- List<ServiceEndpoint> list = new List<ServiceEndpoint>();
- list.Add(se);
- Assert.IsTrue(list.Contains(se2));
- }
-
- [TestMethod]
- public void FriendlyIdentifierForDisplay() {
- Uri providerEndpoint = new Uri("http://someprovider");
- Identifier localId = "someuser";
- string[] serviceTypeUris = new string[] {
- Protocol.V20.ClaimedIdentifierServiceTypeURI,
- };
- ServiceEndpoint se;
-
- // strip of protocol, port, query and fragment
- se = ServiceEndpoint.CreateForClaimedIdentifier(
- "http://someprovider.somedomain.com:79/someuser?query#frag",
- localId,
- new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
- null,
- null);
- Assert.AreEqual("someprovider.somedomain.com/someuser", se.FriendlyIdentifierForDisplay);
-
- // unescape characters
- Uri foreignUri = new Uri("http://server崎/村");
- se = ServiceEndpoint.CreateForClaimedIdentifier(foreignUri, localId, new ProviderEndpointDescription(providerEndpoint, serviceTypeUris), null, null);
- Assert.AreEqual("server崎/村", se.FriendlyIdentifierForDisplay);
-
- // restore user supplied identifier to XRIs
- se = ServiceEndpoint.CreateForClaimedIdentifier(
- new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
- new XriIdentifier("=Arnott崎村"),
- localId,
- new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
- null,
- null);
- Assert.AreEqual("=Arnott崎村", se.FriendlyIdentifierForDisplay);
-
- // If UserSuppliedIdentifier is the same as the ClaimedIdentifier, don't display it twice...
- se = ServiceEndpoint.CreateForClaimedIdentifier(
- new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
- new XriIdentifier("=!9B72.7DD1.50A9.5CCD"),
- localId,
- new ProviderEndpointDescription(providerEndpoint, serviceTypeUris),
- null,
- null);
- Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", se.FriendlyIdentifierForDisplay);
- }
-
- [TestMethod]
- public void IsTypeUriPresent() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- Assert.IsTrue(se.IsTypeUriPresent(Protocol.Default.ClaimedIdentifierServiceTypeURI));
- Assert.IsFalse(se.IsTypeUriPresent("http://someother"));
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentException))]
- public void IsTypeUriPresentNull() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- se.IsTypeUriPresent(null);
- }
-
- [TestMethod, ExpectedException(typeof(ArgumentException))]
- public void IsTypeUriPresentEmpty() {
- ServiceEndpoint se = ServiceEndpoint.CreateForClaimedIdentifier(this.claimedXri, this.userSuppliedXri, this.localId, new ProviderEndpointDescription(this.providerEndpoint, this.v20TypeUris), this.servicePriority, this.uriPriority);
- se.IsTypeUriPresent(string.Empty);
- }
- }
-}
diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
index 5a5182f..5b015ff 100644
--- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs
@@ -13,40 +13,40 @@ namespace DotNetOpenAuth.Test.OpenId {
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class UriIdentifierTests : OpenIdTestBase {
private string goodUri = "http://blog.nerdbank.net/";
private string relativeUri = "host/path";
private string badUri = "som%-)830w8vf/?.<>,ewackedURI";
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ [TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullUri() {
new UriIdentifier((Uri)null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorNullString() {
new UriIdentifier((string)null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorBlank() {
new UriIdentifier(string.Empty);
}
- [TestMethod, ExpectedException(typeof(UriFormatException))]
+ [TestCase, ExpectedException(typeof(UriFormatException))]
public void CtorBadUri() {
new UriIdentifier(this.badUri);
}
- [TestMethod]
+ [TestCase]
public void CtorGoodUri() {
var uri = new UriIdentifier(this.goodUri);
Assert.AreEqual(new Uri(this.goodUri), uri.Uri);
@@ -54,33 +54,33 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(uri.IsDiscoverySecureEndToEnd);
}
- [TestMethod]
+ [TestCase]
public void CtorStringNoSchemeSecure() {
var uri = new UriIdentifier("host/path", true);
Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri);
Assert.IsTrue(uri.IsDiscoverySecureEndToEnd);
}
- [TestMethod]
+ [TestCase]
public void CtorStringHttpsSchemeSecure() {
var uri = new UriIdentifier("https://host/path", true);
Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri);
Assert.IsTrue(uri.IsDiscoverySecureEndToEnd);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorStringHttpSchemeSecure() {
new UriIdentifier("http://host/path", true);
}
- [TestMethod]
+ [TestCase]
public void CtorUriHttpsSchemeSecure() {
var uri = new UriIdentifier(new Uri("https://host/path"), true);
Assert.AreEqual("https://host/path", uri.Uri.AbsoluteUri);
Assert.IsTrue(uri.IsDiscoverySecureEndToEnd);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorUriHttpSchemeSecure() {
new UriIdentifier(new Uri("http://host/path"), true);
}
@@ -93,44 +93,73 @@ namespace DotNetOpenAuth.Test.OpenId {
/// they should NOT be stripped from claimed identifiers. So the UriIdentifier
/// class, which serves both identifier types, must not do the stripping.
/// </remarks>
- [TestMethod]
+ [TestCase]
public void DoesNotStripFragment() {
Uri original = new Uri("http://a/b#c");
UriIdentifier identifier = new UriIdentifier(original);
Assert.AreEqual(original.Fragment, identifier.Uri.Fragment);
}
- [TestMethod]
+ [TestCase]
public void IsValid() {
Assert.IsTrue(UriIdentifier.IsValidUri(this.goodUri));
Assert.IsFalse(UriIdentifier.IsValidUri(this.badUri));
Assert.IsTrue(UriIdentifier.IsValidUri(this.relativeUri), "URL lacking http:// prefix should have worked anyway.");
}
- [TestMethod]
+ [TestCase]
public void TrimFragment() {
Identifier noFragment = UriIdentifier.Parse("http://a/b");
Identifier fragment = UriIdentifier.Parse("http://a/b#c");
Assert.AreSame(noFragment, noFragment.TrimFragment());
- Assert.AreEqual(noFragment, fragment.TrimFragment());
+ Assert.AreEqual(noFragment.ToString(), fragment.TrimFragment().ToString());
+
+ // Try the problematic ones
+ TestAsFullAndPartialTrust(fullTrust => {
+ Identifier noFrag = UriIdentifier.Parse("http://a/b./c");
+ Identifier frag = UriIdentifier.Parse("http://a/b./c#d");
+ Assert.AreSame(noFrag, noFrag.TrimFragment());
+ Assert.AreEqual(noFrag.ToString(), frag.TrimFragment().ToString());
+ });
}
- [TestMethod]
+ [TestCase]
public void ToStringTest() {
Assert.AreEqual(this.goodUri, new UriIdentifier(this.goodUri).ToString());
+ TestAsFullAndPartialTrust(fullTrust => {
+ Assert.AreEqual("http://abc/D./e.?Qq#Ff", new UriIdentifier("HTTP://ABC/D./e.?Qq#Ff").ToString());
+ Assert.AreEqual("http://abc/D./e.?Qq", new UriIdentifier("HTTP://ABC/D./e.?Qq").ToString());
+ Assert.AreEqual("http://abc/D./e.#Ff", new UriIdentifier("HTTP://ABC/D./e.#Ff").ToString());
+ Assert.AreEqual("http://abc/", new UriIdentifier("HTTP://ABC").ToString());
+ Assert.AreEqual("http://abc/?q", new UriIdentifier("HTTP://ABC?q").ToString());
+ Assert.AreEqual("http://abc/#f", new UriIdentifier("HTTP://ABC#f").ToString());
+ });
}
- [TestMethod]
+ [TestCase]
public void EqualsTest() {
- Assert.AreEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri));
- // This next test is an interesting side-effect of passing off to Uri.Equals. But it's probably ok.
- Assert.AreEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri + "#frag"));
- Assert.AreNotEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri + "a"));
- Assert.AreNotEqual(null, new UriIdentifier(this.goodUri));
- Assert.AreEqual(this.goodUri, new UriIdentifier(this.goodUri));
- }
-
- [TestMethod]
+ TestAsFullAndPartialTrust(fulltrust => {
+ Assert.AreEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri));
+ // This next test is an interesting side-effect of passing off to Uri.Equals. But it's probably ok.
+ Assert.AreEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri + "#frag"));
+ Assert.AreEqual(new UriIdentifier("http://a/b./c."), new UriIdentifier("http://a/b./c.#frag"));
+ Assert.AreNotEqual(new UriIdentifier(this.goodUri), new UriIdentifier(this.goodUri + "a"));
+ Assert.AreNotEqual(null, new UriIdentifier(this.goodUri));
+ Assert.IsTrue(new UriIdentifier(this.goodUri).Equals(this.goodUri));
+
+ Assert.AreEqual(Identifier.Parse("HTTP://WWW.FOO.COM/abc", true), Identifier.Parse("http://www.foo.com/abc", true));
+ Assert.AreEqual(Identifier.Parse("HTTP://WWW.FOO.COM/abc", true), Identifier.Parse("http://www.foo.com/abc", false));
+ Assert.AreEqual(Identifier.Parse("HTTP://WWW.FOO.COM/abc", false), Identifier.Parse("http://www.foo.com/abc", false));
+ Assert.AreNotEqual(Identifier.Parse("http://www.foo.com/abc", true), Identifier.Parse("http://www.foo.com/ABC", true));
+ Assert.AreNotEqual(Identifier.Parse("http://www.foo.com/abc", true), Identifier.Parse("http://www.foo.com/ABC", false));
+ Assert.AreNotEqual(Identifier.Parse("http://www.foo.com/abc", false), Identifier.Parse("http://www.foo.com/ABC", false));
+
+ Assert.AreNotEqual(Identifier.Parse("http://a/b./c."), Identifier.Parse("http://a/b/c."));
+ Assert.AreEqual(Identifier.Parse("http://a/b./c."), Identifier.Parse("http://a/b./c."));
+ });
+ }
+
+ [TestCase]
public void UnicodeTest() {
string unicodeUrl = "http://nerdbank.org/opaffirmative/崎村.aspx";
Assert.IsTrue(UriIdentifier.IsValidUri(unicodeUrl));
@@ -140,63 +169,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual(Uri.EscapeUriString(unicodeUrl), id.ToString());
}
- [TestMethod]
- public void HtmlDiscover_11() {
- this.DiscoverHtml("html10prov", ProtocolVersion.V11, null, "http://a/b");
- this.DiscoverHtml("html10both", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html10del");
-
- // Verify that HTML discovery generates the 1.x endpoints when appropriate
- this.DiscoverHtml("html2010", ProtocolVersion.V11, "http://g/h", "http://e/f");
- this.DiscoverHtml("html1020", ProtocolVersion.V11, "http://g/h", "http://e/f");
- this.DiscoverHtml("html2010combinedA", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedB", ProtocolVersion.V11, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedC", ProtocolVersion.V11, "http://c/d", "http://a/b");
- }
-
- [TestMethod]
- public void HtmlDiscover_20() {
- this.DiscoverHtml("html20prov", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverHtml("html20both", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html20del");
- this.DiscoverHtml("html2010", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html1020", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedA", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedB", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.DiscoverHtml("html2010combinedC", ProtocolVersion.V20, "http://c/d", "http://a/b");
- this.FailDiscoverHtml("html20relative");
- }
-
- [TestMethod]
- public void XrdsDiscoveryFromHead() {
- this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
- this.DiscoverXrds("XrdsReferencedInHead.html", ProtocolVersion.V10, null, "http://a/b");
- }
-
- [TestMethod]
- public void XrdsDiscoveryFromHttpHeader() {
- WebHeaderCollection headers = new WebHeaderCollection();
- headers.Add("X-XRDS-Location", new Uri("http://localhost/xrds1020.xml").AbsoluteUri);
- this.MockResponder.RegisterMockResponse(new Uri("http://localhost/xrds1020.xml"), "application/xrds+xml", LoadEmbeddedFile("/Discovery/xrdsdiscovery/xrds1020.xml"));
- this.DiscoverXrds("XrdsReferencedInHttpHeader.html", ProtocolVersion.V10, null, "http://a/b", headers);
- }
-
- [TestMethod]
- public void XrdsDirectDiscovery_10() {
- this.FailDiscoverXrds("xrds-irrelevant");
- this.DiscoverXrds("xrds10", ProtocolVersion.V10, null, "http://a/b");
- this.DiscoverXrds("xrds11", ProtocolVersion.V11, null, "http://a/b");
- this.DiscoverXrds("xrds1020", ProtocolVersion.V10, null, "http://a/b");
- }
-
- [TestMethod]
- public void XrdsDirectDiscovery_20() {
- this.DiscoverXrds("xrds20", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverXrds("xrds2010a", ProtocolVersion.V20, null, "http://a/b");
- this.DiscoverXrds("xrds2010b", ProtocolVersion.V20, null, "http://a/b");
- }
-
- [TestMethod]
+ [TestCase]
public void NormalizeCase() {
// only the host name can be normalized in casing safely.
Identifier id = "http://HOST:80/PaTH?KeY=VaLUE#fRag";
@@ -206,36 +179,66 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.AreEqual("https://host:80/PaTH?KeY=VaLUE#fRag", id.ToString());
}
- [TestMethod]
+ /// <summary>
+ /// Verifies that URIs that contain base64 encoded path segments (such as Yahoo) are properly preserved.
+ /// </summary>
+ /// <remarks>
+ /// Yahoo includes a base64 encoded part as their last path segment,
+ /// which may end with a period. The default .NET Uri parser trims off
+ /// trailing periods, which breaks OpenID unless special precautions are taken.
+ /// </remarks>
+ [TestCase]
+ public void TrailingPeriodsNotTrimmed() {
+ TestAsFullAndPartialTrust(fullTrust => {
+ string claimedIdentifier = "https://me.yahoo.com/a/AsDf.#asdf";
+ Identifier id = claimedIdentifier;
+ Assert.AreEqual(claimedIdentifier, id.OriginalString);
+ Assert.AreEqual(claimedIdentifier, id.ToString());
+
+ UriIdentifier idUri = new UriIdentifier(claimedIdentifier);
+ Assert.AreEqual(claimedIdentifier, idUri.OriginalString);
+ Assert.AreEqual(claimedIdentifier, idUri.ToString());
+ if (fullTrust) {
+ Assert.AreEqual(claimedIdentifier, idUri.Uri.AbsoluteUri);
+ }
+ Assert.AreEqual(Uri.UriSchemeHttps, idUri.Uri.Scheme); // in case custom scheme tricks are played, this must still match
+ Assert.AreEqual("https://me.yahoo.com/a/AsDf.", idUri.TrimFragment().ToString());
+ Assert.AreEqual("https://me.yahoo.com/a/AsDf.", idUri.TrimFragment().OriginalString);
+ Assert.AreEqual(id.ToString(), new UriIdentifier((Uri)idUri).ToString(), "Round tripping UriIdentifier->Uri->UriIdentifier failed.");
+
+ idUri = new UriIdentifier(new Uri(claimedIdentifier));
+ Assert.AreEqual(claimedIdentifier, idUri.OriginalString);
+ Assert.AreEqual(claimedIdentifier, idUri.ToString());
+ if (fullTrust) {
+ Assert.AreEqual(claimedIdentifier, idUri.Uri.AbsoluteUri);
+ }
+ Assert.AreEqual(Uri.UriSchemeHttps, idUri.Uri.Scheme); // in case custom scheme tricks are played, this must still match
+ Assert.AreEqual("https://me.yahoo.com/a/AsDf.", idUri.TrimFragment().ToString());
+ Assert.AreEqual("https://me.yahoo.com/a/AsDf.", idUri.TrimFragment().OriginalString);
+ Assert.AreEqual(id.ToString(), new UriIdentifier((Uri)idUri).ToString(), "Round tripping UriIdentifier->Uri->UriIdentifier failed.");
+
+ claimedIdentifier = "https://me.yahoo.com:443/a/AsDf.#asdf";
+ id = claimedIdentifier;
+ Assert.AreEqual(claimedIdentifier, id.OriginalString);
+ Assert.AreEqual("https://me.yahoo.com/a/AsDf.#asdf", id.ToString());
+ });
+ }
+
+ [TestCase]
public void HttpSchemePrepended() {
UriIdentifier id = new UriIdentifier("www.yahoo.com");
Assert.AreEqual("http://www.yahoo.com/", id.ToString());
Assert.IsTrue(id.SchemeImplicitlyPrepended);
}
- ////[TestMethod, Ignore("The spec says http:// must be prepended in this case, but that just creates an invalid URI. Our UntrustedWebRequest will stop disallowed schemes.")]
+ ////[TestCase, Ignore("The spec says http:// must be prepended in this case, but that just creates an invalid URI. Our UntrustedWebRequest will stop disallowed schemes.")]
public void CtorDisallowedScheme() {
UriIdentifier id = new UriIdentifier(new Uri("ftp://host/path"));
Assert.AreEqual("http://ftp://host/path", id.ToString());
Assert.IsTrue(id.SchemeImplicitlyPrepended);
}
- [TestMethod]
- public void DiscoveryWithRedirects() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, false);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
-
- // don't require secure SSL discovery for this test.
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, false);
- Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
+ [TestCase]
public void TryRequireSslAdjustsIdentifier() {
Identifier secureId;
// Try Parse and ctor without explicit scheme
@@ -256,180 +259,53 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsTrue(secureId.IsDiscoverySecureEndToEnd, "Although the TryRequireSsl failed, the created identifier should retain the Ssl status.");
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover(this.RequestHandler).Count(), "Since TryRequireSsl failed, the created Identifier should never discover anything.");
+ Assert.AreEqual(0, Discover(secureId).Count(), "Since TryRequireSsl failed, the created Identifier should never discover anything.");
id = new UriIdentifier("http://www.yahoo.com");
Assert.IsFalse(id.TryRequireSsl(out secureId));
Assert.IsTrue(secureId.IsDiscoverySecureEndToEnd);
Assert.AreEqual("http://www.yahoo.com/", secureId.ToString());
- Assert.AreEqual(0, secureId.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoverRequireSslWithSecureRedirects() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- // All redirects should be secure.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri secureMidpointUri = new Uri("https://localhost/secureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, secureMidpointUri);
- this.MockResponder.RegisterMockRedirect(secureMidpointUri, new Uri(claimedId.ToString()));
-
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- Assert.AreEqual(1, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod, ExpectedException(typeof(ProtocolException))]
- public void DiscoverRequireSslWithInsecureRedirect() {
- Identifier claimedId = this.GetMockIdentifier(ProtocolVersion.V20, true);
-
- // Add a couple of chained redirect pages that lead to the claimedId.
- // Include an insecure HTTP jump in those redirects to verify that
- // the ultimate endpoint is never found as a result of high security profile.
- Uri userSuppliedUri = new Uri("https://localhost/someSecurePage");
- Uri insecureMidpointUri = new Uri("http://localhost/insecureStop");
- this.MockResponder.RegisterMockRedirect(userSuppliedUri, insecureMidpointUri);
- this.MockResponder.RegisterMockRedirect(insecureMidpointUri, new Uri(claimedId.ToString()));
-
- Identifier userSuppliedIdentifier = new UriIdentifier(userSuppliedUri, true);
- userSuppliedIdentifier.Discover(this.RequestHandler);
+ Assert.AreEqual(0, Discover(secureId).Count());
}
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
- Uri secureClaimedUri = new Uri("https://localhost/secureId");
-
- string html = string.Format("<html><head><meta http-equiv='X-XRDS-Location' content='{0}'/></head><body></body></html>", insecureXrdsSource);
- this.MockResponder.RegisterMockResponse(secureClaimedUri, "text/html", html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(secureClaimedUri, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
-
- string html = "<html><head></head><body></body></html>";
- WebHeaderCollection headers = new WebHeaderCollection {
- { "X-XRDS-Location", insecureXrdsSource }
- };
- this.MockResponder.RegisterMockResponse(VanityUriSsl, VanityUriSsl, "text/html", headers, html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
- Assert.AreEqual(0, userSuppliedIdentifier.Discover(this.RequestHandler).Count());
- }
-
- [TestMethod]
- public void DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags() {
- var insecureXrdsSource = this.GetMockIdentifier(ProtocolVersion.V20, false);
- string html = string.Format(
- @"
- <html><head>
- <meta http-equiv='X-XRDS-Location' content='{0}'/> <!-- this one will be insecure and ignored -->
- <link rel='openid2.provider' href='{1}' />
- <link rel='openid2.local_id' href='{2}' />
- </head><body></body></html>",
- HttpUtility.HtmlEncode(insecureXrdsSource),
- HttpUtility.HtmlEncode(OPUriSsl.AbsoluteUri),
- HttpUtility.HtmlEncode(OPLocalIdentifiersSsl[1].AbsoluteUri));
- this.MockResponder.RegisterMockResponse(VanityUriSsl, "text/html", html);
-
- Identifier userSuppliedIdentifier = new UriIdentifier(VanityUriSsl, true);
-
- // We verify that the XRDS was ignored and the LINK tags were used
- // because the XRDS OP-LocalIdentifier uses different local identifiers.
- Assert.AreEqual(OPLocalIdentifiersSsl[1], userSuppliedIdentifier.Discover(this.RequestHandler).Single().ProviderLocalIdentifier);
- }
-
- [TestMethod]
- public void DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds() {
- var insecureEndpoint = GetServiceEndpoint(0, ProtocolVersion.V20, 10, false);
- var secureEndpoint = GetServiceEndpoint(1, ProtocolVersion.V20, 20, true);
- UriIdentifier secureClaimedId = new UriIdentifier(VanityUriSsl, true);
- this.MockResponder.RegisterMockXrdsResponse(secureClaimedId, new ServiceEndpoint[] { insecureEndpoint, secureEndpoint });
- Assert.AreEqual(secureEndpoint.ProviderLocalIdentifier, secureClaimedId.Discover(this.RequestHandler).Single().ProviderLocalIdentifier);
- }
-
- private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect) {
- this.Discover(url, version, expectedLocalId, providerEndpoint, expectSreg, useRedirect, null);
- }
-
- private void Discover(string url, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool expectSreg, bool useRedirect, WebHeaderCollection headers) {
- Protocol protocol = Protocol.Lookup(version);
- Uri baseUrl = new Uri("http://localhost/");
- UriIdentifier claimedId = new Uri(baseUrl, url);
- UriIdentifier userSuppliedIdentifier = new Uri(baseUrl, "Discovery/htmldiscovery/redirect.aspx?target=" + url);
- if (expectedLocalId == null) {
- expectedLocalId = claimedId;
- }
- Identifier idToDiscover = useRedirect ? userSuppliedIdentifier : claimedId;
-
- string contentType;
- if (url.EndsWith("html")) {
- contentType = "text/html";
- } else if (url.EndsWith("xml")) {
- contentType = "application/xrds+xml";
- } else {
- throw new InvalidOperationException();
- }
- this.MockResponder.RegisterMockResponse(new Uri(idToDiscover), claimedId, contentType, headers ?? new WebHeaderCollection(), LoadEmbeddedFile(url));
-
- ServiceEndpoint expected = ServiceEndpoint.CreateForClaimedIdentifier(
- claimedId,
- expectedLocalId,
- new ProviderEndpointDescription(new Uri(providerEndpoint), new string[] { protocol.ClaimedIdentifierServiceTypeURI }), // services aren't checked by Equals
- null,
- null);
-
- ServiceEndpoint se = idToDiscover.Discover(this.RequestHandler).FirstOrDefault(ep => ep.Equals(expected));
- Assert.IsNotNull(se, url + " failed to be discovered.");
-
- // Do extra checking of service type URIs, which aren't included in
- // the ServiceEndpoint.Equals method.
- Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Count);
- Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Contains(protocol.ClaimedIdentifierServiceTypeURI));
- Assert.AreEqual(expectSreg, se.IsExtensionSupported<ClaimsRequest>());
- }
-
- private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
- this.DiscoverXrds(page, version, expectedLocalId, providerEndpoint, null);
+ /// <summary>
+ /// Verifies that unicode hostnames are handled.
+ /// </summary>
+ [TestCase]
+ public void UnicodeHostSupport() {
+ var id = new UriIdentifier("http://server崎/村");
+ Assert.AreEqual("server崎", id.Uri.Host);
}
- private void DiscoverXrds(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, WebHeaderCollection headers) {
- if (!page.Contains(".")) {
- page += ".xml";
+ /// <summary>
+ /// Verifies SimpleUri behavior
+ /// </summary>
+ [TestCase]
+ public void SimpleUri() {
+ Assert.AreEqual("http://abc/D./e.?Qq#Ff", new UriIdentifier.SimpleUri("HTTP://ABC/D./e.?Qq#Ff").ToString());
+ Assert.AreEqual("http://abc/D./e.?Qq", new UriIdentifier.SimpleUri("HTTP://ABC/D./e.?Qq").ToString());
+ Assert.AreEqual("http://abc/D./e.#Ff", new UriIdentifier.SimpleUri("HTTP://ABC/D./e.#Ff").ToString());
+ Assert.AreEqual("http://abc/", new UriIdentifier.SimpleUri("HTTP://ABC/").ToString());
+ Assert.AreEqual("http://abc/", new UriIdentifier.SimpleUri("HTTP://ABC").ToString());
+ Assert.AreEqual("http://abc/?q", new UriIdentifier.SimpleUri("HTTP://ABC?q").ToString());
+ Assert.AreEqual("http://abc/#f", new UriIdentifier.SimpleUri("HTTP://ABC#f").ToString());
+
+ Assert.AreEqual("http://abc/a//b", new UriIdentifier.SimpleUri("http://abc/a//b").ToString());
+ Assert.AreEqual("http://abc/a%2Fb/c", new UriIdentifier.SimpleUri("http://abc/a%2fb/c").ToString());
+ Assert.AreEqual("http://abc/A/c", new UriIdentifier.SimpleUri("http://abc/%41/c").ToString());
+ }
+
+ private static void TestAsFullAndPartialTrust(Action<bool> action) {
+ // Test a bunch of interesting URLs both with scheme substitution on and off.
+ Assert.IsTrue(UriIdentifier_Accessor.schemeSubstitution, "Expected scheme substitution to be working.");
+ action(true);
+
+ UriIdentifier_Accessor.schemeSubstitution = false;
+ try {
+ action(false);
+ } finally {
+ UriIdentifier_Accessor.schemeSubstitution = true;
}
- this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, false, headers);
- this.Discover("/Discovery/xrdsdiscovery/" + page, version, expectedLocalId, providerEndpoint, true, true, headers);
- }
-
- private void DiscoverHtml(string page, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint, bool useRedirect) {
- this.Discover("/Discovery/htmldiscovery/" + page, version, expectedLocalId, providerEndpoint, false, useRedirect);
- }
-
- private void DiscoverHtml(string scenario, ProtocolVersion version, Identifier expectedLocalId, string providerEndpoint) {
- string page = scenario + ".html";
- this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, false);
- this.DiscoverHtml(page, version, expectedLocalId, providerEndpoint, true);
- }
-
- private void FailDiscover(string url) {
- UriIdentifier userSuppliedId = new Uri(new Uri("http://localhost"), url);
-
- this.MockResponder.RegisterMockResponse(new Uri(userSuppliedId), userSuppliedId, "text/html", LoadEmbeddedFile(url));
-
- Assert.AreEqual(0, userSuppliedId.Discover(this.RequestHandler).Count()); // ... but that no endpoint info is discoverable
- }
-
- private void FailDiscoverHtml(string scenario) {
- this.FailDiscover("/Discovery/htmldiscovery/" + scenario + ".html");
- }
-
- private void FailDiscoverXrds(string scenario) {
- this.FailDiscover("/Discovery/xrdsdiscovery/" + scenario + ".xml");
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
index 46427bb..0c80821 100644
--- a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs
@@ -10,34 +10,34 @@ namespace DotNetOpenAuth.Test.OpenId {
using System.Linq;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class XriIdentifierTests : OpenIdTestBase {
private string goodXri = "=Andrew*Arnott";
private string badXri = "some\\wacky%^&*()non-XRI";
- [TestInitialize]
+ [SetUp]
public override void SetUp() {
base.SetUp();
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorNull() {
new XriIdentifier(null);
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestCase, ExpectedException(typeof(ArgumentException))]
public void CtorBlank() {
new XriIdentifier(string.Empty);
}
- [TestMethod, ExpectedException(typeof(FormatException))]
+ [TestCase, ExpectedException(typeof(FormatException))]
public void CtorBadXri() {
new XriIdentifier(this.badXri);
}
- [TestMethod]
+ [TestCase]
public void CtorGoodXri() {
var xri = new XriIdentifier(this.goodXri);
Assert.AreEqual(this.goodXri, xri.OriginalXri);
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsFalse(xri.IsDiscoverySecureEndToEnd);
}
- [TestMethod]
+ [TestCase]
public void CtorGoodXriSecure() {
var xri = new XriIdentifier(this.goodXri, true);
Assert.AreEqual(this.goodXri, xri.OriginalXri);
@@ -53,7 +53,7 @@ namespace DotNetOpenAuth.Test.OpenId {
Assert.IsTrue(xri.IsDiscoverySecureEndToEnd);
}
- [TestMethod]
+ [TestCase]
public void IsValid() {
Assert.IsTrue(XriIdentifier.IsValidXri(this.goodXri));
Assert.IsFalse(XriIdentifier.IsValidXri(this.badXri));
@@ -62,412 +62,36 @@ namespace DotNetOpenAuth.Test.OpenId {
/// <summary>
/// Verifies 2.0 spec section 7.2#1
/// </summary>
- [TestMethod]
+ [TestCase]
public void StripXriScheme() {
var xri = new XriIdentifier("xri://" + this.goodXri);
Assert.AreEqual("xri://" + this.goodXri, xri.OriginalXri);
Assert.AreEqual(this.goodXri, xri.CanonicalXri);
}
- [TestMethod]
+ [TestCase]
public void TrimFragment() {
Identifier xri = new XriIdentifier(this.goodXri);
Assert.AreSame(xri, xri.TrimFragment());
}
- [TestMethod]
+ [TestCase]
public void ToStringTest() {
Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri).ToString());
}
- [TestMethod]
+ [TestCase]
public void EqualsTest() {
Assert.AreEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri));
Assert.AreNotEqual(new XriIdentifier(this.goodXri), new XriIdentifier(this.goodXri + "a"));
Assert.AreNotEqual(null, new XriIdentifier(this.goodXri));
- Assert.AreEqual(this.goodXri, new XriIdentifier(this.goodXri));
+ Assert.IsTrue(new XriIdentifier(this.goodXri).Equals(this.goodXri));
}
- [TestMethod]
- public void Discover() {
- string xrds = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*Arnott</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:03:24.000Z</Expires>
- <ProviderID>xri://=</ProviderID>
- <LocalID>!9b72.7dd1.50a9.5ccd</LocalID>
- <CanonicalID>=!9B72.7DD1.50A9.5CCD</CanonicalID>
-
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='default' select='false'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null' select='false'/>
- <URI append='qxri' priority='1'>http://1id.com/contact/</URI>
-
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <URI append='qxri' priority='1'>http://1id.com/</URI>
- </Service>
-
- <Service priority='10'>
- <ProviderID>xri://!!1008</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='10'>http://1id.com/sso</URI>
- </Service>
-</XRD>";
- Dictionary<string, string> mocks = new Dictionary<string, string> {
- { "https://xri.net/=Arnott?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
- { "https://xri.net/=!9B72.7DD1.50A9.5CCD?_xrd_r=application/xrd%2Bxml;sep=false", xrds },
- };
- this.MockResponder.RegisterMockXrdsResponses(mocks);
-
- string expectedCanonicalId = "=!9B72.7DD1.50A9.5CCD";
- ServiceEndpoint se = this.VerifyCanonicalId("=Arnott", expectedCanonicalId);
- Assert.AreEqual(Protocol.V10, se.Protocol);
- Assert.AreEqual("http://1id.com/sso", se.ProviderEndpoint.ToString());
- Assert.AreEqual(se.ClaimedIdentifier, se.ProviderLocalIdentifier);
- Assert.AreEqual("=Arnott", se.FriendlyIdentifierForDisplay);
- }
-
- [TestMethod]
- public void DiscoverCommunityInameCanonicalIDs() {
- string llliResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*llli</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:21:06.000Z</Expires>
- <ProviderID>xri://@</ProviderID>
- <LocalID>!72cd.a072.157e.a9c6</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6</CanonicalID>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type match='null' select='false'/>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path match='default'/>
- <Path>(+index)</Path>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI priority='10'>http://resolve.ezibroker.net/resolve/@llli/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
-</XRD>
-";
- string llliAreaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*area</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:07.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA0C</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI>http://resolve.ezibroker.net/resolve/@llli*area/</URI>
- </Service>
-</XRD>";
- string llliAreaCanadaUnattachedResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*canada.unattached</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:08.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA41</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType>application/xrds+xml;trust=none</MediaType>
- <URI>http://resolve.ezibroker.net/resolve/@llli*area*canada.unattached/</URI>
- </Service>
-</XRD>";
- string llliAreaCanadaUnattachedAdaResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*ada</Query>
- <Status cid='verified' code='100'>SUCCESS</Status>
- <ServerStatus code='100'>SUCCESS</ServerStatus>
- <Expires>2008-07-15T01:21:10.000Z</Expires>
- <ProviderID>xri://!!1003</ProviderID>
- <LocalID>0000.0000.3B9A.CA01</LocalID>
- <CanonicalID>@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01</CanonicalID>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <URI append='none' priority='1'>https://login.llli.org/server/</URI>
- </Service>
- <Service>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <URI append='authority' priority='1'>http://linksafe-contact.ezibroker.net/contact/</URI>
- </Service>
- <Service priority='1'>
- <ProviderID>xri://!!1003!103</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path>(+index)</Path>
- <Path match='default'/>
- <URI append='qxri' priority='1'>http://linksafe-forward.ezibroker.net/forwarding/</URI>
- </Service>
-</XRD>";
- string webResponse = @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD version='2.0' xmlns='xri://$xrd*($v*2.0)'>
- <Query>*Web</Query>
- <Status ceid='off' cid='verified' code='100'/>
- <Expires>2008-07-14T02:21:12.000Z</Expires>
- <ProviderID>xri://=</ProviderID>
- <LocalID>!91f2.8153.f600.ae24</LocalID>
- <CanonicalID>=!91F2.8153.F600.AE24</CanonicalID>
- <Service priority='10'>
- <Type select='true'>xri://+i-service*(+locator)*($v*1.0)</Type>
- <Path select='true'>(+locator)</Path>
- <MediaType match='default' select='false'/>
- <URI append='qxri'>http://locator.fullxri.com/locator/</URI>
- </Service>
- <Service priority='10'>
- <ProviderID>xri://=web</ProviderID>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <Type select='true'>xri://$res*auth*($v*2.0)</Type>
- <MediaType select='true'>application/xrds+xml</MediaType>
- <URI append='qxri' priority='1'>https://resolve.freexri.com/ns/=web/</URI>
- <URI append='qxri' priority='2'>http://resolve.freexri.com/ns/=web/</URI>
- </Service>
- <Service priority='10'>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Type select='true'>http://specs.openid.net/auth/2.0/signon</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default' select='false'/>
- <MediaType match='default' select='false'/>
- <URI append='none' priority='2'>http://authn.fullxri.com/authentication/</URI>
- <URI append='none' priority='1'>https://authn.fullxri.com/authentication/</URI>
- </Service>
- <Service priority='10'>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null' select='false'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null' select='false'/>
- <MediaType match='default' select='false'/>
- <URI append='qxri'>http://contact.fullxri.com/contact/</URI>
- </Service>
- <KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'>
- <X509Data>
- <X509Certificate>
-MIIExzCCA6+gAwIBAgIJAM+MlFr0Sth6MA0GCSqGSIb3DQEBBQUAMIGdMR8wHQYD
-VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
-CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
-YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
-YWluLmVkdTAeFw0wNjA4MTcxOTU5NTNaFw0xMTA4MTYxOTU5NTNaMIGdMR8wHQYD
-VQQDExZTdXBlcnZpbGxhaW46IFRoZSBSb290MQswCQYDVQQGEwJVUzERMA8GA1UE
-CBMITmV3IFlvcmsxDzANBgNVBAcTBkdvdGhhbTEgMB4GA1UEChMXU3VwZXJ2aWxs
-YWluIFVuaXZlcnNpdHkxJzAlBgkqhkiG9w0BCQEWGHBlbmd1aW5Ac3VwZXJ2aWxs
-YWluLmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL6uFqas4dK6
-A2wTZL0viRQNJrPyFnFBDSZGib/2ijhgzed/vvmZIBM9sFpwahcuR5hvyKUe37/c
-/RSZXoNDi/eiNOx4qb0l9UB6bd8qvc4V1PnLE7L+ZYcmwrvTKm4x8qXMgEv1wca2
-FPsreHNPdLiTUZ8v0tDTWi3Mgi7y47VTzJaTkcfmO1nL6xAtln5sLdH0PbMM3LAp
-T1d3nwI3VdbhqqZ+6+OKEuC8gk5iH4lfrbr6C9bYS6vzIKrotHpZ3N2aIC3NMjJD
-PMw/mfCuADfRNlHXgZW+0zyUkwGTMDea8qgsoAMWJGdeTIw8I1I3RhnbgLzdsNQl
-b/1ZXx1uJRUCAwEAAaOCAQYwggECMB0GA1UdDgQWBBQe+xSjYTrlfraJARjMxscb
-j36jvDCB0gYDVR0jBIHKMIHHgBQe+xSjYTrlfraJARjMxscbj36jvKGBo6SBoDCB
-nTEfMB0GA1UEAxMWU3VwZXJ2aWxsYWluOiBUaGUgUm9vdDELMAkGA1UEBhMCVVMx
-ETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZHb3RoYW0xIDAeBgNVBAoTF1N1
-cGVydmlsbGFpbiBVbml2ZXJzaXR5MScwJQYJKoZIhvcNAQkBFhhwZW5ndWluQHN1
-cGVydmlsbGFpbi5lZHWCCQDPjJRa9ErYejAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
-DQEBBQUAA4IBAQC4SPBDGYAxfbXd8N5OvG0drM7a5hjXfcCZpiILlPSRpxp79yh7
-I5vVWxBxUfolwbei7PTBVy7CE27SUbSICeqWjcDCfjNjiZk6mLS80rm/TdLrHSyM
-+Ujlw9MGcBGaLI+sdziDUMtTQDpeAyQTaGVbh1mx5874Hlo1VXqGYNo0RwR+iLfs
-x48VuO6GbWVyxtktkE2ypz1KLWiyI056YynydRvuBCBHeRqGUixPlH9CrmeSCP2S
-sfbiKnMOGXjIYbvbsTAMdW2iqg6IWa/fgxhvZoAXChM9bkhisJQc0qD0J5TJQwgr
-uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy
- </X509Certificate>
- </X509Data>
- </KeyInfo>
-</XRD>";
- this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
- { "https://xri.net/@llli?_xrd_r=application/xrd%2Bxml;sep=false", llliResponse },
- { "https://xri.net/@llli*area?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaResponse },
- { "https://xri.net/@llli*area*canada.unattached?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedResponse },
- { "https://xri.net/@llli*area*canada.unattached*ada?_xrd_r=application/xrd%2Bxml;sep=false", llliAreaCanadaUnattachedAdaResponse },
- { "https://xri.net/=Web?_xrd_r=application/xrd%2Bxml;sep=false", webResponse },
- });
- this.VerifyCanonicalId("@llli", "@!72CD.A072.157E.A9C6");
- this.VerifyCanonicalId("@llli*area", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C");
- this.VerifyCanonicalId("@llli*area*canada.unattached", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41");
- this.VerifyCanonicalId("@llli*area*canada.unattached*ada", "@!72CD.A072.157E.A9C6!0000.0000.3B9A.CA0C!0000.0000.3B9A.CA41!0000.0000.3B9A.CA01");
- this.VerifyCanonicalId("=Web", "=!91F2.8153.F600.AE24");
- }
-
- [TestMethod]
- public void DiscoveryCommunityInameDelegateWithoutCanonicalID() {
- this.MockResponder.RegisterMockXrdsResponses(new Dictionary<string, string> {
- { "https://xri.net/=Web*andrew.arnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*andrew.arnott</Query>
- <Status cid='absent' code='100'>Success</Status>
- <ServerStatus code='100'>Success</ServerStatus>
- <Expires>2008-07-14T03:30:59.722Z</Expires>
- <ProviderID>=!91F2.8153.F600.AE24</ProviderID>
- <Service>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
- <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://contact.freexri.com/contact/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path select='true'>(+index)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://authn.freexri.com/authentication/</URI>
- <URI append='none' priority='1'>https://authn.freexri.com/authentication/</URI>
- </Service>
- <ServedBy>OpenXRI</ServedBy>
-</XRD>" },
- { "https://xri.net/@id*andrewarnott?_xrd_r=application/xrd%2Bxml;sep=false", @"<?xml version='1.0' encoding='UTF-8'?>
-<XRD xmlns='xri://$xrd*($v*2.0)'>
- <Query>*andrewarnott</Query>
- <Status cid='absent' code='100'>Success</Status>
- <ServerStatus code='100'>Success</ServerStatus>
- <Expires>2008-07-14T03:31:00.466Z</Expires>
- <ProviderID>@!B1E8.C27B.E41C.25C3</ProviderID>
- <Service>
- <Type select='true'>http://openid.net/signon/1.0</Type>
- <Path select='true'>(+login)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='none' priority='2'>http://www.myopenid.com/server</URI>
- <openid:Delegate xmlns:openid='http://openid.net/xmlns/1.0'>http://blog.nerdbank.net</openid:Delegate>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+contact)*($v*1.0)</Type>
- <Type match='null'/>
- <Path select='true'>(+contact)</Path>
- <Path match='null'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://contact.freexri.com/contact/</URI>
- </Service>
- <Service>
- <ProviderID>@!7F6F.F50.A4E4.1133</ProviderID>
- <Type select='true'>xri://+i-service*(+forwarding)*($v*1.0)</Type>
- <Path select='true'>(+index)</Path>
- <Path match='default'/>
- <MediaType match='default'/>
- <URI append='qxri'>http://forwarding.freexri.com/forwarding/</URI>
- </Service>
- <ServedBy>OpenXRI</ServedBy>
-</XRD>" },
- });
- // Consistent with spec section 7.3.2.3, we do not permit
- // delegation on XRI discovery when there is no CanonicalID present.
- this.VerifyCanonicalId("=Web*andrew.arnott", null);
- this.VerifyCanonicalId("@id*andrewarnott", null);
- }
-
- [TestMethod, Ignore] // XRI parsing and normalization is not implemented (yet).
+ [TestCase, Ignore("XRI parsing and normalization is not implemented (yet).")]
public void NormalizeCase() {
Identifier id = "=!9B72.7dd1.50a9.5ccd";
Assert.AreEqual("=!9B72.7DD1.50A9.5CCD", id.ToString());
}
-
- private ServiceEndpoint VerifyCanonicalId(Identifier iname, string expectedClaimedIdentifier) {
- ServiceEndpoint se = iname.Discover(this.RequestHandler).FirstOrDefault();
- if (expectedClaimedIdentifier != null) {
- Assert.IsNotNull(se);
- Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname);
- Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Count > 0);
- } else {
- Assert.IsNull(se);
- }
- return se;
- }
}
}
diff --git a/src/DotNetOpenAuth.Test/Test References/DotNetOpenAuth.accessor b/src/DotNetOpenAuth.Test/Test References/DotNetOpenAuth.accessor
deleted file mode 100644
index 35adf51..0000000
--- a/src/DotNetOpenAuth.Test/Test References/DotNetOpenAuth.accessor
+++ /dev/null
@@ -1 +0,0 @@
-DotNetOpenAuth.dll
diff --git a/src/DotNetOpenAuth.Test/TestBase.cs b/src/DotNetOpenAuth.Test/TestBase.cs
index c6508f6..8aeca2d 100644
--- a/src/DotNetOpenAuth.Test/TestBase.cs
+++ b/src/DotNetOpenAuth.Test/TestBase.cs
@@ -5,38 +5,43 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Test {
+ using System;
using System.IO;
using System.Reflection;
using System.Web;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth.Messages;
using log4net;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
/// <summary>
/// The base class that all test classes inherit from.
/// </summary>
public class TestBase {
- /// <summary>
- /// The full path to the directory that contains the test ASP.NET site.
- /// </summary>
- internal static readonly string TestWebDirectory = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\src\DotNetOpenAuth.TestWeb"));
-
private MessageDescriptionCollection messageDescriptions = new MessageDescriptionCollection();
/// <summary>
- /// Gets or sets the test context which provides
- /// information about and functionality for the current test run.
- /// </summary>
- public TestContext TestContext { get; set; }
-
- /// <summary>
/// Gets the logger that tests should use.
/// </summary>
internal static ILog TestLogger {
get { return TestUtilities.TestLogger; }
}
+ /// <summary>
+ /// Gets the full path to the directory that contains the test ASP.NET site.
+ /// </summary>
+ internal string TestWebDirectory {
+ get {
+ // System.IO.Path.GetDirectoryName(new System.Uri(basePath).LocalPath)
+ string basePath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
+ string relativePath = @"src\DotNetOpenAuth.TestWeb";
+ for (int i = 0; !Directory.Exists(Path.Combine(basePath, relativePath)) && i < 4; i++) {
+ relativePath = "..\\" + relativePath;
+ }
+ return Path.GetFullPath(relativePath);
+ }
+ }
+
internal MessageDescriptionCollection MessageDescriptions {
get { return this.messageDescriptions; }
}
@@ -44,7 +49,7 @@ namespace DotNetOpenAuth.Test {
/// <summary>
/// The TestInitialize method for the test cases.
/// </summary>
- [TestInitialize]
+ [SetUp]
public virtual void SetUp() {
log4net.Config.XmlConfigurator.Configure(Assembly.GetExecutingAssembly().GetManifestResourceStream("DotNetOpenAuth.Test.Logging.config"));
MessageBase.LowSecurityMode = true;
@@ -55,7 +60,7 @@ namespace DotNetOpenAuth.Test {
/// <summary>
/// The TestCleanup method for the test cases.
/// </summary>
- [TestCleanup]
+ [TearDown]
public virtual void Cleanup() {
log4net.LogManager.Shutdown();
}
diff --git a/src/DotNetOpenAuth.Test/UriUtilTests.cs b/src/DotNetOpenAuth.Test/UriUtilTests.cs
index 29e740d..a2cf1a2 100644
--- a/src/DotNetOpenAuth.Test/UriUtilTests.cs
+++ b/src/DotNetOpenAuth.Test/UriUtilTests.cs
@@ -9,11 +9,11 @@ namespace DotNetOpenAuth.Test {
using System.Collections.Generic;
using System.Linq;
using System.Text;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class UriUtilTests {
- [TestMethod]
+ [TestCase]
public void QueryStringContainPrefixedParametersNull() {
Assert.IsFalse(UriUtil.QueryStringContainPrefixedParameters(null, "prefix."));
}
diff --git a/src/DotNetOpenAuth.Test/UtilTests.cs b/src/DotNetOpenAuth.Test/UtilTests.cs
index 5ea4d0c..0930e8d 100644
--- a/src/DotNetOpenAuth.Test/UtilTests.cs
+++ b/src/DotNetOpenAuth.Test/UtilTests.cs
@@ -9,14 +9,14 @@ namespace DotNetOpenAuth.Test {
using System.Collections.Generic;
using System.Linq;
using System.Text;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using NUnit.Framework;
- [TestClass]
+ [TestFixture]
public class UtilTests {
/// <summary>
/// Verifies ToStringDeferred generates a reasonable string for an empty, multi-line list.
/// </summary>
- [TestMethod]
+ [TestCase]
public void ToStringDeferredEmptyMultiLine() {
Assert.AreEqual("[]", Util.ToStringDeferred(Enumerable.Empty<string>(), true).ToString());
}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 569a7bc..f6f3d03 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -1,16 +1,11 @@

-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth", "DotNetOpenAuth\DotNetOpenAuth.csproj", "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Test", "DotNetOpenAuth.Test\DotNetOpenAuth.Test.csproj", "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}"
-EndProject
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{20B5E173-C3C4-49F8-BD25-E69044075B4D}"
ProjectSection(SolutionItems) = preProject
..\build.proj = ..\build.proj
- DotNetOpenAuth.vsmdi = DotNetOpenAuth.vsmdi
+ ..\projecttemplates\DotNetOpenAuth Starter Kits.vscontent = ..\projecttemplates\DotNetOpenAuth Starter Kits.vscontent
..\LICENSE.txt = ..\LICENSE.txt
- LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
..\doc\README.Bin.html = ..\doc\README.Bin.html
..\doc\README.html = ..\doc\README.html
..\samples\README.html = ..\samples\README.html
@@ -32,11 +27,25 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B4C6F647-C046-4B54-BE12-7701C4119EE7}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenID", "OpenID", "{034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth", "OAuth", "{1E2CBAA5-60A3-4AED-912E-541F5753CDC6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InfoCard", "InfoCard", "{8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{E9ED920D-1F83-48C0-9A4B-09CCE505FE6D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project Templates", "Project Templates", "{B9EB8729-4B54-4453-B089-FE6761BA3057}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth", "DotNetOpenAuth\DotNetOpenAuth.csproj", "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.Test", "DotNetOpenAuth.Test\DotNetOpenAuth.Test.csproj", "{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.ApplicationBlock", "..\samples\DotNetOpenAuth.ApplicationBlock\DotNetOpenAuth.ApplicationBlock.csproj", "{AA78D112-D889-414B-A7D4-467B34C7B663}"
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "DotNetOpenAuth.TestWeb", "DotNetOpenAuth.TestWeb", "{47A84EF7-68C3-4D47-926A-9CCEA6518531}"
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "DotNetOpenAuth.TestWeb", "DotNetOpenAuth.TestWeb\", "{47A84EF7-68C3-4D47-926A-9CCEA6518531}"
ProjectSection(WebsiteProperties) = preProject
- TargetFramework = "3.5"
+ TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5"
ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;{4376ECC9-C346-4A99-B13C-FA93C0FBD2C9}|DotNetOpenAuth.Test.dll;"
Debug.AspNetCompiler.VirtualPath = "/DotNetOpenAuth.TestWeb"
Debug.AspNetCompiler.PhysicalPath = "DotNetOpenAuth.TestWeb\"
@@ -61,9 +70,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderWebForms", ".
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdProviderMvc", "..\samples\OpenIdProviderMvc\OpenIdProviderMvc.csproj", "{AEA29D4D-396F-47F6-BC81-B58D4B855245}"
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InfoCardRelyingParty", "..\samples\InfoCardRelyingParty", "{6EB90284-BD15-461C-BBF2-131CF55F7C8B}"
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InfoCardRelyingParty", "..\samples\InfoCardRelyingParty\", "{6EB90284-BD15-461C-BBF2-131CF55F7C8B}"
ProjectSection(WebsiteProperties) = preProject
- TargetFramework = "3.5"
+ TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5"
ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;"
Debug.AspNetCompiler.VirtualPath = "/InfoCardRelyingParty"
Debug.AspNetCompiler.PhysicalPath = "..\samples\InfoCardRelyingParty\"
@@ -81,15 +90,16 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "InfoCardRelyingParty", "..\
Release.AspNetCompiler.Debug = "False"
VWDPort = "59719"
DefaultWebSiteLanguage = "Visual Basic"
+ StartServerOnDebug = "false"
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdRelyingPartyMvc", "..\samples\OpenIdRelyingPartyMvc\OpenIdRelyingPartyMvc.csproj", "{07B193F1-68AD-4E9C-98AF-BEFB5E9403CB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdRelyingPartyWebForms", "..\samples\OpenIdRelyingPartyWebForms\OpenIdRelyingPartyWebForms.csproj", "{1E8AEA89-BF69-47A1-B290-E8B0FE588700}"
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAsp", "..\samples\OpenIdRelyingPartyClassicAsp", "{BBACD972-014D-478F-9B07-56B9E1D4CC73}"
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAsp", "..\samples\OpenIdRelyingPartyClassicAsp\", "{BBACD972-014D-478F-9B07-56B9E1D4CC73}"
ProjectSection(WebsiteProperties) = preProject
- TargetFramework = "2.0"
+ TargetFrameworkMoniker = ".NETFramework,Version%3Dv3.5"
Debug.AspNetCompiler.VirtualPath = "/OpenIdRelyingPartyClassicAsp"
Debug.AspNetCompiler.PhysicalPath = "..\samples\OpenIdRelyingPartyClassicAsp\"
Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OpenIdRelyingPartyClassicAsp\"
@@ -105,81 +115,38 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAs
Release.AspNetCompiler.FixedNames = "false"
Release.AspNetCompiler.Debug = "False"
VWDPort = "10318"
+ StartServerOnDebug = "false"
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumerWpf", "..\samples\OAuthConsumerWpf\OAuthConsumerWpf.csproj", "{6EC36418-DBC5-4AD1-A402-413604AA7A08}"
- ProjectSection(ProjectDependencies) = postProject
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191} = {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}
- EndProjectSection
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OpenID", "OpenID", "{034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OAuth", "OAuth", "{1E2CBAA5-60A3-4AED-912E-541F5753CDC6}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdOfflineProvider", "..\samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj", "{5C65603B-235F-47E6-B536-06385C60DE7F}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "InfoCard", "InfoCard", "{8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFormsRelyingParty", "..\projecttemplates\WebFormsRelyingParty\WebFormsRelyingParty.csproj", "{A78F8FC6-7B03-4230-BE41-761E400D6810}"
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OAuthConsumer", "..\samples\OAuthConsumer", "{9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}"
- ProjectSection(WebsiteProperties) = preProject
- TargetFramework = "3.5"
- ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;{AA78D112-D889-414B-A7D4-467B34C7B663}|DotNetOpenAuth.ApplicationBlock.dll;"
- Debug.AspNetCompiler.VirtualPath = "/OAuthConsumer"
- Debug.AspNetCompiler.PhysicalPath = "..\samples\OAuthConsumer\"
- Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OAuthConsumer\"
- Debug.AspNetCompiler.Updateable = "true"
- Debug.AspNetCompiler.ForceOverwrite = "true"
- Debug.AspNetCompiler.FixedNames = "false"
- Debug.AspNetCompiler.Debug = "True"
- Release.AspNetCompiler.VirtualPath = "/OAuthConsumer"
- Release.AspNetCompiler.PhysicalPath = "..\samples\OAuthConsumer\"
- Release.AspNetCompiler.TargetPath = "PrecompiledWeb\OAuthConsumer\"
- Release.AspNetCompiler.Updateable = "true"
- Release.AspNetCompiler.ForceOverwrite = "true"
- Release.AspNetCompiler.FixedNames = "false"
- Release.AspNetCompiler.Debug = "False"
- VWDPort = "59721"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelyingPartyLogic", "..\projecttemplates\RelyingPartyLogic\RelyingPartyLogic.csproj", "{17932639-1F50-48AF-B0A5-E2BF832F82CC}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}
EndProjectSection
EndProject
-Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OAuthServiceProvider", "..\samples\OAuthServiceProvider", "{7ADCCD5C-AC2B-4340-9410-FE3A31A48191}"
- ProjectSection(WebsiteProperties) = preProject
- TargetFramework = "3.5"
- ProjectReferences = "{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}|DotNetOpenAuth.dll;"
- Debug.AspNetCompiler.VirtualPath = "/OAuthServiceProvider"
- Debug.AspNetCompiler.PhysicalPath = "..\samples\OAuthServiceProvider\"
- Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\OAuthServiceProvider\"
- Debug.AspNetCompiler.Updateable = "true"
- Debug.AspNetCompiler.ForceOverwrite = "true"
- Debug.AspNetCompiler.FixedNames = "false"
- Debug.AspNetCompiler.Debug = "True"
- Release.AspNetCompiler.VirtualPath = "/OAuthServiceProvider"
- Release.AspNetCompiler.PhysicalPath = "..\samples\OAuthServiceProvider\"
- Release.AspNetCompiler.TargetPath = "PrecompiledWeb\OAuthServiceProvider\"
- Release.AspNetCompiler.Updateable = "true"
- Release.AspNetCompiler.ForceOverwrite = "true"
- Release.AspNetCompiler.FixedNames = "false"
- Release.AspNetCompiler.Debug = "False"
- VWDPort = "65169"
- VWDDynamicPort = "false"
- EndProjectSection
+Project("{C8D11400-126E-41CD-887F-60BD40844F9E}") = "RelyingPartyDatabase", "..\projecttemplates\RelyingPartyDatabase\RelyingPartyDatabase.dbproj", "{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdOfflineProvider", "..\samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj", "{5C65603B-235F-47E6-B536-06385C60DE7F}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcRelyingParty", "..\projecttemplates\MvcRelyingParty\MvcRelyingParty.csproj", "{152B7BAB-E884-4A59-8067-440971A682B3}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{E9ED920D-1F83-48C0-9A4B-09CCE505FE6D}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoRelyingParty", "..\samples\OpenIdWebRingSsoRelyingParty\OpenIdWebRingSsoRelyingParty.csproj", "{B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project Templates", "Project Templates", "{B9EB8729-4B54-4453-B089-FE6761BA3057}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoProvider", "..\samples\OpenIdWebRingSsoProvider\OpenIdWebRingSsoProvider.csproj", "{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebFormsRelyingParty", "..\projecttemplates\WebFormsRelyingParty\WebFormsRelyingParty.csproj", "{A78F8FC6-7B03-4230-BE41-761E400D6810}"
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "OpenIdRelyingPartyWebFormsVB", "..\samples\OpenIdRelyingPartyWebFormsVB\OpenIdRelyingPartyWebFormsVB.vbproj", "{F289B925-4307-4BEC-B411-885CE70E3379}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelyingPartyLogic", "..\projecttemplates\RelyingPartyLogic\RelyingPartyLogic.csproj", "{17932639-1F50-48AF-B0A5-E2BF832F82CC}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthConsumer", "..\samples\OAuthConsumer\OAuthConsumer.csproj", "{9529606E-AF76-4387-BFB7-3D10A5B399AA}"
ProjectSection(ProjectDependencies) = postProject
- {2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {2B4261AC-25AC-4B8D-B459-1C42B6B1401D}
+ {E135F455-0669-49F8-9207-07FCA8C8FC79} = {E135F455-0669-49F8-9207-07FCA8C8FC79}
EndProjectSection
EndProject
-Project("{C8D11400-126E-41CD-887F-60BD40844F9E}") = "RelyingPartyDatabase", "..\projecttemplates\RelyingPartyDatabase\RelyingPartyDatabase.dbproj", "{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OAuthServiceProvider", "..\samples\OAuthServiceProvider\OAuthServiceProvider.csproj", "{E135F455-0669-49F8-9207-07FCA8C8FC79}"
EndProject
Global
- GlobalSection(TestCaseManagementSettings) = postSolution
- CategoryFile = DotNetOpenAuth.vsmdi
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
Debug|Any CPU = Debug|Any CPU
@@ -252,18 +219,6 @@ Global
{6EC36418-DBC5-4AD1-A402-413604AA7A08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EC36418-DBC5-4AD1-A402-413604AA7A08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EC36418-DBC5-4AD1-A402-413604AA7A08}.Release|Any CPU.Build.0 = Release|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.Release|Any CPU.ActiveCfg = Debug|Any CPU
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3}.Release|Any CPU.Build.0 = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.CodeAnalysis|Any CPU.ActiveCfg = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.CodeAnalysis|Any CPU.Build.0 = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.Release|Any CPU.ActiveCfg = Debug|Any CPU
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191}.Release|Any CPU.Build.0 = Debug|Any CPU
{5C65603B-235F-47E6-B536-06385C60DE7F}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
{5C65603B-235F-47E6-B536-06385C60DE7F}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
{5C65603B-235F-47E6-B536-06385C60DE7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -291,28 +246,68 @@ Global
{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Build.0 = Release|Any CPU
{2B4261AC-25AC-4B8D-B459-1C42B6B1401D}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {152B7BAB-E884-4A59-8067-440971A682B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E135F455-0669-49F8-9207-07FCA8C8FC79}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CD57219F-24F4-4136-8741-6063D0D7A031} = {20B5E173-C3C4-49F8-BD25-E69044075B4D}
- {AA78D112-D889-414B-A7D4-467B34C7B663} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
{034D5B5B-7D00-4A9D-8AFE-4A476E0575B1} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
- {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
{1E2CBAA5-60A3-4AED-912E-541F5753CDC6} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
+ {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
+ {AA78D112-D889-414B-A7D4-467B34C7B663} = {B4C6F647-C046-4B54-BE12-7701C4119EE7}
+ {2A59DE0A-B76A-4B42-9A33-04D34548353D} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{AEA29D4D-396F-47F6-BC81-B58D4B855245} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{07B193F1-68AD-4E9C-98AF-BEFB5E9403CB} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{1E8AEA89-BF69-47A1-B290-E8B0FE588700} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{BBACD972-014D-478F-9B07-56B9E1D4CC73} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
- {2A59DE0A-B76A-4B42-9A33-04D34548353D} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
- {6EB90284-BD15-461C-BBF2-131CF55F7C8B} = {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}
+ {B64A1E7E-6A15-4B91-AF13-7D48F7DA5942} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
+ {0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
+ {F289B925-4307-4BEC-B411-885CE70E3379} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{6EC36418-DBC5-4AD1-A402-413604AA7A08} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
- {9ADBE36D-9960-48F6-82E9-B4AC559E9AC3} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
- {7ADCCD5C-AC2B-4340-9410-FE3A31A48191} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
+ {9529606E-AF76-4387-BFB7-3D10A5B399AA} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
+ {E135F455-0669-49F8-9207-07FCA8C8FC79} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
+ {6EB90284-BD15-461C-BBF2-131CF55F7C8B} = {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}
{5C65603B-235F-47E6-B536-06385C60DE7F} = {E9ED920D-1F83-48C0-9A4B-09CCE505FE6D}
{A78F8FC6-7B03-4230-BE41-761E400D6810} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
{17932639-1F50-48AF-B0A5-E2BF832F82CC} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
{2B4261AC-25AC-4B8D-B459-1C42B6B1401D} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
+ {152B7BAB-E884-4A59-8067-440971A682B3} = {B9EB8729-4B54-4453-B089-FE6761BA3057}
EndGlobalSection
EndGlobal
diff --git a/src/DotNetOpenAuth.vsmdi b/src/DotNetOpenAuth.vsmdi
deleted file mode 100644
index 6ca6b0c..0000000
--- a/src/DotNetOpenAuth.vsmdi
+++ /dev/null
@@ -1,540 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
- <TestList name="Hosted ASP.NET tests" id="5a637793-05cb-476f-9f0c-18e7e7a4b205" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
- <Description>Tests that require hosting the test ASP.NET web site to run. These tests tend to be a bit slower than the rest due to the overhead of loading ASP.NET.</Description>
- <TestLinks>
- <TestLink id="896fd3db-5edb-ed16-b11a-e01769735f89" name="BadRequestsGenerateValidErrorResponsesHosted" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a6d6decf-0c19-16d8-edf6-ee70e56877e1" name="AspHostBasicTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- </TestLinks>
- </TestList>
- <TestList name="Fast" id="7e880f0f-2224-4f4c-a555-910a3bc2c0e5" parentListId="f0eeb325-0558-48a3-9a99-952133d8148e">
- <Description>Fast running unit tests</Description>
- <TestLinks>
- <TestLink id="89de77d8-729a-7efe-9667-71b1f5d78859" name="CtorBadXri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="300ae1f7-fc61-1d41-b262-f8c830b6e115" name="RemoveTest1" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="12304550-5647-5e61-64b4-a5e051f20a03" name="IsExtensionSupported" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="734dd45c-6320-26a9-e412-62ecacfd285a" name="CtorNullAttribute" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="70c08ce3-cbd0-d553-61c0-a6d2ca203dc4" name="IsExtensionSupportedNullExtension" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1d5fb5a9-e15c-d99c-7a7e-95a4c4d123c2" name="DirectRequestsUsePost" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6b218bf7-a4e9-8dac-d2c2-9bc3ee3ffc3e" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="74f2623d-98c5-7c2b-a2af-02dfa7ff5601" name="GetHttpVerbTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1c531011-403a-0821-d630-d5433d968f31" name="CtorFromRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="73c6c979-205d-2216-d98d-2dd136b352c6" name="UtcCreationDateConvertsToUniversal" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e7aacb49-62ef-637d-ada2-0a12d836414d" name="ExtensionFactory" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="49a266cf-4ab6-3fdc-f4fd-21533f42c7cb" name="CtorWithProtocolMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d12e8df0-1195-ab75-2275-7c8f854ddf98" name="UserSetupUrl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="21cf1f9a-063f-395a-f8aa-92c190c69146" name="SignaturesMatchKnownGood" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d570770a-74e4-50ec-8eb9-91bd81c093ad" name="ParseNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a9f7897c-b299-807b-0612-384732cd10c9" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f4bec8d2-0531-34ab-8d50-bca260b58c61" name="ReadFromRequestWithContext" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a314e3b9-36a5-bfbb-3e15-e5003f22cf87" name="Serialize" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0f80456a-5465-dd68-bfb0-ba27b676187c" name="EqualsTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1bfbe1e1-3827-824f-27ad-4c990b0e22ab" name="Defaults" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ca9f3da7-e19f-b58b-54fe-54fa56ab9556" name="AddByKeyAndValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d766edce-59de-a03d-830a-0f0477521cff" name="ApplyHeadersToResponseNullAspNetResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9fae8ab4-8436-eba1-3e4b-51511998fa8e" name="UnsolicitedAssertionRejected" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="84e718d7-bb82-e7d1-31be-471e2c154053" name="Item" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="889ba616-43dc-8a7f-ee13-46288969d617" name="ParameterNames" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fdf5b3df-239b-26fd-c1a2-152057195b7e" name="ReadFromRequestForm" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="555edc3b-5abf-7e46-b4f6-ddf44800b5df" name="SpreadSregToAXBasic" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="149a95cf-a538-f853-e11b-3133c15579c5" name="RequestTokenUriTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f3cbbcda-49ff-fc43-140b-f362081654c3" name="CtorNullTypeUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="352d9fd6-cf38-4b72-478f-e3e17ace55f5" name="NoValueLoose" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fa52f2db-fc1e-ba31-cc5e-0bcc05998187" name="NoValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="65752c29-fa1f-7b88-bbec-5329af8db4d8" name="IsValid" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cd1142a5-f77a-5626-a739-65eb0228bf7d" name="ProtocolDetection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="68532d6d-a0cf-5883-17e2-6060707ba9ae" name="DecodeOobToNullUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="188ce83b-3117-adb5-4b89-12f2b09be1de" name="CtorSimpleConsumer" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="93c157e8-1293-3aff-f616-66502872b37d" name="DiscoveryRequiresSslIgnoresInsecureEndpointsInXrds" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f6ecb459-cc64-36ee-438c-4514e9413586" name="AddAttributeByPrimitives" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="03e293d0-dbe8-ad09-1ddd-de7be2cf9276" name="CopyTo" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c87bee54-0edd-1051-b5f8-2233692249ba" name="DiscoverCommunityInameCanonicalIDs" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5fa10f12-3de5-1783-0a97-9802d5469dfa" name="AddAttributeNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5ab06bb5-d047-8c3a-6b91-5951e0a55cc5" name="ToStringTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="454165a2-c26e-5740-09a9-d234db052ba3" name="InvalidRealmNullUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="40e1121e-8ff3-df73-203b-04baab671a0c" name="ImplicitConversionToStringTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="779b1f99-fe67-185c-f165-66787bf6e39a" name="BasicEncodingTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="456c3468-9081-4879-7e7e-8299bd8c7f68" name="IsReadOnly" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d6951a97-9d0b-31c1-7a29-01fbb986c5a9" name="SpoofedClaimedIdDetectionSolicited" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1cde79f8-99b7-7090-f898-ba96a607875f" name="IsReturnUrlDiscoverableValidButNoMatch" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="910f8448-5454-8ae5-cba3-690c7f375576" name="ParameterNames" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="83aba528-c8ea-f464-177e-2ea8ae2cfd0b" name="Birthdates" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3c4e0438-94f5-a132-3949-8d94718e4839" name="PassThruCollection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b63c4b89-3889-6dcf-8890-c92fc44c0b10" name="VerifyBadTimestampIsRejected" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9126d9e0-14dc-490b-3cd3-d3e424d38f9e" name="BinarySerialization" storage="..\bin\debug\dotnetopenauth.test.dll" enabled="false" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4c399759-263f-5eba-8855-de14f197e647" name="QueryStringContainPrefixedParametersNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1757957f-17bb-ef9f-39f8-c008863ec033" name="AssuranceLevels" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c11e5541-0a92-85ab-4f90-0db7766ebdcb" name="CtorUnsolicited" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8aecb3a5-2cb5-143d-aa99-9514fa8dfacb" name="AddAttributeByValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ef6cebca-f8da-edf6-0217-8bb854710090" name="DiscoveryCommunityInameDelegateWithoutCanonicalID" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b09311d4-4dea-6786-3e59-9c62fe16e301" name="ParameterNames" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ad56539c-6156-5f62-a98a-b24ae0159cc6" name="XmlSerialization" storage="..\bin\debug\dotnetopenauth.test.dll" enabled="false" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="54eae9ed-bed1-eeda-b6ea-045c8f7e2ba5" name="SendIndirectMessage301GetNullFields" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2d0ee03a-f082-768c-a0db-574ac8efeffb" name="Valid" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6c20a52a-bab7-e84e-faca-fd79ec5303d9" name="CtorCountZero" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7fb8d29c-c8ea-7f88-ed42-ae7368d6a429" name="CtorNullStore" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="50986611-9de6-a112-2fe8-691210989f45" name="IsTypeUriPresent" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c63c9935-54a0-398a-f44b-214e17faf1f1" name="SendDirectMessageResponseHonorsHttpStatusCodes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="163c8ba8-f829-c21e-a5a1-3c4565ec4425" name="UnifyExtensionsAsSregNoExtensions" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="054484ce-12c5-83ad-49a4-b241cd81557d" name="ClaimedIdentifier" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e8337858-a320-8aad-51aa-402e65a90b75" name="ReplayDetectionTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="507cd1b6-1010-0bca-cf7f-f96e3f4f6c6c" name="QueryBeforeSettingUrl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1dcbaac6-0b11-8d8f-50d7-237574abbab1" name="ToDictionaryWithSkippedNullKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4e3cef90-06f2-f5dd-3510-a8595b552af5" name="GetHttpVerbOutOfRangeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="715dcbdd-28f5-3c33-7d88-e0a1b648d89a" name="CreateRequestDumbMode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a1ff4ada-fe5d-d2f3-b7fb-8e72db02b3c3" name="Full" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="85a71d28-5f2f-75ce-9008-94982438bb5f" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f334cc44-b2d0-2d67-358a-532def3bee80" name="ContainsKeyValuePair" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fa05cc5f-2aaf-da22-ff52-caf1c3c6bb08" name="InsecureIdentifiersRejectedWithRequireSsl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c1c7e292-3e87-4fe5-1f6f-0ef2f86ebbce" name="GetHttpDeliveryMethodOutOfRangeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7debb527-142a-6ca6-3b9b-1e131c18e801" name="AccessTokenUriTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="98e7a0f9-ab6c-7ff1-3a2c-00d8244e1bec" name="CommonMethods" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a25369b4-b1b8-09a1-7a47-aacc1480e51c" name="FilePartAsFile" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="af7cb01c-950e-23d7-0f32-082b7af8b382" name="CtorNullToObject" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a260d196-066f-b0ae-a40e-fb9d962b28a4" name="XrdsDirectDiscovery_20" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="13acd546-c82e-324c-220d-34f42a6d705e" name="DeserializeSimple" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b56cdf04-0d29-8b13-468c-fb4b4258c619" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d474830d-3636-522c-1564-1b83e7a844d3" name="EmptyLine" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f44fb549-fc8a-7469-6eed-09d9f86cebff" name="SendDirectMessageResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="63e5025b-5ccf-5f13-6e05-d1e44502a6e9" name="RequestBadPreferredScheme" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d80bf2a0-bcd5-f1c1-4835-8e5ceb523387" name="GetPublicFacingUrlSSLForwarder3" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f20bd439-e277-dc27-4ec4-5d5949d1c6bf" name="RequestUsingAuthorizationHeaderScattered" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3fc3ac8d-7772-b620-0927-f4bd3a24ce2f" name="SendNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5f3758b3-1410-c742-e623-b964c01b0633" name="AuthenticationTimeUtcConvertsToUtc" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9d4a230d-9e74-dc1b-ecdc-bf875b56e1b3" name="CtorNullVersion" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f8d8d555-7a04-ab6e-918a-3dae32f4b52b" name="IsExtensionSupportedNullString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7b1fb2c4-39c0-0d39-700c-96d992f5a01f" name="AuthenticationTimeUtcSetUnspecified" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="00089858-d849-1e5f-4fb5-31d8d0590233" name="VerifyArgumentNotNullThrows" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="54a65e0b-1857-72b9-797b-fe3d9a082131" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f17424d2-ed4b-1ea0-a339-733f5092d9d0" name="MaximumAuthenticationAgeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d067c55c-3715-ed87-14a2-c07349813c94" name="IsDirectedIdentity" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8fc08a6d-6dcf-6256-42ff-073d4e4b6859" name="RequireDirectedIdentity" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2a7b77c3-27d5-7788-e664-5d20118d223b" name="OPRejectsHttpNoEncryptionAssociateRequests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1f46ce86-bc66-3f5c-4061-3f851cf6dd7f" name="HtmlDiscover_20" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2f9d176e-4137-63bd-ee2a-6b79fde70d0d" name="Clear" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fc7af2d7-6262-d761-335b-ef3ec029484d" name="DeserializeVerifyElementOrdering" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="df159af7-abf5-089c-b592-e6f535dab1c1" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="577b8522-8516-4f62-22db-76227bf82f4c" name="UserSetupUrlNotRequiredInV1SetupOrV2" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ac4ff1af-8333-e54e-0322-27d8824d7573" name="RequestUsingAuthorizationHeader" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e78ab82c-3b49-468a-b2ad-ca038e98ff07" name="GetEnumerator" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8e86c2fd-24b9-44c5-7cda-d66aa7cd4418" name="Serializable" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="06ec5bce-5a78-89c3-0cda-fa8bddfea27d" name="SetCountZero" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e2287de6-cbd2-4298-3fb8-297013749e70" name="SendIndirectMessageFormPostNullFields" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="db8d66cc-8206-57cc-0ce5-c8117813d77c" name="UnifyExtensionsasSregFromSchemaOpenIdNet" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ef8a2274-4e58-0dde-4c5c-7f286865fc3a" name="SendReplayProtectedMessageSetsNonce" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2eb7c3dd-08aa-bfc0-edc8-e14bd82f7507" name="IdentifierTextInteraction" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0d99e0a9-295e-08a6-bc31-2abb79c00ff8" name="IsReturnUrlDiscoverableRequireSsl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f41ce7ab-5500-7eea-ab4d-8c646bffff23" name="HttpSchemePrepended" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="38239ff0-1dfd-1116-55df-2790243dc768" name="IsValid" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="04be6602-31a2-f4ae-8fdb-b9ad2ac370be" name="PrepareMessageForReceiving" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2c2b48d0-8009-e7e0-9ff4-34f9973f59da" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5dd2e6c9-ff0f-48de-3a1a-cbab61370843" name="SetCountNegative" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="182203f3-5a16-b736-ea8c-b59f6bf7df66" name="InvalidRealmTwoWildcards2" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4fd5baa2-8f39-8bf6-db8f-aa92592bfc06" name="CtorRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="385c302d-b546-c164-2a59-2e35f75d7d60" name="RemoveStructDeclaredProperty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="870cce9d-5b17-953c-028f-827ec8b56da2" name="GetInvalidMessageType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="97f0277a-86e6-5b5a-8419-c5253cabf2e0" name="UserAuthorizationUriTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="643add47-e9f3-20b8-d8e0-69e3f8926d33" name="CreateRequestsWithEndpointFilter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d66a3b7a-1738-f6b3-aed1-e9bc80734ae9" name="CtorNullString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f3f84a10-317f-817a-1988-fddc10b75c20" name="AddTwoAttributes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5e2555a0-c07a-6488-c0e9-40ececd5021f" name="Serbian" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e03f0038-5bb7-92f2-87a7-00a7d2c31a77" name="MessageExpirationWithoutTamperResistance" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1f3ea08b-9880-635f-368f-9fcd3e25f3cd" name="ReadFromRequestNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9104f36f-6652-dcbb-a8ae-0d6fc34d76ed" name="AddCallbackArgumentClearsPreviousArgument" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f49bcd49-76fb-bfea-b119-4e0f70159f80" name="OpenIdProvider" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f4b313bb-cebc-a854-ffbd-6c955d850a05" name="VerifyGoodTimestampIsAccepted" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="77047207-0571-72d5-71bd-586b878bcc0c" name="Base64Member" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f919a731-cc5c-88c6-5582-639b272d64fc" name="IsReturnUrlDiscoverableValidResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a8bd3730-1660-dca9-87ec-23bc9dc39ab9" name="CtorGoodXriSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4a00f3ab-f405-95a7-d745-2fcf7787eb56" name="GetNonexistentHandle" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f4537b23-bb5e-5c6f-da53-64b34472f0dc" name="ChannelGetter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="75fa4664-bb0e-3a54-de29-c18ac712b231" name="Mode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="94ba9fd3-851d-13b2-e273-6294b167c13e" name="HttpsSignatureVerification" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cbfeb75b-d031-7df3-c281-3c9e1c450042" name="CtorFromRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5460f9c6-ec9d-969d-5aff-b946d6776e25" name="CtorWithNullProtocolMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d5f4e610-eabe-1dc0-ab3f-7c9dcb17fcc3" name="CtorImpliedLocalIdentifier" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="64d8c630-76c6-e420-937b-19c889dd7f59" name="CtorNonMessageType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fba4d9a6-d8c7-a063-7c07-4a27c38c94a9" name="InvalidRealmBadWildcard3" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="be41e9c1-ecde-cc80-37d0-4126225e4cda" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="48115dc0-1323-bab0-c540-695a2160e0a3" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a79e43c9-ad5a-5543-51ff-22271ec87ab0" name="PrepareMessageForSendingNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7ca16e07-126d-58ac-2ac5-a09a8bf77592" name="InvalidRealmBadWildcard1" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="832dbf28-5bf2-bd95-9029-bf798349d917" name="GetCallbackArguments" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="11108b79-f360-9f7c-aebc-2d11bebff96a" name="ReadFromRequestForm" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="53cbbf4a-89d3-122b-0d88-662f3022ce26" name="OpenIdMaxAuthenticationTime" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="20646985-c84a-db8e-f982-ec55d61eaacd" name="ResponseNonceSetter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c2c78c43-7f50-ffc3-affb-e60de2b76c94" name="CreateQueryStringNullDictionary" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="dc6af36d-0efc-9291-a603-2af7bac2a269" name="ErrorMessagesAsHttp400" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cc584a29-684c-75e8-3d77-96201d9ba537" name="ProviderTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ef20222d-b2e2-d593-17fa-512041020643" name="InvalidRealmNullString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b2e1bba0-ab24-cdd5-906c-a3655814ab2d" name="SendSetsTimestamp" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2f1a3fc4-77ec-2ae3-668c-9e18f9ab0ebe" name="SendIndirectMessage301Get" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e4403d9e-73c1-967d-345c-4a2c83880d4e" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6ce37652-2f47-6952-fb6d-568c2ca85224" name="TransformAXFormatTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a145f430-8062-5ad7-0cf5-b51eba0f8de7" name="HttpsSignatureGeneration" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a6ea74e5-8681-4eb4-a51b-5051e5f7603c" name="NonFieldOrPropertyMember" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="066ce22f-103c-56ee-0250-d9e28d43ffcd" name="Values" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="bb542259-4c10-4b88-1b3c-f842b0bb49a9" name="ImmediateVsSetupModes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="71564ca7-7845-92b3-7433-2f2beeb6b9f7" name="VerifyNonZeroLengthOnNonEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7ea157db-cf32-529f-f1d3-b3351f17725a" name="CtorSimpleServiceProvider" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c905ca57-e427-3833-c2dd-17ca9f6962cd" name="SendIndirectMessageFormPost" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="50594141-1a00-b4ab-d794-5b06e67327e5" name="IsTypeUriPresentNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c7f6459d-9e6e-b4bc-cae8-65f5a3785403" name="SendIndirectMessageNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="aa79cdf5-e0bc-194e-fdbb-78369c19c30f" name="ConstantFieldMemberInvalidValues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="dd9e3279-2d7e-e88e-ccfa-ef213055fc3d" name="SendDirectedNoRecipientMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b384002f-26a9-7dde-c3f6-9ceff34dd8e2" name="GetRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5a77a48f-00d6-da6f-5ef7-c897ebf8fe6b" name="EscapeUriDataStringRfc3986Tests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="81f670d0-d314-c53c-9d91-c0765dfc30c1" name="MessagePartsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="efd570c9-5e74-17e4-f332-ac257c8e8aff" name="RealmReturnToMismatchV1" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fda58c48-e03a-73a3-4294-9a49e776ffb6" name="CtorWithTextMessageAndInnerException" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e7a41771-7dda-be44-0755-e06300f3cd92" name="IsSaneTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ae384709-e9a4-0142-20ba-6adb6b40b3e2" name="CtorStringHttpsSchemeSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3b70dd09-384d-5b99-222b-dc8ce8e791f2" name="SecuritySettingsSetNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f787ae5d-b8fc-0862-a527-9157d11bbed7" name="UntrustedWebRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8df5d75f-bd4d-ce4e-2faf-6106b623de42" name="AddAttributeRequestStrangeUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="51a08d94-c327-4d28-1f0c-f7920ea54870" name="ValidMessageTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="bc3e979b-09ea-c45d-5714-2d1fb00244cf" name="IncomingMessageMissingRequiredParameters" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="051a85ed-eef9-9437-507d-d6208b6a8f74" name="DiscoveryWithRedirects" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="be6a14aa-c0d9-cf61-286a-236b92239597" name="EnumerableCache" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5a4df395-962e-0b7c-de71-abcb7e8930db" name="CreateFiltersDelegatingIdentifiers" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="bf73c7f2-33b1-8e18-c4f6-cb8609388754" name="DiscoveryRequireSslWithInsecureXrdsInSecureHttpHeader" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="feb0a53e-1592-b878-b70c-1a272d9c6908" name="SpreadSregToAxTargetedAtOPFormat" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e071a119-c7e9-1a55-b132-72e161fea598" name="CtorAndProperties" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a6e464af-42df-1ba4-17e5-b955352664b5" name="RPOnlyRenegotiatesOnce" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0290975f-02ce-d8a7-d723-5dae623cab46" name="CtorNullTokenManager" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3b535521-90c8-7f49-545f-bcfc4ad16d40" name="UnresponsiveProvidersComeLast" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4bd86299-18d7-abbe-e5d2-1afad17279e9" name="Parse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0443f5f8-aa08-80d5-dcc6-261802debe5a" name="XrdsDirectDiscovery_10" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6c95f443-463e-2856-f500-b9029645e44c" name="RequestNullRecipient" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3744e1f1-6be1-f27f-78e9-5410d356ccf4" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="afafb5ef-662e-2da3-35b8-1d67bb0d79ce" name="AddPolicies" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d0a92f93-9bb4-1821-81cf-e9b50e3e7d62" name="SendDirectMessageResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="17267cde-a296-8293-5bd1-9ca629817e4b" name="OpenIdRelyingParty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5a21f2d2-f916-fb16-1460-caff8c24a9fc" name="GetHttpDeliveryMethodTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cab73921-470b-331f-e601-b44805b67c81" name="GetAttributeValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="14ce54ee-5507-ac70-5514-99b7b83ba3d6" name="ExtensionFactories" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ebd84587-bbc2-9889-c500-b6fbdf2bf209" name="GetRequestNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="565140c9-c9fe-9466-1e39-740d7e368cb5" name="TryParse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="782d64c8-46af-a624-b3f6-a65aeaa57bfe" name="LastLineNotTerminatedLoose" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="30a8eab6-6423-26af-da1a-ec304935fe43" name="RemoveNonexistentHandle" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e9bc3f63-aeb1-d84d-8abc-fc6ed77955e6" name="SignedResponsesIncludeExtraDataInSignature" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9e209599-5924-f624-48de-ed31588cb425" name="EncodeDecode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3027bfe5-3612-7089-16cc-d6a2a556a41f" name="Transport" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="95e1fc36-2500-2721-1919-35e9e8349a1c" name="AddPolicyMultipleTimes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9af943f7-b289-1a24-8e3e-bfbd7a55b4c7" name="CtorGoodUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ae1ef27c-fbfe-c57e-a1e0-c1ef9de4ea23" name="CommonProperties" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="196be55e-a3e5-adf3-9f15-13ba6cce0701" name="ValidRealmsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="bb68f1dc-3854-fc11-2ea6-d45f892d76fa" name="NistAssuranceLevelSetVarious" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="88aaa032-b18a-b334-937b-66837c5f987c" name="AssociateRenegotiateBitLength" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="dd5be0e2-a1fc-3369-0b11-78b728eeaba5" name="CtorNullUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0362a92c-a21c-f718-6b1e-3d154c14acd0" name="RequestUsingPost" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="264cd371-e830-c09b-5511-18f54d4c69d5" name="RespondSimpleValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4a009f39-66b1-9cc5-ea8b-13b75ab22a5b" name="ContainsKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9bdc56c0-33ce-b46c-4031-bd3252b499a6" name="PrivateAssociationPositive" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="32604ca2-2577-9c33-f778-ff7e4c985ce5" name="RequestTokenUriWithOAuthParametersTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fdf439d0-3b74-4d32-d395-d5a2559ed88b" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3df1f62b-4fb4-d399-cf7f-40b72001d9d6" name="CtorUnsolicited" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7c688207-e58a-86ed-90d0-687e28ee7e38" name="MultiPartPostAscii" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8b11aa63-4c0f-41ff-f70c-882aacf939fe" name="CtorCountNegative" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="83271647-7da8-70b1-48a3-f1253a636088" name="IsExtensionSupportedEmptyString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f583b298-139a-e733-dde6-f9dc4b73d4bf" name="SendDirectMessageResponseHonorsHttpStatusCodes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b671ea40-3b8c-58d5-7788-f776810c49be" name="UnicodeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5435ab79-de25-e2fc-0b2d-b05d5686d27d" name="IsUrlWithinRealmTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="501fa941-c1ac-d4ef-56e7-46827788b571" name="GetRequestNoContext" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="01e33554-07cc-ff90-46f8-7d0ca036c9f6" name="ToDictionaryNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="33dd2f79-cd69-f1c0-0e47-f7a17b5a8a8b" name="MultiPartPostMultiByteCharacters" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0215f125-3936-484e-a8d0-d940d85bbc27" name="AppendQueryArgsNullDictionary" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7c048c58-c456-3406-995f-adb742cc2501" name="DeserializeInvalidMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="704a32d0-3f50-d462-f767-fd9cf1981b7f" name="ProviderVersion" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f362baf3-da5b-1b8c-39ae-7c9b2051270a" name="AuthenticationTimeUtcSetUtc" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="decb3fef-ef61-6794-5bc6-f7ff722a146e" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3bb818b4-5423-ad91-8cd9-8606ec85d2cb" name="ReadFromRequestAuthorizationScattered" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="30f3c12b-e510-de63-5acd-ae8e32866592" name="CreateQueryString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9302541c-9c30-9ce7-66db-348ee4e9f6ee" name="UnifyExtensionsAsSregWithSreg" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="997253fb-7591-c151-1705-02976b400f27" name="AddAttributeTwice" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9bf0528f-c3ab-9a38-fd8a-fd14bade0d0b" name="EnumerableCacheCurrentThrowsAfter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8346368c-9c8a-de76-18dd-5faeeac3917d" name="OPRejectsMismatchingAssociationAndSessionTypes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3d0effa3-894a-630c-02b0-ada4b5cef795" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3c438474-63f3-b56c-dcba-1ed923fcdbdd" name="CreateResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="47706bc6-7bee-0385-62b4-4f9cec6cc702" name="CtorWithTextMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2495fc9b-d766-5ae7-7324-f044c4ce1242" name="AddNullValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fb6c270f-ff72-73f4-b8b3-82851537427c" name="MultiVersionedMessageTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="10245b55-8130-e0aa-e211-4a16fa14d0b1" name="ClearValues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c9d67d40-1903-8319-0f7c-d70db4846380" name="SendWithoutAspNetContext" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="aa93fd70-1b5f-1ce7-c9dd-3c70f9e271ac" name="PostMultipart" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e97cee09-4163-d83f-f65f-14e424294172" name="ExtensionsAreIdentifiedAsSignedOrUnsigned" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f4fd129a-a7c3-dc1e-2b4a-5059a4207a8a" name="Send" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cc0031b8-1fdb-cd87-97c1-c6f893c296e0" name="TooManyBindingElementsProvidingSameProtection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="152e7a3a-21f9-eabf-0065-08597a0cc9a6" name="AuthorizationHeaderScheme" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="93041654-1050-3878-6b90-656a7e2e3cfd" name="CtorDefault" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e2ab77b2-a6dc-f165-1485-140b9b3d916f" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="035cd43a-23d5-af91-12ee-0a0ce78b3548" name="XrdsDiscoveryFromHttpHeader" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="dbf7855c-0cc6-309f-b5f5-022e0b95fe3b" name="QueryStringLookupWithoutQuery" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="abb0610a-c06f-0767-ac99-f37a2b573d1b" name="ParameterPrefix" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="32532d1f-d817-258d-ca72-021772bfc185" name="UriEncodeDecode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f3345901-2e76-34dd-32f1-0b312d6e1c1e" name="IsReturnUrlDiscoverableNotSsl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a2b3835e-8edb-89aa-ba6c-f10b28a3af81" name="ReadFromRequestQueryString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1deb0ca9-923a-8ef7-7a24-d5d5af04acdf" name="SpecAppendixAExample" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b32b6295-d4a9-3369-f072-28a71e84d4e8" name="SerializationWithUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2fb2563b-b908-2fad-5efc-522a68c76780" name="ValidMessageNoNonceReceivedTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ee052b02-681f-2303-3cc6-37f7b2319579" name="RequireAssociation" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fb0e478e-0f55-b257-75fe-2ab60b57292e" name="SendInvalidMessageTransport" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a4aa113a-57b5-a52c-c4e3-f70d6702badb" name="Default" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ee7a04ba-0419-e08f-b838-01ec0f2a838e" name="UnsolicitedAssertion" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="547cfee6-bbb4-6138-a114-fc0eb6cc94f6" name="PrivateAssociationTampered" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5803e93d-e256-86ba-e10e-499d2f813c6d" name="Trivial" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="beb086e9-5eb7-fb8f-480a-70ede9efd70d" name="CreateRequests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="78f622a3-750c-12c5-afc6-470c1bf71d85" name="ProtocolDetectionWithoutClues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0c1a0323-092a-34b3-1601-1f941569efab" name="CtorGoodXri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8538caf8-48bd-7cf8-6ad8-15e1c3766f92" name="CtorNullType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e1958fc5-a979-88b2-b593-3bc89ad6ad4e" name="GetEnumeratorUntyped" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f4893153-bb84-bf45-7889-8350a7e1db66" name="DiscoveryRequireSslWithInsecureXrdsInSecureHtmlHead" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5218fba2-d1af-e1f4-7641-9ae1d4975430" name="DirectResponsesSentUsingKeyValueForm" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a1a0178c-cd4a-1651-8535-3c9ee3d40821" name="ToDictionaryWithNullKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0f36556d-ece7-eb70-8597-a9d085165c2c" name="Sign" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="19d2219e-c04d-fa3a-5e26-92448f35f21d" name="RespondNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="eb932fc7-76c7-b63f-e1e6-a59dea8e4da1" name="AddAttribute" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a59c5dc0-de4d-8136-8545-2e2e9616de46" name="SerializationWithXri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0aa1bc22-0b26-3977-5983-5dc4a454cea5" name="OptionalNullableStruct" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c205832e-711c-62d0-5f5e-78f1250ea7cc" name="AuthenticationTimeUtcSetNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3536ba12-fdb0-2ac9-3fef-00a2dd8e9a65" name="SharedAssociationTampered" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e7b8770d-b26c-e7b3-e80e-fac46285f59d" name="PassThruList" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="14acb719-f090-018f-b870-9a5acb1d7179" name="AddAuthLevelTypes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="aef95d4e-ad69-0eca-6528-7fce78512336" name="EqualityTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1b66e135-bdab-c2ed-18d8-aa89b46a57fc" name="RPRejectsUnrecognizedAssociationType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1ea8bd07-75a5-bfc0-5f8c-1a78d04240c2" name="TryGetValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7b89844d-f60a-fb66-c48d-e483864c66b5" name="RespondTooManyValues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b9cda1a0-83cd-cf4b-b61f-4faa75fa37ba" name="ReceivedReplayProtectedMessageTwice" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7f9c4a9e-de7a-555c-543d-db89b757588e" name="AppendQueryArgs" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cf58b7b9-9718-f6cd-1839-fc53174598f2" name="IsExtensionSupportedNullType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9aa6a81e-c198-c0fd-0252-003b856b7674" name="ConstantFieldMemberValidValues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d6b120b7-fc16-6815-927e-af382cd44bbd" name="ReceivedInvalidSignature" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b71d12f6-58a1-cf82-d06e-e57c0a3ea55c" name="RPRejectsUnencryptedSuggestion" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="77e5af06-b02d-692e-b32f-40ea39e77fbd" name="FriendlyIdentifierForDisplay" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3c67903e-15ce-9ed4-34c8-f77059af79ca" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="87593646-8db5-fb47-3a5b-bf84d7d828c2" name="InvalidMessageTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="65f16786-7296-ee46-8a8f-82f18b211234" name="AddByKeyValuePair" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c891c6bc-da47-d4ab-b450-f3e3a0d6cba8" name="NoAssociationNegative" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="47e8fae9-542d-1ebb-e17c-568cf9594539" name="RelativeUriDecodeFails" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f3af5fd8-f661-dc4f-4539-947b081a8b54" name="ReceivedReplayProtectedMessageJustOnce" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a14ddf08-796b-6cf1-a9bf-856dd50520fa" name="RequiredProtection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3aa4e498-fd14-8274-22da-895436c1659e" name="AssociateUnencrypted" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5b4fee50-7c15-8c6b-3398-c82279646e5f" name="RequiredOptionalLists" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="59295023-d248-e9c4-68b9-65f6ea38490c" name="VerifyArgumentNotNullDoesNotThrow" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e137b84a-d2a7-9af6-d15d-a92417668ccf" name="Transport" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a94ee2ec-02df-b535-1d2e-0c5db9c76b49" name="ReceiveUnrecognizedMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="88ae5661-da27-91c5-4d78-1f43cd716127" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cea48223-04e2-d336-0ac4-255c514bd188" name="RoundTripFullStackTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ba35acc7-78d2-6710-57ac-6843210d4202" name="UserSetupUrlRequiredInV1Immediate" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f18b514c-4f78-5421-8bdf-8b0f1fdf2282" name="HandleLifecycle" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1e2ae78c-d2f3-a808-2b82-eca9f9f2e458" name="Keys" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9173c754-a358-91cc-a8f0-2c2703a55da8" name="AssertionWithEndpointFilter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6badbaa8-33d1-13c4-c1f9-aef73a9ac5bf" name="InvalidRawBirthdate" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0435e38a-71f2-d58d-9c07-d97d830a1578" name="ExtensionResponsesAreSigned" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2f2ea001-a4f8-ff0d-5d12-74180e0bf610" name="HttpsSignatureVerificationNotApplicable" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fe55cc74-98eb-c6c7-622f-77ad3e304c10" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ca5360e1-ca08-d00f-6ade-7c9441db4294" name="CreateQueryStringEmptyCollection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4735a071-3c06-509b-05f5-912ab0e39f13" name="InvalidRealmBadProtocol" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6fbd433d-cd54-b206-6df3-fbd591690a4d" name="HtmlDiscover_11" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="175b6eb8-a448-4e07-7fed-001355edc128" name="PassThruArray" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="777af676-ee70-0e16-799b-85b9ec33cd63" name="IsValid" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d083396b-db68-1318-e62b-6dc9f89e26bd" name="CtorDefault" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2f6a81c5-cd04-0ca0-22ee-d4213f9cf147" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="72d3f240-67f2-0b04-bd31-a99c3f7a8e12" name="SharedAssociationPositive" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3cd9447e-9ffd-f706-37bb-e7eb5828e430" name="InvalidRealmEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="28fe030c-d36e-13cf-475c-7813210bf886" name="AddAttributeRequestAgain" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e344ba35-96b7-d441-c174-8c8b295fd157" name="AddCallbackArgument" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2e23dc5a-93ea-11a5-d00d-02d294794e5f" name="AssociateDiffieHellmanOverHttps" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8d0df47c-c381-0487-6c19-77548ad7fc13" name="UnifyExtensionsAsSregWithBothSregAndAX" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2237b8ce-94ce-28c1-7eb2-14e59f47e926" name="UnifyExtensionsAsSregFromAXSchemaOrg" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a2f79410-e593-9155-e03d-8168cbb9f091" name="GetPublicFacingUrlSSLForwarder1" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="069995aa-4136-610b-3f41-df80a138c244" name="AppendQueryArgsNullUriBuilder" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="457d6b32-d224-8a06-5e34-dbef3e935655" name="HttpSignatureVerification" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="309fdc0f-150c-5992-9a79-63be5f479d89" name="RequiredProtection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2e1b27e8-2e3e-0290-2bee-d88e2914efd9" name="SpreadSregToAXNoExtensions" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c15c3ab5-e969-efc9-366d-78ebc43ce08f" name="Fetch" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7bf8e806-68a1-86bc-8d91-9a99d237d35c" name="CreateRequestMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a883dc73-d6be-e59a-6da2-0db1d4452679" name="BindingElementsOrdering" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5dcd69c3-e979-7316-4551-a73fe4645dcd" name="SecuritySettings" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f533bf9e-daa1-b26a-4789-372f3a9291d6" name="TryRequireSslAdjustsIdentifier" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6ef9df5a-d069-0103-5260-593808f232da" name="XrdsDiscoveryFromHead" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="313faac6-6357-5468-2d4d-4c9fba001678" name="TryParseNoThrow" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7cbe4350-38d0-db7e-335c-93d9398fc95b" name="ExtensionOnlyFacadeLevel" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2f5cfa57-bcb4-39af-e769-2d7c34e2598e" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ff78d828-b437-aaeb-e48a-85a5ad1fe396" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="29e45877-ca7a-85de-5c39-6d43befe1a1e" name="DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c351c660-d583-d869-0129-2e312665d815" name="CtorBlank" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f063a3c6-5a36-2801-53d7-5142416199a9" name="ImplicitConversionFromStringTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="809afd59-8f10-ce37-6630-06b59351a05a" name="CommonProperties" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="02333934-cfea-2fb6-5e08-7a24be050f44" name="CreateRequestsOnNonOpenID" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5298ecb0-bcad-9022-8b93-87793eb2c669" name="UnsolicitedDelegatingIdentifierRejection" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b97c4a66-a832-401c-a98b-6342ad7bcdcf" name="LanguagePreferenceEncodingDecoding" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="068dcefa-8f2b-52c3-fe79-576c84c5648b" name="CtorBlank" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="315b5857-7697-8222-f94c-f6f10d539491" name="BaseSignatureStringTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cd219db4-4f6e-8ff4-f957-c8428d38c118" name="HttpSignatureGeneration" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="864578a5-61a2-bc5d-1d19-17093885bea3" name="InvalidRealmTwoWildcards1" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8a5c9404-1e77-68cf-229a-ef7ed413e6e7" name="OptionalNonNullableStruct" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ab653060-5bec-3dc6-78ee-a5ef7d393b1d" name="AddPolicyMultipleTimes" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2599d559-d036-5dd2-0b5b-fb229c3bf486" name="InvalidRealmBadWildcard2" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9684f7bf-cdda-a2c5-0822-29cb0add3835" name="ResponseNonceGetter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e0b191fa-aa68-bd0f-c9d0-f8cba23003f3" name="RequestUsingHead" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f341c47f-ac23-2fc0-fcf5-c999fe8d2611" name="SetBodyToByteStream" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="643d722c-2c2b-fbd8-a499-5a852ef14dc7" name="PrepareMessageForSending" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="79c0d33a-f7f2-fd69-1b4d-57ee3ece2cca" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="937b85f4-1ef3-84d1-a567-8bba079a33a9" name="Properties" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="53bc1962-e7c2-04b6-cafa-0f6fde7592a9" name="ReadFromRequestNoContext" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c057a3e5-b527-62a9-c19b-abb82e6be621" name="SendIndirectMessage301GetEmptyRecipient" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0dc9284e-cba4-9d87-8955-19639578c70d" name="Serializable" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="384fecbf-f18e-edcb-a2eb-fb0322f031aa" name="ApplyHeadersToResponseNullListenerResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e3a3b3b6-e05f-0a99-e20c-af91a9065819" name="AssociateRequestDeterminedBySecuritySettings" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d3c4624f-f78a-2ff3-199a-77c922059718" name="Best" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7f3144c7-95a1-affa-1a37-9e6169c19be6" name="SharedAssociationNegative" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="aedfde98-4357-5b63-7dca-cced838ee416" name="Provider" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b71e8878-b20e-5d96-bce4-7f10831ceaf8" name="AddPolicies" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ddf4f3ec-07bb-09e8-b5e8-0837cb8cb684" name="IsReturnUrlDiscoverableNoResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a18ae750-318b-bb1f-c2b3-c31da845c085" name="Count" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5b451648-5ca1-4395-333d-bbcb098f4a45" name="NoRequestedExtensions" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cb9a8325-abf5-5d97-a94e-a6d34f2b51e1" name="AssociateRenegotiateLimitedByRPSecuritySettings" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5271f941-565f-5977-6884-82cef09161db" name="ParseEndUserSuppliedXriIdentifer" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7cf52613-a212-8a0f-843f-37f08740c125" name="SpreadSregToAxNoOpIfOPSupportsSreg" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7c8eac5a-0455-e038-0e9a-10e59d459452" name="CtorUriHttpSchemeSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="bdba0004-be80-f5c1-1aae-487db09bdf04" name="GetReturnToArgumentDoesNotReturnExtraArgs" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ccfda025-cb1a-a2ff-78bd-5e9af885ae0b" name="ToDictionary" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="64142858-d52e-be06-d11f-6be326c6176b" name="RespondTwoValues" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="03b47440-3d09-ab28-97f1-39809f5703b6" name="NormalizeCase" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="34357633-4745-6fba-9316-493d3c6c5b90" name="ParseEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="85a0dec0-983c-8f21-b093-a2179624cc88" name="UnifyExtensionsAsSregWithSreg" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5c66a1b8-5b20-2e3b-8427-d6ff4640ac53" name="BadRequestsGenerateValidErrorResponses" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4ba7ca33-72f1-3fc6-d37c-65134eda904d" name="AddDeclaredValueThatAlreadyExists" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="06b350b0-79d1-9393-7620-cd919061898c" name="ParseEndUserSuppliedUriIdentifier" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="44afc59c-60fc-3179-b5a6-1e58e7752d54" name="ApplyHeadersToResponseNullHeaders" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="46ec24da-deb7-27c7-6dc6-52090e4fd1fb" name="Serialize" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e9a5efc6-fde8-8fa4-0bda-2675a4a7e06b" name="DefaultReferenceTypeDeclaredPropertyHasNoKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b70b4bd5-6dae-b4ad-349c-c3ad70603773" name="ReadFromRequestQueryString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5f02e24c-2972-c598-ca71-ea362b2fe7d8" name="SecuritySettingsSetNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="98a2ece8-c9e6-e6f3-c65e-f915b22077fa" name="RequestUsingGet" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2cfefc4a-918a-3e16-0670-53eb33634525" name="GeneratesOnlyRequiredElements" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="da8fcfa9-bd2c-eca0-ecbf-90364f84e8e5" name="AddExtraFieldThatAlreadyExists" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fb91e9dd-fc3b-d8a7-a5d7-d215d5ba880f" name="CtorStringHttpSchemeSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5211652f-1c25-fd4b-890d-05d2178a60e2" name="ExtensionFactories" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7650ec62-b144-f36f-8b56-31ad20521d0e" name="DoesNotStripFragment" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e2b1ae2a-8f30-b6b3-bca6-ef28fc5a0175" name="ClaimedIdAndLocalIdSpecifiedIsValid" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="58d69d1e-3bd2-3379-0af1-188f9cff2dd0" name="IsTypeUriPresentEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="495dd486-08dd-d365-7a84-67d96fef8460" name="SendIndirectedUndirectedMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="24fb403f-be35-278e-9beb-e11177f2cd1e" name="FormDataSerializeMatchesLength" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7cdabb8a-aefa-e90e-c32e-047404b64c2d" name="SerializeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f6979feb-7016-4e2b-14e2-e6c2c392419f" name="RemoveByKeyValuePair" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="58df167c-cf19-351c-cb09-5c52ae9f97be" name="DeserializeNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a778f331-f14e-9d6e-f942-a023423540f6" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="90f06a50-7b81-05ec-3dc0-7b3e8ade8cfa" name="NormalizeCase" storage="..\bin\debug\dotnetopenauth.test.dll" enabled="false" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="be00d3ef-f24d-eb8a-d251-4d691736ee6f" name="AddAttributeRequestNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="593e1d86-a6c2-c937-a1b4-6d25a595a1f1" name="EnumerableCacheCurrentThrowsBefore" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="030ac3cf-cfb6-ca47-f822-ec1d2979f0b3" name="Defaults" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3fe0b432-dbb4-b334-e504-a83fe5ffdbaf" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d5d2c553-97db-8d6c-c984-982299d6091d" name="Serializable" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="628a417f-4ddb-5965-bd4a-86c8de565c8f" name="AssociateDiffieHellmanOverHttp" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="10c44d72-2789-2afe-3b27-091dea97546e" name="RequestNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="724cc3e8-c13c-5cc6-ce14-25c51ad6297d" name="Mode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="24506e06-a678-66cc-48ee-b7f11f18a6e8" name="StripXriScheme" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c79dd056-8fff-3393-f125-4b83cf02cb3b" name="RequireSsl" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5a0d31d9-9c70-2a28-3e8c-46e8e047ac2d" name="ReceiveNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4b44b825-36cc-77f8-3a4a-5892c540f577" name="GetValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f17128c1-5953-5391-ed75-c33774eacbfc" name="LastLineNotTerminated" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="671ddaf5-238d-a517-b0f3-d79bd591a396" name="EmptyMailAddress" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d8118997-ecf7-7130-f068-5e2bc867786d" name="SerializeNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e9c2087b-1c52-5bb9-bf4e-9046cf281e36" name="DiscoverRequireSslWithInsecureRedirect" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f69f1c0c-e258-95fb-4fcb-ad14bfc40e3c" name="Discover" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="25e2c593-2e69-6215-90c0-67f269939865" name="CtorEmptyTypeUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e1e9dde8-30e6-6ce0-d5a6-4e22e0347ac4" name="UnifyExtensionsAsSregWithAX" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f50a0bdb-380e-30f6-492a-a6dd9664d0f0" name="ExtensionOnlyChannelLevel" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="64b41c6c-2b67-af35-0c93-df41bd6f2dbb" name="Store" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="55b078e4-3933-d4e0-1151-a0a61321638e" name="ReadFromRequestAuthorization" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="2d82ac4b-99b4-a132-eb62-d943e02d1498" name="ApplyHeadersToResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="599add9e-e9eb-5e8a-ce6b-6dc73c2bb408" name="DataContractNamespace" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="643c9887-3f12-300e-fdac-17ae59652712" name="Mode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ed7efca3-c3c1-bc4a-cef7-eaf984749355" name="ValidMessageReceivedTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="44ced969-83dd-201d-a660-e3744ee81cf8" name="ConstructorTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="1c5d54e2-d96a-d3a6-aeac-95f137b96421" name="CommonMethods" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cfc4032d-936a-6532-09d5-4a1267e57d63" name="GetPublicFacingUrlSSLForwarder2" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e9cceef5-383d-92f0-a8bb-f3e207582836" name="RealmReturnToMismatchV2" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e6b412e5-3a53-e717-6393-254e1c93e239" name="PassThruDoubleCache" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8375c7bb-b539-3396-885a-a3ca220078ec" name="InsufficientlyProtectedMessageSent" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="924b5295-0d39-5c89-8794-22518091e05a" name="CtorNullToString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a63c169c-4e9a-bcba-b7cd-c4c5280cd652" name="PrepareMessageForSendingNonExtendableMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="63944cb8-4c61-c42c-906f-986fa793370b" name="SignatureTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="77934ac4-bd65-7ad8-9c53-9c9447f9e175" name="GetReturnToArgumentAndNames" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="735b7a56-0f6f-77d8-8968-6708792a7ce8" name="UnifyExtensionsAsSregWithAXSchemaOpenIdNet" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="4a5b601d-475d-e6cc-1fec-19a2850681ad" name="Serializable" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9bcc2d64-870f-7675-a314-fbb975446817" name="IsApprovedDeterminesReturnedMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3e676e31-3b6d-9d12-febd-d632ece804ec" name="RPRejectsMismatchingAssociationAndSessionBitLengths" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9026e58c-8582-0852-3c3c-9eadfd544cbc" name="VerifyNonZeroLengthOnEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="0f56721c-ef8f-84be-28b7-d909614c2f85" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="ae8b7cba-696e-2362-d5e1-79a9c202a994" name="EmptyLineLoose" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="41ff051f-03d5-5f06-c6e4-615360cac08a" name="ReadFromRequestDisallowedHttpMethod" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d647fd93-40b3-24d5-25fc-661c0d58335c" name="SendIndirectMessageFormPostNullMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="62c6ee5b-ac29-461c-2373-bf620e948825" name="InvalidRealmNoScheme" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="115283b9-d95c-9a92-2197-96685ee8e96a" name="TwoExtensionsSameTypeUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d24a246f-5017-49f0-8030-e44a68ba534d" name="GetPublicFacingUrlSSLForwarder4" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="80719076-10fd-20a7-7ff3-a0aa2bc661cb" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b2b54c72-1d26-8c28-ebf5-7a5a4beeec43" name="VerifyNonZeroLengthOnNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c4001e1c-75ad-236b-284f-318905d2bc3a" name="CreateRequestOnNonOpenID" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a66588b5-989d-8f8e-4994-4a066220516b" name="FileSerializeMatchesLength" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c0d7cfcc-4f7e-e7df-3de2-b578c4c3d6ee" name="SpreadSregToAxMultipleSchemas" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="32e95494-d0bb-cfc7-a8d6-652f8816c6b4" name="ReadFromResponse" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f967c0af-c04c-d156-4faf-8978bfcab5d7" name="RequiredNullableStruct" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="248f0afc-979f-a86f-e7de-fdeb4f9dd3ea" name="CtorBadUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="536ecd26-4bda-a35e-5af8-666eb9b44940" name="NullValueEncoding" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="fa2e5bbd-4c41-f2b1-e875-38c6ef011fa1" name="RandomCharactersTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3e2f1dad-3684-587c-9039-8d116582be10" name="GetReturnToArgumentEmptyKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="00ed61cd-46cd-9c0e-f044-38d784c8bcfb" name="DecodeEmptyStringFails" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="09b892f2-96e9-45b7-d082-b0bb512c1dd4" name="RequiredNonNullableStruct" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d5912d3e-441c-a20e-20a2-0b9f0220a762" name="ParameterNames" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="439c8c16-2ba5-eb3b-b631-ce50ec48eba0" name="CtorNullMember" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="a6295302-c78f-4122-ce88-94fc30980262" name="CtorStringNoSchemeSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f12bf351-584c-bc51-c315-a67f1076927c" name="ReturnToDoesNotMatchRecipient" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b4b00582-dcc9-7672-0c02-52432b074a92" name="GetNullType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f1e1aa37-c712-6096-22fa-394008f0820a" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cb48421f-f4ff-3994-3abc-4be35f8bfd99" name="AssociateQuietlyFailsAfterHttpError" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="660ad25a-b02b-1b17-7d6e-3af3303fa7bc" name="ModeEncoding" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="736a09b4-f56e-0176-6c1c-81db0fbe3412" name="CtorUriHttpsSchemeSecure" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9f880280-aa8f-91bb-4a5f-3fe044b6815a" name="CreateVerificationCode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="10a8b8e5-e147-838c-0708-be98d5e4490e" name="CtorFull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="6daa360b-71e4-a972-143f-01b801fada84" name="DeserializeWithExtraFields" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8bbc6a02-b5a4-ea8e-2a77-8d1b6671ceb5" name="ImplicitConverstionFromUriTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="d6088ffe-ccf5-9738-131b-0fc1bc7e3707" name="TrimFragment" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="90d3c411-8895-a07f-7a21-258b9d43c5b2" name="InvalidMessageNoNonceReceivedTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="121983e3-1336-70cb-8d2a-498629e92bec" name="GetReturnToArgumentNullKey" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5e0c892d-7ad8-6d56-1f1d-2fb6236670d6" name="CtorDefault" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b58e4791-68c0-1bc0-2e48-e1351459ee46" name="UserSetupUrlSetForV1Immediate" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="c23e762d-4162-cb9e-47b3-455a568b5072" name="SendIndirectMessageFormPostEmptyRecipient" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="f70b368e-da33-bc64-6096-1b467d49a9d4" name="NonIdentityRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="46877579-ba4c-c30c-38c4-9c6ad3922390" name="InsufficientlyProtectedMessageReceived" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="b191e585-49d9-df8e-c156-307f798db169" name="AddAttributeRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="3772f97f-3fe6-3fc0-350d-4085e7c4329e" name="Test" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="44091d36-98db-2115-8647-7bd7cd308796" name="ToStringTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9e59b8d8-2fc4-b425-b5c4-c0a9fde3bf4d" name="SetValue" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="90557d85-db17-e9ab-e17b-32d6cc9fd437" name="TrimFragment" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="534bee09-36e1-c3e0-f6af-bc191b10aa48" name="CtorNullSigner" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="9986fea9-8d64-9ada-60cb-ab95adb50fb7" name="ToStringDeferredEmptyMultiLine" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="de1cdd00-a226-0d43-62b6-0c1ad325be8c" name="RequiredMinAndMaxVersions" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cbdfd707-7ba8-4b8f-9d58-17b125aa4cd4" name="SendIndirectMessage301GetNullMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="5aa4dfa9-9691-bfe0-7d81-587cfa519a55" name="DirectResponsesReceivedAsKeyValueForm" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="8fd673c8-977a-7b66-72cb-38c7054796c7" name="DiscoverRequireSslWithSecureRedirects" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="cc9200bf-1399-d40a-9754-6415f0b7bcf8" name="CreateRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- </TestLinks>
- </TestList>
- <TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
- <RunConfiguration id="abbd81c0-7d7b-4c98-878c-05dbead62c27" name="Local Test Run" storage="localtestrun.testrunconfig" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, PublicKeyToken=b03f5f7f11d50a3a" />
- </TestList>
- <TestList name="Slow" id="c426db8a-259c-4eac-b887-152be3e06ece" parentListId="f0eeb325-0558-48a3-9a99-952133d8148e">
- <Description>All tests</Description>
- <TestLinks>
- <TestLink id="b350ddb1-f4e5-e79c-af5e-f4195767f294" name="TestPublic" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7c3603c8-3686-807b-7840-1f04f8f307f5" name="AssociateDH" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="7fa99410-3aa3-10c3-10a0-27bb9288c900" name="CheckIdSharedHmacSha1Association" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="85469029-ffe0-f6f7-b56a-9ffd48fa137b" name="AssociateClearText" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- <TestLink id="e6dadcc3-60ff-f60c-0c9a-2ebd5cf91df0" name="CheckIdSharedHmacSha256Association" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" />
- </TestLinks>
- </TestList>
- <TestList name="Unit tests" id="f0eeb325-0558-48a3-9a99-952133d8148e" parentListId="8c43106b-9dc1-4907-a29f-aa66a61bf5b6" />
-</TestLists> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
index 37f9c78..980d90f 100644
--- a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
+++ b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
@@ -144,6 +144,7 @@ using System.Reflection;
/// The conversion cannot be performed.
/// </exception>
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
+ Contract.Assume(destinationType != null, "Missing contract.");
if (destinationType.IsInstanceOfType(value)) {
return value;
}
diff --git a/src/DotNetOpenAuth/ComponentModel/IdentifierConverter.cs b/src/DotNetOpenAuth/ComponentModel/IdentifierConverter.cs
index 6ba9c4b..61c0fd8 100644
--- a/src/DotNetOpenAuth/ComponentModel/IdentifierConverter.cs
+++ b/src/DotNetOpenAuth/ComponentModel/IdentifierConverter.cs
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.ComponentModel {
return null;
}
- MemberInfo identifierParse = typeof(Identifier).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public);
+ MemberInfo identifierParse = typeof(Identifier).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
return CreateInstanceDescriptor(identifierParse, new object[] { value.ToString() });
}
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
index b639a29..3164ec5 100644
--- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
@@ -319,6 +319,32 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="allowDualPurposeIdentifiers" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Controls whether identifiers that are both OP Identifiers and Claimed Identifiers
+ should ever be recognized as claimed identifiers.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="allowApproximateIdentifierDiscovery" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Controls whether certain Claimed Identifiers that exploit
+ features that .NET does not have the ability to send exact HTTP requests for will
+ still be allowed by using an approximate HTTP request.
+ Only impacts hosts running under partial trust.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="protectDownlevelReplayAttacks" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>
+ Controls whether the relying party should take special care
+ to protect users against replay attacks when interoperating with OpenID 1.1 Providers.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="behaviors">
@@ -361,6 +387,27 @@
</xs:choice>
</xs:complexType>
</xs:element>
+ <xs:element name="discoveryServices">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="name" 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:complexType>
+ </xs:element>
<xs:element name="store">
<xs:annotation>
<xs:documentation>
diff --git a/src/DotNetOpenAuth/Configuration/MessagingElement.cs b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
index 9e957fe..f130dbc 100644
--- a/src/DotNetOpenAuth/Configuration/MessagingElement.cs
+++ b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
@@ -32,6 +32,11 @@ namespace DotNetOpenAuth.Configuration {
private const string MaximumClockSkewConfigName = "clockSkew";
/// <summary>
+ /// The name of the attribute that controls whether messaging rules are strictly followed.
+ /// </summary>
+ private const string StrictConfigName = "strict";
+
+ /// <summary>
/// Gets the actual maximum message lifetime that a program should allow.
/// </summary>
/// <value>The sum of the <see cref="MaximumMessageLifetime"/> and
@@ -83,6 +88,24 @@ namespace DotNetOpenAuth.Configuration {
}
/// <summary>
+ /// Gets or sets a value indicating whether messaging rules are strictly
+ /// adhered to.
+ /// </summary>
+ /// <value><c>true</c> by default.</value>
+ /// <remarks>
+ /// Strict will require that remote parties adhere strictly to the specifications,
+ /// even when a loose interpretation would not compromise security.
+ /// <c>true</c> is a good default because it shakes out interoperability bugs in remote services
+ /// so they can be identified and corrected. But some web sites want things to Just Work
+ /// more than they want to file bugs against others, so <c>false</c> is the setting for them.
+ /// </remarks>
+ [ConfigurationProperty(StrictConfigName, DefaultValue = true)]
+ internal bool Strict {
+ get { return (bool)this[StrictConfigName]; }
+ set { this[StrictConfigName] = value; }
+ }
+
+ /// <summary>
/// Gets or sets the configuration for the <see cref="UntrustedWebRequestHandler"/> class.
/// </summary>
/// <value>The untrusted web request.</value>
diff --git a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartyElement.cs b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartyElement.cs
index cdf4fd3..2ee2e91 100644
--- a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartyElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartyElement.cs
@@ -5,8 +5,10 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Configuration {
+ using System;
using System.Configuration;
using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
@@ -25,11 +27,21 @@ namespace DotNetOpenAuth.Configuration {
private const string SecuritySettingsConfigName = "security";
/// <summary>
- /// Gets the name of the &lt;behaviors&gt; sub-element.
+ /// The name of the &lt;behaviors&gt; sub-element.
/// </summary>
private const string BehaviorsElementName = "behaviors";
/// <summary>
+ /// The name of the &lt;discoveryServices&gt; sub-element.
+ /// </summary>
+ private const string DiscoveryServicesElementName = "discoveryServices";
+
+ /// <summary>
+ /// The built-in set of identifier discovery services.
+ /// </summary>
+ private static readonly TypeConfigurationCollection<IIdentifierDiscoveryService> defaultDiscoveryServices = new TypeConfigurationCollection<IIdentifierDiscoveryService>(new Type[] { typeof(UriDiscoveryService), typeof(XriDiscoveryProxyService) });
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartyElement"/> class.
/// </summary>
public OpenIdRelyingPartyElement() {
@@ -62,5 +74,25 @@ namespace DotNetOpenAuth.Configuration {
get { return (TypeConfigurationElement<IRelyingPartyApplicationStore>)this[StoreConfigName] ?? new TypeConfigurationElement<IRelyingPartyApplicationStore>(); }
set { this[StoreConfigName] = value; }
}
+
+ /// <summary>
+ /// Gets or sets the services to use for discovering service endpoints for identifiers.
+ /// </summary>
+ /// <remarks>
+ /// If no discovery services are defined in the (web) application's .config file,
+ /// the default set of discovery services built into the library are used.
+ /// </remarks>
+ [ConfigurationProperty(DiscoveryServicesElementName, IsDefaultCollection = false)]
+ [ConfigurationCollection(typeof(TypeConfigurationCollection<IIdentifierDiscoveryService>))]
+ internal TypeConfigurationCollection<IIdentifierDiscoveryService> DiscoveryServices {
+ get {
+ var configResult = (TypeConfigurationCollection<IIdentifierDiscoveryService>)this[DiscoveryServicesElementName];
+ return configResult != null && configResult.Count > 0 ? configResult : defaultDiscoveryServices;
+ }
+
+ set {
+ this[DiscoveryServicesElementName] = value;
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
index d10d9bd..1bf2ebc 100644
--- a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
@@ -66,6 +66,21 @@ namespace DotNetOpenAuth.Configuration {
private const string PrivateSecretMaximumAgeConfigName = "privateSecretMaximumAge";
/// <summary>
+ /// Gets the name of the @allowDualPurposeIdentifiers attribute.
+ /// </summary>
+ private const string AllowDualPurposeIdentifiersConfigName = "allowDualPurposeIdentifiers";
+
+ /// <summary>
+ /// Gets the name of the @allowApproximateIdentifierDiscovery attribute.
+ /// </summary>
+ private const string AllowApproximateIdentifierDiscoveryConfigName = "allowApproximateIdentifierDiscovery";
+
+ /// <summary>
+ /// Gets the name of the @protectDownlevelReplayAttacks attribute.
+ /// </summary>
+ private const string ProtectDownlevelReplayAttacksConfigName = "protectDownlevelReplayAttacks";
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartySecuritySettingsElement"/> class.
/// </summary>
public OpenIdRelyingPartySecuritySettingsElement() {
@@ -183,6 +198,43 @@ namespace DotNetOpenAuth.Configuration {
}
/// <summary>
+ /// Gets or sets a value indicating whether identifiers that are both OP Identifiers and Claimed Identifiers
+ /// should ever be recognized as claimed identifiers.
+ /// </summary>
+ /// <value>
+ /// The default value is <c>false</c>, per the OpenID 2.0 spec.
+ /// </value>
+ [ConfigurationProperty(AllowDualPurposeIdentifiersConfigName, DefaultValue = false)]
+ public bool AllowDualPurposeIdentifiers {
+ get { return (bool)this[AllowDualPurposeIdentifiersConfigName]; }
+ set { this[AllowDualPurposeIdentifiersConfigName] = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether certain Claimed Identifiers that exploit
+ /// features that .NET does not have the ability to send exact HTTP requests for will
+ /// still be allowed by using an approximate HTTP request.
+ /// </summary>
+ /// <value>
+ /// The default value is <c>true</c>.
+ /// </value>
+ [ConfigurationProperty(AllowApproximateIdentifierDiscoveryConfigName, DefaultValue = true)]
+ public bool AllowApproximateIdentifierDiscovery {
+ get { return (bool)this[AllowApproximateIdentifierDiscoveryConfigName]; }
+ set { this[AllowApproximateIdentifierDiscoveryConfigName] = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the Relying Party should take special care
+ /// to protect users against replay attacks when interoperating with OpenID 1.1 Providers.
+ /// </summary>
+ [ConfigurationProperty(ProtectDownlevelReplayAttacksConfigName, DefaultValue = RelyingPartySecuritySettings.ProtectDownlevelReplayAttacksDefault)]
+ public bool ProtectDownlevelReplayAttacks {
+ get { return (bool)this[ProtectDownlevelReplayAttacksConfigName]; }
+ set { this[ProtectDownlevelReplayAttacksConfigName] = 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>
@@ -200,6 +252,9 @@ namespace DotNetOpenAuth.Configuration {
settings.RejectUnsolicitedAssertions = this.RejectUnsolicitedAssertions;
settings.RejectDelegatingIdentifiers = this.RejectDelegatingIdentifiers;
settings.IgnoreUnsignedExtensions = this.IgnoreUnsignedExtensions;
+ settings.AllowDualPurposeIdentifiers = this.AllowDualPurposeIdentifiers;
+ settings.AllowApproximateIdentifierDiscovery = this.AllowApproximateIdentifierDiscovery;
+ settings.ProtectDownlevelReplayAttacks = this.ProtectDownlevelReplayAttacks;
return settings;
}
diff --git a/src/DotNetOpenAuth/Configuration/ReportingElement.cs b/src/DotNetOpenAuth/Configuration/ReportingElement.cs
index ab1437f..2374448 100644
--- a/src/DotNetOpenAuth/Configuration/ReportingElement.cs
+++ b/src/DotNetOpenAuth/Configuration/ReportingElement.cs
@@ -69,7 +69,7 @@ namespace DotNetOpenAuth.Configuration {
/// Gets or sets a value indicating whether this reporting is enabled.
/// </summary>
/// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
- [ConfigurationProperty(EnabledAttributeName, DefaultValue = false)]
+ [ConfigurationProperty(EnabledAttributeName, DefaultValue = true)]
internal bool Enabled {
get { return (bool)this[EnabledAttributeName]; }
set { this[EnabledAttributeName] = value; }
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index f904c45..919d1f2 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
+ <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)\..\..\</ProjectRoot>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ </PropertyGroup>
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.props" />
+ <PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</ProjectGuid>
@@ -10,26 +14,46 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DotNetOpenAuth</RootNamespace>
<AssemblyName>DotNetOpenAuth</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StandardCopyright>
Copyright (c) 2009, Andrew Arnott. All rights reserved.
Code licensed under the Ms-PL License:
http://opensource.org/licenses/ms-pl.html
</StandardCopyright>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <TargetFrameworkProfile />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ <ApplicationIcon>DotNetOpenAuth.ico</ApplicationIcon>
+ <DocumentationFile>$(OutputPath)DotNetOpenAuth.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <OutputPath>..\..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <DocumentationFile>..\..\bin\Debug\DotNetOpenAuth.xml</DocumentationFile>
<RunCodeAnalysis>false</RunCodeAnalysis>
- <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules>
+ <CodeAnalysisRules>
+ </CodeAnalysisRules>
<CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
<CodeContractsCustomRewriterAssembly>
</CodeContractsCustomRewriterAssembly>
@@ -58,18 +82,18 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
- <OutputPath>..\..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <DocumentationFile>..\..\bin\Release\DotNetOpenAuth.xml</DocumentationFile>
<RunCodeAnalysis>true</RunCodeAnalysis>
- <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules>
+ <CodeAnalysisRules>
+ </CodeAnalysisRules>
<CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
<CodeContractsCustomRewriterAssembly>
</CodeContractsCustomRewriterAssembly>
@@ -98,18 +122,15 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- </PropertyGroup>
- <PropertyGroup>
- <SignAssembly>true</SignAssembly>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
- <OutputPath>..\..\bin\CodeAnalysis\</OutputPath>
<DefineConstants>$(DefineConstants);CONTRACTS_FULL;DEBUG;TRACE</DefineConstants>
- <DocumentationFile>..\..\bin\CodeAnalysis\DotNetOpenAuth.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules>
+ <CodeAnalysisRules>
+ </CodeAnalysisRules>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
@@ -142,15 +163,11 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\log4net.dll</HintPath>
- </Reference>
- <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\Microsoft.Contracts.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
@@ -178,9 +195,7 @@ http://opensource.org/licenses/ms-pl.html
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web" />
- <Reference Include="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\System.Web.Abstractions.dll</HintPath>
+ <Reference Include="System.Web.Abstractions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Extensions">
@@ -189,16 +204,11 @@ http://opensource.org/licenses/ms-pl.html
<Reference Include="System.Web.Extensions.Design">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
- <Reference Include="System.Web.Mobile" />
- <Reference Include="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\System.Web.Mvc.dll</HintPath>
- </Reference>
- <Reference Include="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\..\lib\System.Web.Routing.dll</HintPath>
+ <Reference Include="System.Web.Mobile" Condition=" '$(ClrVersion)' != '4' " />
+ <Reference Include="System.Web.Routing">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.Xaml" Condition=" '$(ClrVersion)' == '4' " />
<Reference Include="System.XML" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -206,6 +216,18 @@ http://opensource.org/licenses/ms-pl.html
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.ComponentModel.DataAnnotations">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(ClrVersion)' == '4' ">
+ <Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
+ </ItemGroup>
+ <ItemGroup Condition=" '$(ClrVersion)' != '4' ">
+ <!-- MVC 2 can run on CLR 2 (it doesn't require CLR 4) but since MVC 2 apps tend to use type forwarding,
+ it's a more broadly consumable idea to bind against MVC 1 for the library unless we're building on CLR 4,
+ which will definitely have MVC 2 available. -->
+ <Reference Include="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
</ItemGroup>
<ItemGroup>
<Compile Include="ComponentModel\ClaimTypeSuggestions.cs" />
@@ -276,7 +298,10 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\OutgoingWebResponseActionResult.cs" />
<Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" />
<Compile Include="Messaging\Reflection\IMessagePartNullEncoder.cs" />
+ <Compile Include="Messaging\Reflection\IMessagePartOriginalEncoder.cs" />
<Compile Include="Messaging\Reflection\MessageDescriptionCollection.cs" />
+ <Compile Include="Mvc\OpenIdHelper.cs" />
+ <Compile Include="Mvc\OpenIdAjaxOptions.cs" />
<Compile Include="OAuth\ChannelElements\ICombinedOpenIdProviderTokenManager.cs" />
<Compile Include="OAuth\ChannelElements\IConsumerDescription.cs" />
<Compile Include="OAuth\ChannelElements\IConsumerTokenManager.cs" />
@@ -302,6 +327,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OAuth\ConsumerSecuritySettings.cs" />
<Compile Include="OAuth\DesktopConsumer.cs" />
<Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Messaging\IMessageWithBinaryData.cs" />
<Compile Include="OAuth\Messages\ITokenSecretContainingMessage.cs" />
<Compile Include="Messaging\ChannelEventArgs.cs" />
<Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" />
@@ -429,12 +455,14 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\Extensions\UI\UIUtilities.cs" />
<Compile Include="OpenId\Extensions\UI\UIModes.cs" />
<Compile Include="OpenId\Extensions\UI\UIRequest.cs" />
+ <Compile Include="OpenId\HostMetaDiscoveryService.cs" />
<Compile Include="OpenId\Identifier.cs" />
<Compile Include="OpenId\IdentifierContract.cs" />
<Compile Include="OpenId\Extensions\ExtensionsInteropHelper.cs" />
<Compile Include="OpenId\Interop\AuthenticationResponseShim.cs" />
<Compile Include="OpenId\Interop\ClaimsResponseShim.cs" />
<Compile Include="OpenId\Interop\OpenIdRelyingPartyShim.cs" />
+ <Compile Include="OpenId\IIdentifierDiscoveryService.cs" />
<Compile Include="OpenId\Messages\CheckAuthenticationRequest.cs" />
<Compile Include="OpenId\Messages\CheckAuthenticationResponse.cs" />
<Compile Include="OpenId\Messages\CheckIdRequest.cs" />
@@ -501,6 +529,9 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\AssociationPreference.cs" />
<Compile Include="OpenId\RelyingParty\AuthenticationRequest.cs" />
<Compile Include="OpenId\RelyingParty\AuthenticationRequestMode.cs" />
+ <Compile Include="OpenId\RelyingParty\DuplicateRequestedHostsComparer.cs" />
+ <Compile Include="OpenId\RelyingParty\IProviderEndpoint.cs" />
+ <Compile Include="OpenId\RelyingParty\OpenIdAjaxRelyingParty.cs" />
<Compile Include="OpenId\RelyingParty\SelectorButtonContract.cs" />
<Compile Include="OpenId\RelyingParty\SelectorProviderButton.cs" />
<Compile Include="OpenId\RelyingParty\SelectorOpenIdButton.cs" />
@@ -508,14 +539,13 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\IRelyingPartyBehavior.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdSelector.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.cs" />
- <Compile Include="OpenId\RelyingParty\IXrdsProviderEndpointContract.cs" />
<Compile Include="OpenId\RelyingParty\IAuthenticationRequestContract.cs" />
<Compile Include="OpenId\RelyingParty\NegativeAuthenticationResponse.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdAjaxTextBox.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdButton.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdEventArgs.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdLogin.cs" />
- <Compile Include="OpenId\RelyingParty\OpenIdMobileTextBox.cs" />
+ <Compile Include="OpenId\RelyingParty\OpenIdMobileTextBox.cs" Condition=" '$(ClrVersion)' != '4' " />
<Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdTextBox.cs" />
<Compile Include="OpenId\RelyingParty\PopupBehavior.cs" />
@@ -525,9 +555,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\FailedAuthenticationResponse.cs" />
<Compile Include="OpenId\RelyingParty\IAuthenticationRequest.cs" />
<Compile Include="OpenId\RelyingParty\IAuthenticationResponse.cs" />
- <Compile Include="OpenId\RelyingParty\IProviderEndpoint.cs" />
<Compile Include="OpenId\RelyingParty\ISetupRequiredAuthenticationResponse.cs" />
- <Compile Include="OpenId\RelyingParty\IXrdsProviderEndpoint.cs" />
<Compile Include="OpenId\RelyingParty\OpenIdRelyingParty.cs" />
<Compile Include="OpenId\OpenIdStrings.Designer.cs">
<DependentUpon>OpenIdStrings.resx</DependentUpon>
@@ -542,7 +570,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\PrivateSecretManager.cs" />
<Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettings.cs" />
<Compile Include="OpenId\RelyingParty\SelectorButton.cs" />
- <Compile Include="OpenId\RelyingParty\ServiceEndpoint.cs" />
+ <Compile Include="OpenId\IdentifierDiscoveryResult.cs" />
<Compile Include="OpenId\OpenIdXrdsHelper.cs" />
<Compile Include="OpenId\RelyingParty\SimpleXrdsProviderEndpoint.cs" />
<Compile Include="OpenId\RelyingParty\StandardRelyingPartyApplicationStore.cs" />
@@ -550,7 +578,9 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OpenId\RelyingParty\WellKnownProviders.cs" />
<Compile Include="OpenId\SecuritySettings.cs" />
<Compile Include="Messaging\UntrustedWebRequestHandler.cs" />
+ <Compile Include="OpenId\UriDiscoveryService.cs" />
<Compile Include="OpenId\UriIdentifier.cs" />
+ <Compile Include="OpenId\XriDiscoveryProxyService.cs" />
<Compile Include="OpenId\XriIdentifier.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="OAuth\Messages\UnauthorizedTokenRequest.cs" />
@@ -586,6 +616,7 @@ http://opensource.org/licenses/ms-pl.html
</ItemGroup>
<ItemGroup>
<None Include="Configuration\DotNetOpenAuth.xsd" />
+ <None Include="Migrated rules for DotNetOpenAuth.ruleset" />
<None Include="OAuth\ClassDiagram.cd" />
<None Include="OAuth\Messages\OAuth Messages.cd" />
<None Include="Messaging\Bindings\Bindings.cd" />
@@ -618,7 +649,7 @@ http://opensource.org/licenses/ms-pl.html
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
- <EmbeddedResource Include="OpenId\RelyingParty\openid_login.gif" />
+ <EmbeddedResource Include="OpenId\RelyingParty\openid_login.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="OpenId\RelyingParty\login_failure.png" />
@@ -681,14 +712,49 @@ http://opensource.org/licenses/ms-pl.html
<ItemGroup>
<EmbeddedResource Include="OpenId\RelyingParty\OpenIdSelector.css" />
</ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
- <Import Project="..\..\tools\JavascriptPacker.targets" />
- <PropertyGroup>
- <CompileDependsOn>$(CompileDependsOn);CheckForCodeContracts</CompileDependsOn>
- </PropertyGroup>
- <Target Name="CheckForCodeContracts">
- <Error Condition=" '$(CodeContractsImported)' != 'true' "
- Text="This project requires Code Contracts. Please install from: http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx"/>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <Content Include="DotNetOpenAuth.ico" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <SignDependsOn Include="BuildUnifiedProduct" />
+ <DelaySignedAssemblies Include="$(ILMergeOutputAssembly);
+ $(OutputPath)CodeContracts\$(ProductName).Contracts.dll;
+ " />
+ </ItemGroup>
+ <PropertyGroup>
+ <!-- Don't sign the non-unified version of the assembly. -->
+ <SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly>
+ </PropertyGroup>
+
+ <Target Name="BuildUnifiedProduct"
+ DependsOnTargets="Build"
+ Inputs="@(ILMergeInputAssemblies)"
+ Outputs="$(ILMergeOutputAssembly)">
+ <MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" />
+ <ILMerge ExcludeFile="$(ProjectRoot)ILMergeInternalizeExceptions.txt"
+ InputAssemblies="@(ILMergeInputAssemblies)"
+ OutputFile="$(ILMergeOutputAssembly)"
+ KeyFile="$(PublicKeyFile)"
+ DelaySign="true"
+ />
</Target>
+
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
</Project>
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.ico b/src/DotNetOpenAuth/DotNetOpenAuth.ico
new file mode 100644
index 0000000..e227dbe
--- /dev/null
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.ico
Binary files differ
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index e436846..9b1bcfa 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -57,3 +57,6 @@
[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")]
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
index 86c1118..ae45229 100644
--- a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
+++ b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
@@ -268,6 +268,7 @@ namespace DotNetOpenAuth.InfoCard {
[Category(InfoCardCategory), DefaultValue(PrivacyUrlDefault)]
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "We construct a Uri to validate the format of the string.")]
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "That overload is NOT the same.")]
+ [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "This can take ~/ paths.")]
public string PrivacyUrl {
get {
return (string)this.ViewState[PrivacyUrlViewStateKey] ?? PrivacyUrlDefault;
@@ -570,24 +571,28 @@ namespace DotNetOpenAuth.InfoCard {
Panel supportedPanel = new Panel();
- if (!this.DesignMode) {
- // At the user agent, assume InfoCard is not supported until
- // the JavaScript discovers otherwise and reveals this panel.
- supportedPanel.Style[HtmlTextWriterStyle.Display] = "none";
- }
+ try {
+ if (!this.DesignMode) {
+ // At the user agent, assume InfoCard is not supported until
+ // the JavaScript discovers otherwise and reveals this panel.
+ supportedPanel.Style[HtmlTextWriterStyle.Display] = "none";
+ }
- supportedPanel.Controls.Add(this.CreateInfoCardImage());
+ supportedPanel.Controls.Add(this.CreateInfoCardImage());
- // trigger the selector at page load?
- if (this.AutoPopup && !this.Page.IsPostBack) {
- this.Page.ClientScript.RegisterStartupScript(
- typeof(InfoCardSelector),
- "selector_load_trigger",
- this.GetInfoCardSelectorActivationScript(true),
- true);
+ // trigger the selector at page load?
+ if (this.AutoPopup && !this.Page.IsPostBack) {
+ this.Page.ClientScript.RegisterStartupScript(
+ typeof(InfoCardSelector),
+ "selector_load_trigger",
+ this.GetInfoCardSelectorActivationScript(true),
+ true);
+ }
+ return supportedPanel;
+ } catch {
+ supportedPanel.Dispose();
+ throw;
}
-
- return supportedPanel;
}
/// <summary>
@@ -624,10 +629,15 @@ namespace DotNetOpenAuth.InfoCard {
Contract.Ensures(Contract.Result<Panel>() != null);
Panel unsupportedPanel = new Panel();
- if (this.UnsupportedTemplate != null) {
- this.UnsupportedTemplate.InstantiateIn(unsupportedPanel);
+ try {
+ if (this.UnsupportedTemplate != null) {
+ this.UnsupportedTemplate.InstantiateIn(unsupportedPanel);
+ }
+ return unsupportedPanel;
+ } catch {
+ unsupportedPanel.Dispose();
+ throw;
}
- return unsupportedPanel;
}
/// <summary>
@@ -692,13 +702,18 @@ namespace DotNetOpenAuth.InfoCard {
private Image CreateInfoCardImage() {
// add clickable image
Image image = new Image();
- image.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(InfoCardSelector), InfoCardImage.GetImageManifestResourceStreamName(this.ImageSize));
- image.AlternateText = InfoCardStrings.SelectorClickPrompt;
- image.ToolTip = this.ToolTip;
- image.Style[HtmlTextWriterStyle.Cursor] = "hand";
-
- image.Attributes["onclick"] = this.GetInfoCardSelectorActivationScript(false);
- return image;
+ try {
+ image.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(InfoCardSelector), InfoCardImage.GetImageManifestResourceStreamName(this.ImageSize));
+ image.AlternateText = InfoCardStrings.SelectorClickPrompt;
+ image.ToolTip = this.ToolTip;
+ image.Style[HtmlTextWriterStyle.Cursor] = "hand";
+
+ image.Attributes["onclick"] = this.GetInfoCardSelectorActivationScript(false);
+ return image;
+ } catch {
+ image.Dispose();
+ throw;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs
index 00eb1af..a6d3dcf 100644
--- a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs
+++ b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4918
+// Runtime Version:4.0.30104.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.InfoCard {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class InfoCardStrings {
diff --git a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
index 124f9f8..2ac2b7e 100644
--- a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
+++ b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
@@ -74,7 +74,13 @@ namespace DotNetOpenAuth.InfoCard {
public void AddDecryptingToken(X509Certificate2 certificate) {
Contract.Requires<ArgumentNullException>(certificate != null);
Contract.Requires<ArgumentException>(certificate.HasPrivateKey);
- this.AddDecryptingToken(new X509SecurityToken(certificate));
+ var cert = new X509SecurityToken(certificate);
+ try {
+ this.AddDecryptingToken(cert);
+ } catch {
+ cert.Dispose();
+ throw;
+ }
}
#if CONTRACTS_FULL
diff --git a/src/DotNetOpenAuth/InfoCard/Token/Token.cs b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
index 7fa9a95..89fa3a3 100644
--- a/src/DotNetOpenAuth/InfoCard/Token/Token.cs
+++ b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
@@ -49,16 +49,18 @@ namespace DotNetOpenAuth.InfoCard {
byte[] decryptedBytes;
string decryptedString;
- using (XmlReader tokenReader = XmlReader.Create(new StringReader(tokenXml))) {
- Contract.Assume(tokenReader != null); // BCL contract should say XmlReader.Create result != null
- if (IsEncrypted(tokenReader)) {
- Logger.InfoCard.DebugFormat("Incoming SAML token, before decryption: {0}", tokenXml);
- decryptedBytes = decryptor.DecryptToken(tokenReader);
- decryptedString = Encoding.UTF8.GetString(decryptedBytes);
- Contract.Assume(decryptedString != null); // BCL contracts should be enhanced here
- } else {
- decryptedBytes = Encoding.UTF8.GetBytes(tokenXml);
- decryptedString = tokenXml;
+ using (StringReader xmlReader = new StringReader(tokenXml)) {
+ using (XmlReader tokenReader = XmlReader.Create(xmlReader)) {
+ Contract.Assume(tokenReader != null); // BCL contract should say XmlReader.Create result != null
+ if (IsEncrypted(tokenReader)) {
+ Logger.InfoCard.DebugFormat("Incoming SAML token, before decryption: {0}", tokenXml);
+ decryptedBytes = decryptor.DecryptToken(tokenReader);
+ decryptedString = Encoding.UTF8.GetString(decryptedBytes);
+ Contract.Assume(decryptedString != null); // BCL contracts should be enhanced here
+ } else {
+ decryptedBytes = Encoding.UTF8.GetBytes(tokenXml);
+ decryptedString = tokenXml;
+ }
}
}
diff --git a/src/DotNetOpenAuth/InfoCard/Token/TokenUtility.cs b/src/DotNetOpenAuth/InfoCard/Token/TokenUtility.cs
index 48b7794..4ac871a 100644
--- a/src/DotNetOpenAuth/InfoCard/Token/TokenUtility.cs
+++ b/src/DotNetOpenAuth/InfoCard/Token/TokenUtility.cs
@@ -226,7 +226,9 @@ namespace DotNetOpenAuth.InfoCard {
int charMapLength = charMap.Length;
byte[] raw = Convert.FromBase64String(ppid);
- raw = SHA1.Create().ComputeHash(raw);
+ using (HashAlgorithm hasher = SHA1.Create()) {
+ raw = hasher.ComputeHash(raw);
+ }
StringBuilder callSign = new StringBuilder();
diff --git a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
index dd34d90..c9bc1d3 100644
--- a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
@@ -90,11 +90,16 @@ namespace DotNetOpenAuth.Messaging {
public override StreamReader GetResponseReader() {
this.ResponseStream.Seek(0, SeekOrigin.Begin);
string contentEncoding = this.Headers[HttpResponseHeader.ContentEncoding];
- if (string.IsNullOrEmpty(contentEncoding)) {
- return new StreamReader(this.ResponseStream);
- } else {
- return new StreamReader(this.ResponseStream, Encoding.GetEncoding(contentEncoding));
+ Encoding encoding = null;
+ if (!string.IsNullOrEmpty(contentEncoding)) {
+ try {
+ encoding = Encoding.GetEncoding(contentEncoding);
+ } catch (ArgumentException ex) {
+ Logger.Messaging.ErrorFormat("Encoding.GetEncoding(\"{0}\") threw ArgumentException: {1}", contentEncoding, ex);
+ }
}
+
+ return encoding != null ? new StreamReader(this.ResponseStream, encoding) : new StreamReader(this.ResponseStream);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index 831283a..cc411c8 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -695,27 +695,28 @@ namespace DotNetOpenAuth.Messaging {
WebHeaderCollection headers = new WebHeaderCollection();
headers.Add(HttpResponseHeader.ContentType, "text/html");
- StringWriter bodyWriter = new StringWriter(CultureInfo.InvariantCulture);
- StringBuilder hiddenFields = new StringBuilder();
- foreach (var field in fields) {
- hiddenFields.AppendFormat(
- "\t<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />\r\n",
- HttpUtility.HtmlEncode(field.Key),
- HttpUtility.HtmlEncode(field.Value));
+ using (StringWriter bodyWriter = new StringWriter(CultureInfo.InvariantCulture)) {
+ StringBuilder hiddenFields = new StringBuilder();
+ foreach (var field in fields) {
+ hiddenFields.AppendFormat(
+ "\t<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />\r\n",
+ HttpUtility.HtmlEncode(field.Key),
+ HttpUtility.HtmlEncode(field.Value));
+ }
+ bodyWriter.WriteLine(
+ IndirectMessageFormPostFormat,
+ HttpUtility.HtmlEncode(message.Recipient.AbsoluteUri),
+ hiddenFields);
+ bodyWriter.Flush();
+ OutgoingWebResponse response = new OutgoingWebResponse {
+ Status = HttpStatusCode.OK,
+ Headers = headers,
+ Body = bodyWriter.ToString(),
+ OriginalMessage = message
+ };
+
+ return response;
}
- bodyWriter.WriteLine(
- IndirectMessageFormPostFormat,
- HttpUtility.HtmlEncode(message.Recipient.AbsoluteUri),
- hiddenFields);
- bodyWriter.Flush();
- OutgoingWebResponse response = new OutgoingWebResponse {
- Status = HttpStatusCode.OK,
- Headers = headers,
- Body = bodyWriter.ToString(),
- OriginalMessage = message
- };
-
- return response;
}
/// <summary>
@@ -872,7 +873,18 @@ namespace DotNetOpenAuth.Messaging {
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(requestMessage.Recipient);
httpRequest.CachePolicy = this.CachePolicy;
httpRequest.Method = "POST";
- this.SendParametersInEntity(httpRequest, fields);
+
+ var requestMessageWithBinaryData = requestMessage as IMessageWithBinaryData;
+ if (requestMessageWithBinaryData != null && requestMessageWithBinaryData.SendAsMultipart) {
+ var multiPartFields = new List<MultipartPostPart>(requestMessageWithBinaryData.BinaryData);
+
+ // When sending multi-part, all data gets send as multi-part -- even the non-binary data.
+ multiPartFields.AddRange(fields.Select(field => MultipartPostPart.CreateFormPart(field.Key, field.Value)));
+ this.SendParametersInEntityAsMultipart(httpRequest, multiPartFields);
+ } else {
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || requestMessageWithBinaryData.BinaryData.Count == 0, MessagingStrings.BinaryDataRequiresMultipart);
+ this.SendParametersInEntity(httpRequest, fields);
+ }
return httpRequest;
}
@@ -942,6 +954,19 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Sends the given parameters in the entity stream of an HTTP request in multi-part format.
+ /// </summary>
+ /// <param name="httpRequest">The HTTP request.</param>
+ /// <param name="fields">The parameters to send.</param>
+ /// <remarks>
+ /// This method calls <see cref="HttpWebRequest.GetRequestStream()"/> and closes
+ /// the request stream, but does not call <see cref="HttpWebRequest.GetResponse"/>.
+ /// </remarks>
+ protected void SendParametersInEntityAsMultipart(HttpWebRequest httpRequest, IEnumerable<MultipartPostPart> fields) {
+ httpRequest.PostMultipartNoGetResponse(this.WebRequestHandler, fields);
+ }
+
+ /// <summary>
/// Verifies the integrity and applicability of an incoming message.
/// </summary>
/// <param name="message">The message just received.</param>
@@ -953,7 +978,7 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentNullException>(message != null);
if (Logger.Channel.IsInfoEnabled) {
- var messageAccessor = this.MessageDescriptions.GetAccessor(message);
+ var messageAccessor = this.MessageDescriptions.GetAccessor(message, true);
Logger.Channel.InfoFormat(
"Processing incoming {0} ({1}) message:{2}{3}",
message.GetType().Name,
diff --git a/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs b/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs
new file mode 100644
index 0000000..f411cf5
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs
@@ -0,0 +1,152 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessageWithBinaryData.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// The interface that classes must implement to be serialized/deserialized
+ /// as protocol or extension messages that uses POST multi-part data for binary content.
+ /// </summary>
+ [ContractClass(typeof(IMessageWithBinaryDataContract))]
+ public interface IMessageWithBinaryData : IDirectedProtocolMessage {
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ IList<MultipartPostPart> BinaryData { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ bool SendAsMultipart { get; }
+ }
+
+ /// <summary>
+ /// The contract class for the <see cref="IMessageWithBinaryData"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IMessageWithBinaryData))]
+ internal sealed class IMessageWithBinaryDataContract : IMessageWithBinaryData {
+ #region IMessageWithBinaryData Members
+
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ IList<MultipartPostPart> IMessageWithBinaryData.BinaryData {
+ get {
+ Contract.Ensures(Contract.Result<IList<MultipartPostPart>>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ bool IMessageWithBinaryData.SendAsMultipart {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IMessage Properties
+
+ /// <summary>
+ /// Gets the version of the protocol or extension this message is prepared to implement.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ Version IMessage.Version {
+ get {
+ Contract.Ensures(Contract.Result<Version>() != null);
+ return default(Version); // dummy return
+ }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-standard Protocol parameters included in the message.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ IDictionary<string, string> IMessage.ExtraData {
+ get {
+ Contract.Ensures(Contract.Result<IDictionary<string, string>>() != null);
+ return default(IDictionary<string, string>);
+ }
+ }
+
+ #endregion
+
+ #region IDirectedProtocolMessage Members
+
+ /// <summary>
+ /// Gets the preferred method of transport for the message.
+ /// </summary>
+ /// <remarks>
+ /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent:
+ /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript
+ /// to automate submission.
+ /// </remarks>
+ HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets the URL of the intended receiver of this message.
+ /// </summary>
+ Uri IDirectedProtocolMessage.Recipient {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IProtocolMessage Members
+
+ /// <summary>
+ /// Gets the level of protection this message requires.
+ /// </summary>
+ MessageProtections IProtocolMessage.RequiredProtection {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ MessageTransport IProtocolMessage.Transport {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IMessage methods
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ void IMessage.EnsureValidMessage() {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
index f2c9add..6f8c4f9 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4918
+// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Messaging {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class MessagingStrings {
@@ -70,6 +70,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to Unable to send all message data because some of it requires multi-part POST, but IMessageWithBinaryData.SendAsMultipart was false..
+ /// </summary>
+ internal static string BinaryDataRequiresMultipart {
+ get {
+ return ResourceManager.GetString("BinaryDataRequiresMultipart", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed..
/// </summary>
internal static string CurrentHttpContextRequired {
@@ -385,6 +394,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to An HttpContext.Current.Session object is required..
+ /// </summary>
+ internal static string SessionRequired {
+ get {
+ return ResourceManager.GetString("SessionRequired", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Message signature was incorrect..
/// </summary>
internal static string SignatureInvalid {
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
index 3d4e317..bdf4f68 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
@@ -297,4 +297,10 @@
<data name="StreamMustHaveKnownLength" xml:space="preserve">
<value>The stream must have a known length.</value>
</data>
+ <data name="BinaryDataRequiresMultipart" xml:space="preserve">
+ <value>Unable to send all message data because some of it requires multi-part POST, but IMessageWithBinaryData.SendAsMultipart was false.</value>
+ </data>
+ <data name="SessionRequired" xml:space="preserve">
+ <value>An HttpContext.Current.Session object is required.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 04d91de..6a55bc9 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -89,7 +89,7 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Transforms an OutgoingWebResponse to an MVC-friendly ActionResult.
/// </summary>
- /// <param name="response">The response to send to the uesr agent.</param>
+ /// <param name="response">The response to send to the user agent.</param>
/// <returns>The <see cref="ActionResult"/> instance to be returned by the Controller's action method.</returns>
public static ActionResult AsActionResult(this OutgoingWebResponse response) {
Contract.Requires<ArgumentNullException>(response != null);
@@ -107,14 +107,7 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
HttpContext context = HttpContext.Current;
- // We use Request.Url for the full path to the server, and modify it
- // with Request.RawUrl to capture both the cookieless session "directory" if it exists
- // and the original path in case URL rewriting is going on. We don't want to be
- // fooled by URL rewriting because we're comparing the actual URL with what's in
- // the return_to parameter in some cases.
- // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless
- // session, but not the URL rewriting problem.
- return new Uri(context.Request.Url, context.Request.RawUrl);
+ return HttpRequestInfo.GetPublicFacingUrl(context.Request, context.Request.ServerVariables);
}
/// <summary>
@@ -153,6 +146,63 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentNullException>(requestHandler != null);
Contract.Requires<ArgumentNullException>(parts != null);
+ PostMultipartNoGetResponse(request, requestHandler, parts);
+ return requestHandler.GetResponse(request);
+ }
+
+ /// <summary>
+ /// Assembles a message comprised of the message on a given exception and all inner exceptions.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ /// <returns>The assembled message.</returns>
+ public static string ToStringDescriptive(this Exception exception) {
+ // The input being null is probably bad, but since this method is called
+ // from a catch block, we don't really want to throw a new exception and
+ // hide the details of this one.
+ if (exception == null) {
+ Logger.Messaging.Error("MessagingUtilities.GetAllMessages called with null input.");
+ }
+
+ StringBuilder message = new StringBuilder();
+ while (exception != null) {
+ message.Append(exception.Message);
+ exception = exception.InnerException;
+ if (exception != null) {
+ message.Append(" ");
+ }
+ }
+
+ return message.ToString();
+ }
+
+ /// <summary>
+ /// Flattens the specified sequence of sequences.
+ /// </summary>
+ /// <typeparam name="T">The type of element contained in the sequence.</typeparam>
+ /// <param name="sequence">The sequence of sequences to flatten.</param>
+ /// <returns>A sequence of the contained items.</returns>
+ [Obsolete("Use Enumerable.SelectMany instead.")]
+ public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> sequence) {
+ ErrorUtilities.VerifyArgumentNotNull(sequence, "sequence");
+
+ foreach (IEnumerable<T> subsequence in sequence) {
+ foreach (T item in subsequence) {
+ yield return item;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sends a multipart HTTP POST request (useful for posting files) but doesn't call GetResponse on it.
+ /// </summary>
+ /// <param name="request">The HTTP request.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="parts">The parts to include in the POST entity.</param>
+ internal static void PostMultipartNoGetResponse(this HttpWebRequest request, IDirectWebRequestHandler requestHandler, IEnumerable<MultipartPostPart> parts) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Requires<ArgumentNullException>(parts != null);
+
Reporting.RecordFeatureUse("MessagingUtilities.PostMultipart");
parts = parts.CacheGeneratedResults();
string boundary = Guid.NewGuid().ToString();
@@ -193,33 +243,6 @@ namespace DotNetOpenAuth.Messaging {
requestStream.Dispose();
}
}
-
- return requestHandler.GetResponse(request);
- }
-
- /// <summary>
- /// Assembles a message comprised of the message on a given exception and all inner exceptions.
- /// </summary>
- /// <param name="exception">The exception.</param>
- /// <returns>The assembled message.</returns>
- public static string ToStringDescriptive(this Exception exception) {
- // The input being null is probably bad, but since this method is called
- // from a catch block, we don't really want to throw a new exception and
- // hide the details of this one.
- if (exception == null) {
- Logger.Messaging.Error("MessagingUtilities.GetAllMessages called with null input.");
- }
-
- StringBuilder message = new StringBuilder();
- while (exception != null) {
- message.Append(exception.Message);
- exception = exception.InnerException;
- if (exception != null) {
- message.Append(" ");
- }
- }
-
- return message.ToString();
}
/// <summary>
@@ -324,6 +347,7 @@ namespace DotNetOpenAuth.Messaging {
}
}
+#if !CLR4
/// <summary>
/// Copies the contents of one stream to another.
/// </summary>
@@ -339,8 +363,9 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentNullException>(copyTo != null);
Contract.Requires<ArgumentException>(copyFrom.CanRead, MessagingStrings.StreamUnreadable);
Contract.Requires<ArgumentException>(copyTo.CanWrite, MessagingStrings.StreamUnwritable);
- return CopyTo(copyFrom, copyTo, int.MaxValue);
+ return CopyUpTo(copyFrom, copyTo, int.MaxValue);
}
+#endif
/// <summary>
/// Copies the contents of one stream to another.
@@ -353,7 +378,7 @@ namespace DotNetOpenAuth.Messaging {
/// Copying begins at the streams' current positions.
/// The positions are NOT reset after copying is complete.
/// </remarks>
- internal static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) {
+ internal static int CopyUpTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) {
Contract.Requires<ArgumentNullException>(copyFrom != null);
Contract.Requires<ArgumentNullException>(copyTo != null);
Contract.Requires<ArgumentException>(copyFrom.CanRead, MessagingStrings.StreamUnreadable);
@@ -755,7 +780,10 @@ namespace DotNetOpenAuth.Messaging {
if (throwOnNullKey) {
throw new ArgumentException(MessagingStrings.UnexpectedNullKey);
} else {
- Logger.OpenId.WarnFormat("Null key with value {0} encountered while translating NameValueCollection to Dictionary.", nvc[key]);
+ // Only emit a warning if there was a non-empty value.
+ if (!string.IsNullOrEmpty(nvc[key])) {
+ Logger.OpenId.WarnFormat("Null key with value {0} encountered while translating NameValueCollection to Dictionary.", nvc[key]);
+ }
}
} else {
dictionary.Add(key, nvc[key]);
@@ -847,7 +875,7 @@ namespace DotNetOpenAuth.Messaging {
/// by using appropriate character escaping.
/// </summary>
/// <param name="value">The untrusted string value to be escaped to protected against XSS attacks. May be null.</param>
- /// <returns>The escaped string.</returns>
+ /// <returns>The escaped string, surrounded by single-quotes.</returns>
internal static string GetSafeJavascriptValue(string value) {
if (value == null) {
return "null";
diff --git a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
index 06cb5fc..cc655cf 100644
--- a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs
@@ -57,7 +57,7 @@ namespace DotNetOpenAuth.Messaging {
this.ResponseStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : (int)response.ContentLength);
using (Stream responseStream = response.GetResponseStream()) {
// BUGBUG: strictly speaking, is the response were exactly the limit, we'd report it as truncated here.
- this.IsResponseTruncated = responseStream.CopyTo(this.ResponseStream, maximumBytesToRead) == maximumBytesToRead;
+ this.IsResponseTruncated = responseStream.CopyUpTo(this.ResponseStream, maximumBytesToRead) == maximumBytesToRead;
this.ResponseStream.Seek(0, SeekOrigin.Begin);
}
}
@@ -183,7 +183,10 @@ namespace DotNetOpenAuth.Messaging {
/// would transmit the message that normally would be transmitted via a user agent redirect.
/// </summary>
/// <param name="channel">The channel to use for encoding.</param>
- /// <returns>The URL that would transmit the original message.</returns>
+ /// <returns>
+ /// The URL that would transmit the original message. This URL may exceed the normal 2K limit,
+ /// and should therefore be broken up manually and POSTed as form fields when it exceeds this length.
+ /// </returns>
/// <remarks>
/// This is useful for desktop applications that will spawn a user agent to transmit the message
/// rather than cause a redirect.
diff --git a/src/DotNetOpenAuth/Messaging/ProtocolException.cs b/src/DotNetOpenAuth/Messaging/ProtocolException.cs
index 25f8eee..fb9ec6d 100644
--- a/src/DotNetOpenAuth/Messaging/ProtocolException.cs
+++ b/src/DotNetOpenAuth/Messaging/ProtocolException.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.Messaging {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+ using System.Security;
using System.Security.Permissions;
/// <summary>
@@ -79,7 +80,11 @@ namespace DotNetOpenAuth.Messaging {
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="*AllFiles*" PathDiscovery="*AllFiles*"/>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter"/>
/// </PermissionSet>
+#if CLR4
+ [SecurityCritical]
+#else
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
+#endif
public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) {
base.GetObjectData(info, context);
throw new NotImplementedException();
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/IMessagePartOriginalEncoder.cs b/src/DotNetOpenAuth/Messaging/Reflection/IMessagePartOriginalEncoder.cs
new file mode 100644
index 0000000..9ad55c9
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/Reflection/IMessagePartOriginalEncoder.cs
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessagePartOriginalEncoder.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging.Reflection {
+ /// <summary>
+ /// An interface describing how various objects can be serialized and deserialized between their object and string forms.
+ /// </summary>
+ /// <remarks>
+ /// Implementations of this interface must include a default constructor and must be thread-safe.
+ /// </remarks>
+ public interface IMessagePartOriginalEncoder : IMessagePartEncoder {
+ /// <summary>
+ /// Encodes the specified value as the original value that was formerly decoded.
+ /// </summary>
+ /// <param name="value">The value. Guaranteed to never be null.</param>
+ /// <returns>The <paramref name="value"/> in string form, ready for message transport.</returns>
+ string EncodeAsOriginalString(object value);
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescription.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescription.cs
index 5493ba6..3b41b35 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescription.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescription.cs
@@ -66,7 +66,20 @@ namespace DotNetOpenAuth.Messaging.Reflection {
internal MessageDictionary GetDictionary(IMessage message) {
Contract.Requires<ArgumentNullException>(message != null);
Contract.Ensures(Contract.Result<MessageDictionary>() != null);
- return new MessageDictionary(message, this);
+ return this.GetDictionary(message, false);
+ }
+
+ /// <summary>
+ /// Gets a dictionary that provides read/write access to a message.
+ /// </summary>
+ /// <param name="message">The message the dictionary should provide access to.</param>
+ /// <param name="getOriginalValues">A value indicating whether this message dictionary will retrieve original values instead of normalized ones.</param>
+ /// <returns>The dictionary accessor to the message</returns>
+ [Pure]
+ internal MessageDictionary GetDictionary(IMessage message, bool getOriginalValues) {
+ Contract.Requires<ArgumentNullException>(message != null);
+ Contract.Ensures(Contract.Result<MessageDictionary>() != null);
+ return new MessageDictionary(message, this, getOriginalValues);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
index ff8b74b..125742c 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
@@ -78,7 +78,19 @@ namespace DotNetOpenAuth.Messaging.Reflection {
[Pure]
internal MessageDictionary GetAccessor(IMessage message) {
Contract.Requires<ArgumentNullException>(message != null);
- return this.Get(message).GetDictionary(message);
+ return this.GetAccessor(message, false);
+ }
+
+ /// <summary>
+ /// Gets the dictionary that provides read/write access to a message.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <param name="getOriginalValues">A value indicating whether this message dictionary will retrieve original values instead of normalized ones.</param>
+ /// <returns>The dictionary.</returns>
+ [Pure]
+ internal MessageDictionary GetAccessor(IMessage message, bool getOriginalValues) {
+ Contract.Requires<ArgumentNullException>(message != null);
+ return this.Get(message).GetDictionary(message, getOriginalValues);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
index f6eed24..2b60a9c 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
@@ -30,17 +30,24 @@ namespace DotNetOpenAuth.Messaging.Reflection {
private readonly MessageDescription description;
/// <summary>
+ /// Whether original string values should be retrieved instead of normalized ones.
+ /// </summary>
+ private readonly bool getOriginalValues;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="MessageDictionary"/> class.
/// </summary>
/// <param name="message">The message instance whose values will be manipulated by this dictionary.</param>
/// <param name="description">The message description.</param>
+ /// <param name="getOriginalValues">A value indicating whether this message dictionary will retrieve original values instead of normalized ones.</param>
[Pure]
- internal MessageDictionary(IMessage message, MessageDescription description) {
+ internal MessageDictionary(IMessage message, MessageDescription description, bool getOriginalValues) {
Contract.Requires<ArgumentNullException>(message != null);
Contract.Requires<ArgumentNullException>(description != null);
this.message = message;
this.description = description;
+ this.getOriginalValues = getOriginalValues;
}
/// <summary>
@@ -103,7 +110,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
List<string> keys = new List<string>(this.description.Mapping.Count);
foreach (var pair in this.description.Mapping) {
// Don't include keys with null values, but default values for structs is ok
- if (pair.Value.GetValue(this.message) != null) {
+ if (pair.Value.GetValue(this.message, this.getOriginalValues) != null) {
keys.Add(pair.Key);
}
}
@@ -126,8 +133,8 @@ namespace DotNetOpenAuth.Messaging.Reflection {
get {
List<string> values = new List<string>(this.message.ExtraData.Count + this.description.Mapping.Count);
foreach (MessagePart part in this.description.Mapping.Values) {
- if (part.GetValue(this.message) != null) {
- values.Add(part.GetValue(this.message));
+ if (part.GetValue(this.message, this.getOriginalValues) != null) {
+ values.Add(part.GetValue(this.message, this.getOriginalValues));
}
}
@@ -167,7 +174,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
MessagePart part;
if (this.description.Mapping.TryGetValue(key, out part)) {
// Never throw KeyNotFoundException for declared properties.
- return part.GetValue(this.message);
+ return part.GetValue(this.message, this.getOriginalValues);
} else {
return this.message.ExtraData[key];
}
@@ -223,7 +230,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <returns>True if the parameter by the given name has a set value. False otherwise.</returns>
public bool ContainsKey(string key) {
return this.message.ExtraData.ContainsKey(key) ||
- (this.description.Mapping.ContainsKey(key) && this.description.Mapping[key].GetValue(this.message) != null);
+ (this.description.Mapping.ContainsKey(key) && this.description.Mapping[key].GetValue(this.message, this.getOriginalValues) != null);
}
/// <summary>
@@ -237,7 +244,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
} else {
MessagePart part;
if (this.description.Mapping.TryGetValue(key, out part)) {
- if (part.GetValue(this.message) != null) {
+ if (part.GetValue(this.message, this.getOriginalValues) != null) {
part.SetValue(this.message, null);
return true;
}
@@ -255,7 +262,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
public bool TryGetValue(string key, out string value) {
MessagePart part;
if (this.description.Mapping.TryGetValue(key, out part)) {
- value = part.GetValue(this.message);
+ value = part.GetValue(this.message, this.getOriginalValues);
return value != null;
}
return this.message.ExtraData.TryGetValue(key, out value);
@@ -306,7 +313,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
public bool Contains(KeyValuePair<string, string> item) {
MessagePart part;
if (this.description.Mapping.TryGetValue(item.Key, out part)) {
- return string.Equals(part.GetValue(this.message), item.Value, StringComparison.Ordinal);
+ return string.Equals(part.GetValue(this.message, this.getOriginalValues), item.Value, StringComparison.Ordinal);
} else {
return this.message.ExtraData.Contains(item);
}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index 08e2411..b876ec4 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
using System.Net.Security;
using System.Reflection;
using System.Xml;
+ using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.OpenId;
/// <summary>
@@ -73,10 +74,10 @@ namespace DotNetOpenAuth.Messaging.Reflection {
Contract.Assume(str != null);
return bool.Parse(str);
};
- Func<string, Identifier> safeIdentfier = str => {
+ Func<string, Identifier> safeIdentifier = str => {
Contract.Assume(str != null);
ErrorUtilities.VerifyFormat(str.Length > 0, MessagingStrings.NonEmptyStringExpected);
- return Identifier.Parse(str);
+ return Identifier.Parse(str, true);
};
Func<byte[], string> safeFromByteArray = bytes => {
Contract.Assume(bytes != null);
@@ -90,14 +91,14 @@ namespace DotNetOpenAuth.Messaging.Reflection {
Contract.Assume(str != null);
return new Realm(str);
};
- Map<Uri>(uri => uri.AbsoluteUri, safeUri);
- Map<DateTime>(dt => XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Utc), str => XmlConvert.ToDateTime(str, XmlDateTimeSerializationMode.Utc));
- Map<byte[]>(safeFromByteArray, safeToByteArray);
- Map<Realm>(realm => realm.ToString(), safeRealm);
- Map<Identifier>(id => id.ToString(), safeIdentfier);
- Map<bool>(value => value.ToString().ToLowerInvariant(), safeBool);
- Map<CultureInfo>(c => c.Name, str => new CultureInfo(str));
- Map<CultureInfo[]>(cs => string.Join(",", cs.Select(c => c.Name).ToArray()), str => str.Split(',').Select(s => new CultureInfo(s)).ToArray());
+ Map<Uri>(uri => uri.AbsoluteUri, uri => uri.OriginalString, safeUri);
+ Map<DateTime>(dt => XmlConvert.ToString(dt, XmlDateTimeSerializationMode.Utc), null, str => XmlConvert.ToDateTime(str, XmlDateTimeSerializationMode.Utc));
+ Map<byte[]>(safeFromByteArray, null, safeToByteArray);
+ Map<Realm>(realm => realm.ToString(), realm => realm.OriginalString, safeRealm);
+ Map<Identifier>(id => id.SerializedString, id => id.OriginalString, safeIdentifier);
+ Map<bool>(value => value.ToString().ToLowerInvariant(), null, safeBool);
+ Map<CultureInfo>(c => c.Name, null, str => new CultureInfo(str));
+ Map<CultureInfo[]>(cs => string.Join(",", cs.Select(c => c.Name).ToArray()), null, str => str.Split(',').Select(s => new CultureInfo(s)).ToArray());
}
/// <summary>
@@ -129,9 +130,28 @@ namespace DotNetOpenAuth.Messaging.Reflection {
Contract.Assume(this.memberDeclaredType != null); // CC missing PropertyInfo.PropertyType ensures result != null
if (attribute.Encoder == null) {
if (!converters.TryGetValue(this.memberDeclaredType, out this.converter)) {
- this.converter = new ValueMapping(
- obj => obj != null ? obj.ToString() : null,
- str => str != null ? Convert.ChangeType(str, this.memberDeclaredType, CultureInfo.InvariantCulture) : null);
+ if (this.memberDeclaredType.IsGenericType &&
+ this.memberDeclaredType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
+ // It's a nullable type. Try again to look up an appropriate converter for the underlying type.
+ Type underlyingType = Nullable.GetUnderlyingType(this.memberDeclaredType);
+ ValueMapping underlyingMapping;
+ if (converters.TryGetValue(underlyingType, out underlyingMapping)) {
+ this.converter = new ValueMapping(
+ underlyingMapping.ValueToString,
+ null,
+ str => str != null ? underlyingMapping.StringToValue(str) : null);
+ } else {
+ this.converter = new ValueMapping(
+ obj => obj != null ? obj.ToString() : null,
+ null,
+ str => str != null ? Convert.ChangeType(str, underlyingType, CultureInfo.InvariantCulture) : null);
+ }
+ } else {
+ this.converter = new ValueMapping(
+ obj => obj != null ? obj.ToString() : null,
+ null,
+ str => str != null ? Convert.ChangeType(str, this.memberDeclaredType, CultureInfo.InvariantCulture) : null);
+ }
}
} else {
this.converter = new ValueMapping(GetEncoder(attribute.Encoder));
@@ -189,7 +209,8 @@ namespace DotNetOpenAuth.Messaging.Reflection {
try {
if (this.IsConstantValue) {
string constantValue = this.GetValue(message);
- if (!string.Equals(constantValue, value)) {
+ var caseSensitivity = DotNetOpenAuthSection.Configuration.Messaging.Strict ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
+ if (!string.Equals(constantValue, value, caseSensitivity)) {
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
MessagingStrings.UnexpectedMessagePartValueForConstant,
@@ -211,7 +232,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
}
/// <summary>
- /// Gets the value of a member of a given message.
+ /// Gets the normalized form of a value of a member of a given message.
/// Used in serialization.
/// </summary>
/// <param name="message">The message instance to read the value from.</param>
@@ -219,7 +240,23 @@ namespace DotNetOpenAuth.Messaging.Reflection {
internal string GetValue(IMessage message) {
try {
object value = this.GetValueAsObject(message);
- return this.ToString(value);
+ return this.ToString(value, false);
+ } catch (FormatException ex) {
+ throw ErrorUtilities.Wrap(ex, MessagingStrings.MessagePartWriteFailure, message.GetType(), this.Name);
+ }
+ }
+
+ /// <summary>
+ /// Gets the value of a member of a given message.
+ /// Used in serialization.
+ /// </summary>
+ /// <param name="message">The message instance to read the value from.</param>
+ /// <param name="originalValue">A value indicating whether the original value should be retrieved (as opposed to a normalized form of it).</param>
+ /// <returns>The string representation of the member's value.</returns>
+ internal string GetValue(IMessage message, bool originalValue) {
+ try {
+ object value = this.GetValueAsObject(message);
+ return this.ToString(value, originalValue);
} catch (FormatException ex) {
throw ErrorUtilities.Wrap(ex, MessagingStrings.MessagePartWriteFailure, message.GetType(), this.Name);
}
@@ -252,15 +289,24 @@ namespace DotNetOpenAuth.Messaging.Reflection {
}
/// <summary>
- /// Adds a pair of type conversion functions to the static converstion map.
+ /// Adds a pair of type conversion functions to the static conversion map.
/// </summary>
/// <typeparam name="T">The custom type to convert to and from strings.</typeparam>
/// <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>
- private static void Map<T>(Func<T, string> toString, Func<string, T> toValue) {
+ 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");
+
+ if (toOriginalString == null) {
+ toOriginalString = toString;
+ }
+
Func<object, string> safeToString = obj => obj != null ? toString((T)obj) : null;
+ Func<object, string> safeToOriginalString = obj => obj != null ? toOriginalString((T)obj) : null;
Func<string, object> safeToT = str => str != null ? toValue(str) : default(T);
- converters.Add(typeof(T), new ValueMapping(safeToString, safeToT));
+ converters.Add(typeof(T), new ValueMapping(safeToString, safeToOriginalString, safeToT));
}
/// <summary>
@@ -312,11 +358,12 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// Converts the member's value to its string representation.
/// </summary>
/// <param name="value">The value of the member.</param>
+ /// <param name="originalString">A value indicating whether a string matching the originally decoded string should be returned (as opposed to a normalized string).</param>
/// <returns>
/// The string representation of the member's value.
/// </returns>
- private string ToString(object value) {
- return this.converter.ValueToString(value);
+ private string ToString(object value, bool originalString) {
+ return originalString ? this.converter.ValueToOriginalString(value) : this.converter.ValueToString(value);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/ValueMapping.cs b/src/DotNetOpenAuth/Messaging/Reflection/ValueMapping.cs
index 1c7631e..b0b8b47 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/ValueMapping.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/ValueMapping.cs
@@ -19,6 +19,12 @@ namespace DotNetOpenAuth.Messaging.Reflection {
internal readonly Func<object, string> ValueToString;
/// <summary>
+ /// The mapping function that converts some custom type to the original string
+ /// (possibly non-normalized) that represents it.
+ /// </summary>
+ internal readonly Func<object, string> ValueToOriginalString;
+
+ /// <summary>
/// The mapping function that converts a string to some custom type.
/// </summary>
internal readonly Func<string, object> StringToValue;
@@ -26,13 +32,15 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <summary>
/// Initializes a new instance of the <see cref="ValueMapping"/> struct.
/// </summary>
- /// <param name="toString">The mapping function that converts some custom type to a string.</param>
- /// <param name="toValue">The mapping function that converts a string to some custom type.</param>
- internal ValueMapping(Func<object, string> toString, Func<string, object> toValue) {
+ /// <param name="toString">The mapping function that converts some custom value 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 mapping function that converts a string to some custom value.</param>
+ internal ValueMapping(Func<object, string> toString, Func<object, string> toOriginalString, Func<string, object> toValue) {
Contract.Requires<ArgumentNullException>(toString != null);
Contract.Requires<ArgumentNullException>(toValue != null);
this.ValueToString = toString;
+ this.ValueToOriginalString = toOriginalString ?? toString;
this.StringToValue = toValue;
}
@@ -45,8 +53,15 @@ namespace DotNetOpenAuth.Messaging.Reflection {
var nullEncoder = encoder as IMessagePartNullEncoder;
string nullString = nullEncoder != null ? nullEncoder.EncodedNullValue : null;
+ var originalStringEncoder = encoder as IMessagePartOriginalEncoder;
+ Func<object, string> originalStringEncode = encoder.Encode;
+ if (originalStringEncoder != null) {
+ originalStringEncode = originalStringEncoder.EncodeAsOriginalString;
+ }
+
this.ValueToString = obj => (obj != null) ? encoder.Encode(obj) : nullString;
this.StringToValue = str => (str != null) ? encoder.Decode(str) : null;
+ this.ValueToOriginalString = obj => (obj != null) ? originalStringEncode(obj) : nullString;
}
}
}
diff --git a/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
new file mode 100644
index 0000000..db238b6
--- /dev/null
+++ b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RuleSet Name="Migrated rules for DotNetOpenAuth.ruleset" Description="This rule set was created from the CodeAnalysisRules property for the &quot;Debug (Any CPU)&quot; configuration in project &quot;C:\Users\andarno\git\dotnetopenid\src\DotNetOpenAuth\DotNetOpenAuth.csproj&quot;." ToolsVersion="10.0">
+ <IncludeAll Action="Warning" />
+ <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
+ <Rule Id="CA1054" Action="None" />
+ <Rule Id="CA1055" Action="None" />
+ <Rule Id="CA1056" Action="None" />
+ <Rule Id="CA2104" Action="None" />
+ </Rules>
+</RuleSet> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Mvc/OpenIdAjaxOptions.cs b/src/DotNetOpenAuth/Mvc/OpenIdAjaxOptions.cs
new file mode 100644
index 0000000..4b88d04
--- /dev/null
+++ b/src/DotNetOpenAuth/Mvc/OpenIdAjaxOptions.cs
@@ -0,0 +1,76 @@
+//-----------------------------------------------------------------------
+// <copyright file="OpenIdAjaxOptions.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Mvc {
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A set of customizations available for the scripts sent to the browser in AJAX OpenID scenarios.
+ /// </summary>
+ public class OpenIdAjaxOptions {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdAjaxOptions"/> class.
+ /// </summary>
+ public OpenIdAjaxOptions() {
+ this.AssertionHiddenFieldId = "openid_openidAuthData";
+ this.ReturnUrlHiddenFieldId = "ReturnUrl";
+ }
+
+ /// <summary>
+ /// Gets or sets the ID of the hidden field that should carry the positive assertion
+ /// until it is posted to the RP.
+ /// </summary>
+ public string AssertionHiddenFieldId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the ID of the hidden field that should be set with the parent window/frame's URL
+ /// prior to posting the form with the positive assertion. Useful for jQuery popup dialogs.
+ /// </summary>
+ public string ReturnUrlHiddenFieldId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the index of the form in the document.forms array on the browser that should
+ /// be submitted when the user is ready to send the positive assertion to the RP.
+ /// </summary>
+ public int FormIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id of the form in the document.forms array on the browser that should
+ /// be submitted when the user is ready to send the positive assertion to the RP. A value
+ /// in this property takes precedence over any value in the <see cref="FormIndex"/> property.
+ /// </summary>
+ /// <value>The form id.</value>
+ public string FormId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the preloaded discovery results.
+ /// </summary>
+ public string PreloadedDiscoveryResults { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to print diagnostic trace messages in the browser.
+ /// </summary>
+ public bool ShowDiagnosticTrace { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to show all the "hidden" iframes that facilitate
+ /// asynchronous authentication of the user for diagnostic purposes.
+ /// </summary>
+ public bool ShowDiagnosticIFrame { get; set; }
+
+ /// <summary>
+ /// Gets the form key to use when accessing the relevant form.
+ /// </summary>
+ internal string FormKey {
+ get { return string.IsNullOrEmpty(this.FormId) ? this.FormIndex.ToString(CultureInfo.InvariantCulture) : MessagingUtilities.GetSafeJavascriptValue(this.FormId); }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
new file mode 100644
index 0000000..193e445
--- /dev/null
+++ b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
@@ -0,0 +1,432 @@
+//-----------------------------------------------------------------------
+// <copyright file="OpenIdHelper.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Mvc {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using System.Web;
+ using System.Web.Mvc;
+ using System.Web.Routing;
+ using System.Web.UI;
+ using DotNetOpenAuth.Configuration;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ /// <summary>
+ /// Methods that generate HTML or Javascript for hosting AJAX OpenID "controls" on
+ /// ASP.NET MVC web sites.
+ /// </summary>
+ public static class OpenIdHelper {
+ /// <summary>
+ /// Emits a series of stylesheet import tags to support the AJAX OpenID Selector.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <returns>HTML that should be sent directly to the browser.</returns>
+ public static string OpenIdSelectorStyles(this HtmlHelper html, Page page) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ StringWriter result = new StringWriter();
+ result.WriteStylesheetLink(page, OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName);
+ result.WriteStylesheetLink(page, OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName);
+ return result.ToString();
+ }
+
+ /// <summary>
+ /// Emits a series of script import tags and some inline script to support the AJAX OpenID Selector.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <returns>HTML that should be sent directly to the browser.</returns>
+ public static string OpenIdSelectorScripts(this HtmlHelper html, Page page) {
+ return OpenIdSelectorScripts(html, page, null, null);
+ }
+
+ /// <summary>
+ /// Emits a series of script import tags and some inline script to support the AJAX OpenID Selector.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="selectorOptions">An optional instance of an <see cref="OpenIdSelector"/> control, whose properties have been customized to express how this MVC control should be rendered.</param>
+ /// <param name="additionalOptions">An optional set of additional script customizations.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ public static string OpenIdSelectorScripts(this HtmlHelper html, Page page, OpenIdSelector selectorOptions, OpenIdAjaxOptions additionalOptions) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ if (selectorOptions == null) {
+ selectorOptions = new OpenId.RelyingParty.OpenIdSelector();
+ }
+
+ 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
+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[] {
+ OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource,
+ OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource,
+ OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedScriptResourceName,
+ };
+ result.WriteScriptTags(page, scriptResources);
+
+ if (selectorOptions.DownloadYahooUILibrary) {
+ result.WriteScriptTags(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 {
+ if (YAHOO) {
+ var loader = new YAHOO.util.YUILoader({
+ require: ['button', 'menu'],
+ loadOptional: false,
+ combine: true
+ });
+
+ loader.insert();
+ }
+ } catch (e) { }");
+ }
+
+ 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));
+
+ 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) {{
+ jQuery.ajax({{
+ async: true,
+ dataType: 'text',
+ error: function (request, status, error) {{ errorCallback(status, argument); }},
+ success: function (result) {{ resultFunction(result, argument); }},
+ url: '{1}'.replace('xxx', encodeURIComponent(argument))
+ }});
+ }};";
+ blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl);
+
+ 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);
+
+ 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
+ {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17},
+ false, // auto postback
+ null); // PostBackEventReference (unused in MVC)
+ }});";
+ blockBuilder.WriteLine(
+ blockFormat,
+ MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(page.ClientScript.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(page, OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName);
+
+ Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name);
+ return result.ToString();
+ }
+
+ /// <summary>
+ /// Emits the HTML to render an OpenID Provider button as a part of the overall OpenID Selector UI.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="providerIdentifier">The OP Identifier.</param>
+ /// <param name="imageUrl">The URL of the image to display on the button.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ public static string OpenIdSelectorOPButton(this HtmlHelper html, Page page, Identifier providerIdentifier, string imageUrl) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentNullException>(providerIdentifier != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return OpenIdSelectorButton(html, page, providerIdentifier, "OPButton", imageUrl);
+ }
+
+ /// <summary>
+ /// Emits the HTML to render a generic OpenID button as a part of the overall OpenID Selector UI,
+ /// allowing the user to enter their own OpenID.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="imageUrl">The URL of the image to display on the button.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ public static string OpenIdSelectorOpenIdButton(this HtmlHelper html, Page page, string imageUrl) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ return OpenIdSelectorButton(html, page, "OpenIDButton", "OpenIDButton", imageUrl);
+ }
+
+ /// <summary>
+ /// Emits the HTML to render the entire OpenID Selector UI.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="buttons">The buttons to include on the selector.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ public static string OpenIdSelector(this HtmlHelper html, Page page, params SelectorButton[] buttons) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentNullException>(buttons != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ var writer = new StringWriter();
+ var h = new HtmlTextWriter(writer);
+
+ 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, page, op.OPIdentifier, op.Image));
+ continue;
+ }
+
+ var openid = button as SelectorOpenIdButton;
+ if (openid != null) {
+ h.Write(OpenIdSelectorOpenIdButton(html, page, openid.Image));
+ continue;
+ }
+
+ ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name);
+ }
+
+ h.RenderEndTag(); // ul
+
+ if (buttons.OfType<SelectorOpenIdButton>().Any()) {
+ h.Write(OpenIdAjaxTextBox(html));
+ }
+
+ return writer.ToString();
+ }
+
+ /// <summary>
+ /// Emits the HTML to render the <see cref="OpenIdAjaxTextBox"/> control as a part of the overall
+ /// OpenID Selector UI.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ 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'>
+ <input name='openid_identifier' id='openid_identifier' size='40' style='padding-left: 18px; border-style: solid; border-width: 1px; border-color: lightgray' />
+ </span>
+ </div>";
+ }
+
+ /// <summary>
+ /// Emits the HTML to render a button as a part of the overall OpenID Selector UI.
+ /// </summary>
+ /// <param name="html">The <see cref="HtmlHelper"/> on the view.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="id">The value to assign to the HTML id attribute.</param>
+ /// <param name="cssClass">The value to assign to the HTML class attribute.</param>
+ /// <param name="imageUrl">The URL of the image to draw on the button.</param>
+ /// <returns>
+ /// HTML that should be sent directly to the browser.
+ /// </returns>
+ private static string OpenIdSelectorButton(this HtmlHelper html, Page page, string id, string cssClass, string imageUrl) {
+ Contract.Requires<ArgumentNullException>(html != null);
+ Contract.Requires<ArgumentNullException>(page != 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);
+
+ h.AddAttribute(HtmlTextWriterAttribute.Href, "#");
+ h.RenderBeginTag(HtmlTextWriterTag.A);
+
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+
+ h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
+ h.RenderBeginTag(HtmlTextWriterTag.Img);
+ h.RenderEndTag();
+
+ h.AddAttribute(HtmlTextWriterAttribute.Src, page.ClientScript.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.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay");
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderEndTag(); // div
+
+ h.RenderEndTag(); // div
+ h.RenderEndTag(); // a
+ h.RenderEndTag(); // li
+
+ return writer.ToString();
+ }
+
+ /// <summary>
+ /// Emits &lt;script&gt; tags that import a given set of scripts given their URLs.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="scriptUrls">The locations of the scripts to import.</param>
+ private static void WriteScriptTags(this TextWriter writer, IEnumerable<string> scriptUrls) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentNullException>(scriptUrls != null);
+
+ foreach (string script in scriptUrls) {
+ writer.WriteLine("<script type='text/javascript' src='{0}'></script>", script);
+ }
+ }
+
+ /// <summary>
+ /// Writes out script tags that import a script from resources embedded in this assembly.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="resourceName">Name of the resource.</param>
+ private static void WriteScriptTags(this TextWriter writer, Page page, string resourceName) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(resourceName));
+
+ WriteScriptTags(writer, page, new[] { resourceName });
+ }
+
+ /// <summary>
+ /// Writes out script tags that import scripts from resources embedded in this assembly.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="resourceNames">The resource names.</param>
+ private static void WriteScriptTags(this TextWriter writer, Page page, IEnumerable<string> resourceNames) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentNullException>(resourceNames != null);
+
+ writer.WriteScriptTags(resourceNames.Select(r => page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), r)));
+ }
+
+ /// <summary>
+ /// Writes a given script block, surrounding it with &lt;script&gt; and CDATA tags.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="script">The script to inline on the page.</param>
+ private static void WriteScriptBlock(this TextWriter writer, string script) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(script));
+
+ writer.WriteLine("<script type='text/javascript' language='javascript'><!--");
+ writer.WriteLine("//<![CDATA[");
+ writer.WriteLine(script);
+ writer.WriteLine("//]]>--></script>");
+ }
+
+ /// <summary>
+ /// Writes a given CSS link.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="page">The page being rendered.</param>
+ /// <param name="resourceName">Name of the resource containing the CSS content.</param>
+ private static void WriteStylesheetLink(this TextWriter writer, Page page, string resourceName) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentNullException>(page != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(resourceName));
+
+ WriteStylesheetLink(writer, page.ClientScript.GetWebResourceUrl(typeof(OpenIdRelyingPartyAjaxControlBase), resourceName));
+ }
+
+ /// <summary>
+ /// Writes a given CSS link.
+ /// </summary>
+ /// <param name="writer">The writer to emit the tags to.</param>
+ /// <param name="stylesheet">The stylesheet to link in.</param>
+ private static void WriteStylesheetLink(this TextWriter writer, string stylesheet) {
+ Contract.Requires<ArgumentNullException>(writer != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(stylesheet));
+
+ writer.WriteLine("<link rel='stylesheet' type='text/css' href='{0}' />", stylesheet);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index 036c19a..dc59b56 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
+ using System.Linq;
using System.Net;
using System.Net.Mime;
using System.Text;
@@ -88,7 +89,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="message">The message with data to encode.</param>
/// <returns>A dictionary of name-value pairs with their strings encoded.</returns>
- internal static IDictionary<string, string> GetUriEscapedParameters(MessageDictionary message) {
+ internal static IDictionary<string, string> GetUriEscapedParameters(IEnumerable<KeyValuePair<string, string>> message) {
var encodedDictionary = new Dictionary<string, string>();
UriEscapeParameters(message, encodedDictionary);
return encodedDictionary;
@@ -210,6 +211,8 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) {
httpRequest = this.InitializeRequestAsAuthHeader(request);
} else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) {
+ var requestMessageWithBinaryData = request as IMessageWithBinaryData;
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || !requestMessageWithBinaryData.SendAsMultipart, OAuthStrings.MultipartPostMustBeUsedWithAuthHeader);
httpRequest = this.InitializeRequestAsPost(request);
} else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) {
httpRequest = InitializeRequestAsGet(request);
@@ -282,7 +285,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="source">The dictionary with names and values to encode.</param>
/// <param name="destination">The dictionary to add the encoded pairs to.</param>
- private static void UriEscapeParameters(IDictionary<string, string> source, IDictionary<string, string> destination) {
+ private static void UriEscapeParameters(IEnumerable<KeyValuePair<string, string>> source, IDictionary<string, string> destination) {
Contract.Requires<ArgumentNullException>(source != null);
Contract.Requires<ArgumentNullException>(destination != null);
@@ -359,12 +362,22 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if (hasEntity) {
// WARNING: We only set up the request stream for the caller if there is
// extra data. If there isn't any extra data, the caller must do this themselves.
- if (requestMessage.ExtraData.Count > 0) {
- SendParametersInEntity(httpRequest, requestMessage.ExtraData);
+ var requestMessageWithBinaryData = requestMessage as IMessageWithBinaryData;
+ if (requestMessageWithBinaryData != null && requestMessageWithBinaryData.SendAsMultipart) {
+ // Include the binary data in the multipart entity, and any standard text extra message data.
+ // The standard declared message parts are included in the authorization header.
+ var multiPartFields = new List<MultipartPostPart>(requestMessageWithBinaryData.BinaryData);
+ multiPartFields.AddRange(requestMessage.ExtraData.Select(field => MultipartPostPart.CreateFormPart(field.Key, field.Value)));
+ this.SendParametersInEntityAsMultipart(httpRequest, multiPartFields);
} else {
- // We'll assume the content length is zero since the caller may not have
- // anything. They're responsible to change it when the add the payload if they have one.
- httpRequest.ContentLength = 0;
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || requestMessageWithBinaryData.BinaryData.Count == 0, MessagingStrings.BinaryDataRequiresMultipart);
+ if (requestMessage.ExtraData.Count > 0) {
+ this.SendParametersInEntity(httpRequest, requestMessage.ExtraData);
+ } else {
+ // We'll assume the content length is zero since the caller may not have
+ // anything. They're responsible to change it when the add the payload if they have one.
+ httpRequest.ContentLength = 0;
+ }
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
index 004e7d5..cf09036 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
@@ -10,6 +10,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.Collections.Specialized;
using System.Diagnostics.Contracts;
using System.Globalization;
+ using System.Linq;
using System.Text;
using System.Web;
using DotNetOpenAuth.Messaging;
@@ -157,7 +158,26 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
signatureBaseStringElements.Add(message.HttpMethod.ToUpperInvariant());
- var encodedDictionary = OAuthChannel.GetUriEscapedParameters(messageDictionary);
+ // For multipart POST messages, only include the message parts that are NOT
+ // in the POST entity (those parts that may appear in an OAuth authorization header).
+ var encodedDictionary = new Dictionary<string, string>();
+ IEnumerable<KeyValuePair<string, string>> partsToInclude = Enumerable.Empty<KeyValuePair<string, string>>();
+ var binaryMessage = message as IMessageWithBinaryData;
+ if (binaryMessage != null && binaryMessage.SendAsMultipart) {
+ HttpDeliveryMethods authHeaderInUseFlags = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
+ ErrorUtilities.VerifyProtocol((binaryMessage.HttpMethods & authHeaderInUseFlags) == authHeaderInUseFlags, OAuthStrings.MultipartPostMustBeUsedWithAuthHeader);
+
+ // Include the declared keys in the signature as those will be signable.
+ // Cache in local variable to avoid recalculating DeclaredKeys in the delegate.
+ ICollection<string> declaredKeys = messageDictionary.DeclaredKeys;
+ partsToInclude = messageDictionary.Where(pair => declaredKeys.Contains(pair.Key));
+ } else {
+ partsToInclude = messageDictionary;
+ }
+
+ foreach (var pair in OAuthChannel.GetUriEscapedParameters(partsToInclude)) {
+ encodedDictionary[pair.Key] = pair.Value;
+ }
// An incoming message will already have included the query and form parameters
// in the message dictionary, but an outgoing message COULD have SOME parameters
@@ -238,6 +258,8 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <c>true</c> if the signature on the message is valid; otherwise, <c>false</c>.
/// </returns>
protected virtual bool IsSignatureValid(ITamperResistantOAuthMessage message) {
+ Contract.Requires<ArgumentNullException>(message != null);
+
string signature = this.GetSignature(message);
return message.Signature == signature;
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBaseContract.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBaseContract.cs
index 7b369c3..4ff52fd 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBaseContract.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBaseContract.cs
@@ -15,8 +15,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
[ContractClassFor(typeof(SigningBindingElementBase))]
internal abstract class SigningBindingElementBaseContract : SigningBindingElementBase {
/// <summary>
- /// Prevents a default instance of the SigningBindingElementBaseContract
- /// class from being created.
+ /// Prevents a default instance of the SigningBindingElementBaseContract class from being created.
/// </summary>
private SigningBindingElementBaseContract()
: base(string.Empty) {
diff --git a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
index a189dcf..dddbe9e 100644
--- a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OAuth {
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
+ using System.Linq;
using System.Net;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -111,6 +112,27 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
+ /// Prepares an authorized request that carries an HTTP multi-part POST, allowing for binary data.
+ /// </summary>
+ /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
+ /// <param name="accessToken">The access token that permits access to the protected resource.</param>
+ /// <param name="binaryData">Extra parameters to include in the message. Must not be null, but may be empty.</param>
+ /// <returns>The initialized WebRequest object.</returns>
+ public HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint endpoint, string accessToken, IEnumerable<MultipartPostPart> binaryData) {
+ Contract.Requires<ArgumentNullException>(endpoint != null);
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(accessToken));
+ Contract.Requires<ArgumentNullException>(binaryData != null);
+
+ AccessProtectedResourceRequest message = this.CreateAuthorizingMessage(endpoint, accessToken);
+ foreach (MultipartPostPart part in binaryData) {
+ message.BinaryData.Add(part);
+ }
+
+ HttpWebRequest wr = this.OAuthChannel.InitializeRequest(message);
+ return wr;
+ }
+
+ /// <summary>
/// Prepares an HTTP request that has OAuth authorization already attached to it.
/// </summary>
/// <param name="message">The OAuth authorization message to attach to the HTTP request.</param>
diff --git a/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs b/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
index b60fda4..f3231f0 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OAuth.Messages {
using System;
+ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DotNetOpenAuth.Messaging;
@@ -13,7 +14,12 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// A message attached to a request for protected resources that provides the necessary
/// credentials to be granted access to those resources.
/// </summary>
- public class AccessProtectedResourceRequest : SignedMessageBase, ITokenContainingMessage {
+ public class AccessProtectedResourceRequest : SignedMessageBase, ITokenContainingMessage, IMessageWithBinaryData {
+ /// <summary>
+ /// A store for the binary data that is carried in the message.
+ /// </summary>
+ private List<MultipartPostPart> binaryData = new List<MultipartPostPart>();
+
/// <summary>
/// Initializes a new instance of the <see cref="AccessProtectedResourceRequest"/> class.
/// </summary>
@@ -43,5 +49,24 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// </remarks>
[MessagePart("oauth_token", IsRequired = true)]
public string AccessToken { get; set; }
+
+ #region IMessageWithBinaryData Members
+
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ public IList<MultipartPostPart> BinaryData {
+ get { return this.binaryData; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ public bool SendAsMultipart {
+ get { return this.HttpMethod == "POST" && this.BinaryData.Count > 0; }
+ }
+
+ #endregion
}
}
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
index 3593446..fb4c9a1 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:2.0.50727.4918
+// Runtime Version:4.0.30104.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.OAuth {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class OAuthStrings {
@@ -115,29 +115,38 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
- /// Looks up a localized string similar to Use of the OpenID+OAuth extension requires that the token manager in use implement the {0} interface..
+ /// Looks up a localized string similar to This OAuth service provider requires OAuth consumers to implement OAuth {0}, but this consumer appears to only support {1}..
/// </summary>
- internal static string OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface {
+ internal static string MinimumConsumerVersionRequirementNotMet {
get {
- return ResourceManager.GetString("OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface", resourceCulture);
+ return ResourceManager.GetString("MinimumConsumerVersionRequirementNotMet", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to The OpenID Relying Party&apos;s realm is not recognized as belonging to the OAuth Consumer identified by the consumer key given..
+ /// Looks up a localized string similar to Cannot send OAuth message as multipart POST without an authorization HTTP header because sensitive data would not be signed..
/// </summary>
- internal static string OpenIdOAuthRealmConsumerKeyDoNotMatch {
+ internal static string MultipartPostMustBeUsedWithAuthHeader {
get {
- return ResourceManager.GetString("OpenIdOAuthRealmConsumerKeyDoNotMatch", resourceCulture);
+ return ResourceManager.GetString("MultipartPostMustBeUsedWithAuthHeader", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to This OAuth service provider requires OAuth consumers to implement OAuth {0}, but this consumer appears to only support {1}..
+ /// Looks up a localized string similar to Use of the OpenID+OAuth extension requires that the token manager in use implement the {0} interface..
/// </summary>
- internal static string MinimumConsumerVersionRequirementNotMet {
+ internal static string OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface {
get {
- return ResourceManager.GetString("MinimumConsumerVersionRequirementNotMet", resourceCulture);
+ return ResourceManager.GetString("OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The OpenID Relying Party&apos;s realm is not recognized as belonging to the OAuth Consumer identified by the consumer key given..
+ /// </summary>
+ internal static string OpenIdOAuthRealmConsumerKeyDoNotMatch {
+ get {
+ return ResourceManager.GetString("OpenIdOAuthRealmConsumerKeyDoNotMatch", resourceCulture);
}
}
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.resx b/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
index bbeeda9..34b314b 100644
--- a/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
@@ -138,6 +138,9 @@
<data name="MinimumConsumerVersionRequirementNotMet" xml:space="preserve">
<value>This OAuth service provider requires OAuth consumers to implement OAuth {0}, but this consumer appears to only support {1}.</value>
</data>
+ <data name="MultipartPostMustBeUsedWithAuthHeader" xml:space="preserve">
+ <value>Cannot send OAuth message as multipart POST without an authorization HTTP header because sensitive data would not be signed.</value>
+ </data>
<data name="OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface" xml:space="preserve">
<value>Use of the OpenID+OAuth extension requires that the token manager in use implement the {0} interface.</value>
</data>
diff --git a/src/DotNetOpenAuth/OpenId/Association.cs b/src/DotNetOpenAuth/OpenId/Association.cs
index 62e91ec..3c7e89f 100644
--- a/src/DotNetOpenAuth/OpenId/Association.cs
+++ b/src/DotNetOpenAuth/OpenId/Association.cs
@@ -238,24 +238,28 @@ namespace DotNetOpenAuth.OpenId {
/// </returns>
public override int GetHashCode() {
HMACSHA1 hmac = new HMACSHA1(this.SecretKey);
- CryptoStream cs = new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
+ try {
+ CryptoStream cs = new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
- byte[] hbytes = ASCIIEncoding.ASCII.GetBytes(this.Handle);
+ byte[] hbytes = ASCIIEncoding.ASCII.GetBytes(this.Handle);
- cs.Write(hbytes, 0, hbytes.Length);
- cs.Close();
+ cs.Write(hbytes, 0, hbytes.Length);
+ cs.Close();
- byte[] hash = hmac.Hash;
- hmac.Clear();
+ byte[] hash = hmac.Hash;
+ hmac.Clear();
- long val = 0;
- for (int i = 0; i < hash.Length; i++) {
- val = val ^ (long)hash[i];
- }
+ long val = 0;
+ for (int i = 0; i < hash.Length; i++) {
+ val = val ^ (long)hash[i];
+ }
- val = val ^ this.Expires.ToFileTimeUtc();
+ val = val ^ this.Expires.ToFileTimeUtc();
- return (int)val;
+ return (int)val;
+ } finally {
+ ((IDisposable)hmac).Dispose();
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.Designer.cs
index 937ecaf..8c952ab 100644
--- a/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4918
+// Runtime Version:4.0.30104.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.OpenId.Behaviors {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class BehaviorStrings {
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
index 43d6c03..370192a 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
@@ -209,7 +209,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// or if unsolicited assertions should be rejected at the RP; otherwise <c>false</c>.
/// </returns>
private bool UseRequestNonce(IMessage message) {
- return message != null && (message.Version.Major < 2 || this.securitySettings.RejectUnsolicitedAssertions);
+ return message != null && (this.securitySettings.RejectUnsolicitedAssertions ||
+ (message.Version.Major < 2 && this.securitySettings.ProtectDownlevelReplayAttacks));
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
index d27619f..1b58c2f 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
@@ -51,7 +51,7 @@ namespace DotNetOpenAuth.OpenId.Extensions {
return;
}
- if (req.Provider.IsExtensionSupported<ClaimsRequest>()) {
+ if (req.DiscoveryResult.IsExtensionSupported<ClaimsRequest>()) {
Logger.OpenId.Debug("Skipping generation of AX request because the Identifier advertises the Provider supports the Sreg extension.");
return;
}
@@ -277,8 +277,7 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// <returns>The AX format(s) to use based on the Provider's advertised AX support.</returns>
private static bool TryDetectOPAttributeFormat(RelyingParty.IAuthenticationRequest request, out AXAttributeFormats attributeFormat) {
Contract.Requires<ArgumentNullException>(request != null);
- var provider = (RelyingParty.ServiceEndpoint)request.Provider;
- attributeFormat = DetectAXFormat(provider.ProviderDescription.Capabilities);
+ attributeFormat = DetectAXFormat(request.DiscoveryResult.Capabilities);
return attributeFormat != AXAttributeFormats.None;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
index ae483a6..55c2dc5 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
@@ -28,8 +28,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// <see cref="UIModes.Popup"/>. </para>
/// <para>An RP may determine whether an arbitrary OP supports this extension (and thereby determine
/// whether to use a standard full window redirect or a popup) via the
- /// <see cref="IProviderEndpoint.IsExtensionSupported"/> method on the <see cref="DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationRequest.Provider"/>
- /// object.</para>
+ /// <see cref="IdentifierDiscoveryResult.IsExtensionSupported&lt;T&gt;()"/> method.</para>
/// </remarks>
[Serializable]
public sealed class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
@@ -63,6 +62,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// </summary>
public UIRequest() {
this.LanguagePreference = new[] { CultureInfo.CurrentUICulture };
+ this.Mode = UIModes.Popup;
}
/// <summary>
@@ -77,12 +77,11 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
public CultureInfo[] LanguagePreference { get; set; }
/// <summary>
- /// Gets the style of UI that the RP is hosting the OP's authentication page in.
+ /// Gets or sets the style of UI that the RP is hosting the OP's authentication page in.
/// </summary>
/// <value>Some value from the <see cref="UIModes"/> class. Defaults to <see cref="UIModes.Popup"/>.</value>
- [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Design is to allow this later to be changable when more than one value exists.")]
[MessagePart("mode", AllowEmpty = false, IsRequired = true)]
- public string Mode { get { return UIModes.Popup; } }
+ public string Mode { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the Relying Party has an icon
diff --git a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
new file mode 100644
index 0000000..ba9852e
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
@@ -0,0 +1,515 @@
+//-----------------------------------------------------------------------
+// <copyright file="HostMetaDiscoveryService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Net;
+ using System.Security;
+ using System.Security.Cryptography;
+ using System.Security.Cryptography.X509Certificates;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Xml;
+ using System.Xml.XPath;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Xrds;
+ using DotNetOpenAuth.Yadis;
+
+ /// <summary>
+ /// The discovery service to support host-meta based discovery, such as Google Apps for Domains.
+ /// </summary>
+ /// <remarks>
+ /// The spec for this discovery mechanism can be found at:
+ /// http://groups.google.com/group/google-federated-login-api/web/openid-discovery-for-hosted-domains
+ /// and the XMLDSig spec referenced in that spec can be found at:
+ /// http://wiki.oasis-open.org/xri/XrdOne/XmlDsigProfile
+ /// </remarks>
+ public class HostMetaDiscoveryService : IIdentifierDiscoveryService {
+ /// <summary>
+ /// The URI template for discovery host-meta on domains hosted by
+ /// Google Apps for Domains.
+ /// </summary>
+ private static readonly HostMetaProxy GoogleHostedHostMeta = new HostMetaProxy("https://www.google.com/accounts/o8/.well-known/host-meta?hd={0}", "hosted-id.google.com");
+
+ /// <summary>
+ /// Path to the well-known location of the host-meta document at a domain.
+ /// </summary>
+ private const string LocalHostMetaPath = "/.well-known/host-meta";
+
+ /// <summary>
+ /// The pattern within a host-meta file to look for to obtain the URI to the XRDS document.
+ /// </summary>
+ private static readonly Regex HostMetaLink = new Regex(@"^Link: <(?<location>.+?)>; rel=""describedby http://reltype.google.com/openid/xrd-op""; type=""application/xrds\+xml""$");
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HostMetaDiscoveryService"/> class.
+ /// </summary>
+ public HostMetaDiscoveryService() {
+ this.TrustedHostMetaProxies = new List<HostMetaProxy>();
+ }
+
+ /// <summary>
+ /// Gets the set of URI templates to use to contact host-meta hosting proxies
+ /// for domain discovery.
+ /// </summary>
+ public IList<HostMetaProxy> TrustedHostMetaProxies { get; private set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to trust Google to host domains' host-meta documents.
+ /// </summary>
+ /// <remarks>
+ /// This property is just a convenient mechanism for checking or changing the set of
+ /// trusted host-meta proxies in the <see cref="TrustedHostMetaProxies"/> property.
+ /// </remarks>
+ public bool UseGoogleHostedHostMeta {
+ get {
+ return this.TrustedHostMetaProxies.Contains(GoogleHostedHostMeta);
+ }
+
+ set {
+ if (value != this.UseGoogleHostedHostMeta) {
+ if (value) {
+ this.TrustedHostMetaProxies.Add(GoogleHostedHostMeta);
+ } else {
+ this.TrustedHostMetaProxies.Remove(GoogleHostedHostMeta);
+ }
+ }
+ }
+ }
+
+ #region IIdentifierDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ public IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ abortDiscoveryChain = false;
+
+ // Google Apps are always URIs -- not XRIs.
+ var uriIdentifier = identifier as UriIdentifier;
+ if (uriIdentifier == null) {
+ return Enumerable.Empty<IdentifierDiscoveryResult>();
+ }
+
+ var results = new List<IdentifierDiscoveryResult>();
+ string signingHost;
+ using (var response = GetXrdsResponse(uriIdentifier, requestHandler, out signingHost)) {
+ if (response != null) {
+ try {
+ var document = new XrdsDocument(XmlReader.Create(response.ResponseStream));
+ ValidateXmlDSig(document, uriIdentifier, response, signingHost);
+ var xrds = GetXrdElements(document, uriIdentifier.Uri.Host);
+
+ // Look for claimed identifier template URIs for an additional XRDS document.
+ results.AddRange(GetExternalServices(xrds, uriIdentifier, requestHandler));
+
+ // If we couldn't find any claimed identifiers, look for OP identifiers.
+ // Normally this would be the opposite (OP Identifiers take precedence over
+ // claimed identifiers, but for Google Apps, XRDS' always have OP Identifiers
+ // mixed in, which the OpenID spec mandate should eclipse Claimed Identifiers,
+ // which would break positive assertion checks).
+ if (results.Count == 0) {
+ results.AddRange(xrds.CreateServiceEndpoints(uriIdentifier, uriIdentifier));
+ }
+
+ abortDiscoveryChain = true;
+ } catch (XmlException ex) {
+ Logger.Yadis.ErrorFormat("Error while parsing XRDS document at {0} pointed to by host-meta: {1}", response.FinalUri, ex);
+ }
+ }
+ }
+
+ return results;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets the XRD elements that have a given CanonicalID.
+ /// </summary>
+ /// <param name="document">The XRDS document.</param>
+ /// <param name="canonicalId">The CanonicalID to match on.</param>
+ /// <returns>A sequence of XRD elements.</returns>
+ private static IEnumerable<XrdElement> GetXrdElements(XrdsDocument document, string canonicalId) {
+ // filter to include only those XRD elements describing the host whose host-meta pointed us to this document.
+ return document.XrdElements.Where(xrd => string.Equals(xrd.CanonicalID, canonicalId, StringComparison.Ordinal));
+ }
+
+ /// <summary>
+ /// Gets the described-by services in XRD elements.
+ /// </summary>
+ /// <param name="xrds">The XRDs to search.</param>
+ /// <returns>A sequence of services.</returns>
+ private static IEnumerable<ServiceElement> GetDescribedByServices(IEnumerable<XrdElement> xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
+
+ var describedBy = from xrd in xrds
+ from service in xrd.SearchForServiceTypeUris(p => "http://www.iana.org/assignments/relation/describedby")
+ select service;
+ return describedBy;
+ }
+
+ /// <summary>
+ /// Gets the services for an identifier that are described by an external XRDS document.
+ /// </summary>
+ /// <param name="xrds">The XRD elements to search for described-by services.</param>
+ /// <param name="identifier">The identifier under discovery.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <returns>The discovered services.</returns>
+ private static IEnumerable<IdentifierDiscoveryResult> GetExternalServices(IEnumerable<XrdElement> xrds, UriIdentifier identifier, IDirectWebRequestHandler requestHandler) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+
+ var results = new List<IdentifierDiscoveryResult>();
+ foreach (var serviceElement in GetDescribedByServices(xrds)) {
+ var templateNode = serviceElement.Node.SelectSingleNode("google:URITemplate", serviceElement.XmlNamespaceResolver);
+ var nextAuthorityNode = serviceElement.Node.SelectSingleNode("google:NextAuthority", serviceElement.XmlNamespaceResolver);
+ if (templateNode != null) {
+ Uri externalLocation = new Uri(templateNode.Value.Trim().Replace("{%uri}", Uri.EscapeDataString(identifier.Uri.AbsoluteUri)));
+ string nextAuthority = nextAuthorityNode != null ? nextAuthorityNode.Value.Trim() : identifier.Uri.Host;
+ try {
+ using (var externalXrdsResponse = GetXrdsResponse(identifier, requestHandler, externalLocation)) {
+ XrdsDocument externalXrds = new XrdsDocument(XmlReader.Create(externalXrdsResponse.ResponseStream));
+ ValidateXmlDSig(externalXrds, identifier, externalXrdsResponse, nextAuthority);
+ results.AddRange(GetXrdElements(externalXrds, identifier).CreateServiceEndpoints(identifier, identifier));
+ }
+ } catch (ProtocolException ex) {
+ Logger.Yadis.WarnFormat("HTTP GET error while retrieving described-by XRDS document {0}: {1}", externalLocation.AbsoluteUri, ex);
+ } catch (XmlException ex) {
+ Logger.Yadis.ErrorFormat("Error while parsing described-by XRDS document {0}: {1}", externalLocation.AbsoluteUri, ex);
+ }
+ }
+ }
+
+ return results;
+ }
+
+ /// <summary>
+ /// Validates the XML digital signature on an XRDS document.
+ /// </summary>
+ /// <param name="document">The XRDS document whose signature should be validated.</param>
+ /// <param name="identifier">The identifier under discovery.</param>
+ /// <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>
+ private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) {
+ Contract.Requires<ArgumentNullException>(document != null);
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(response != null);
+
+ var signatureNode = document.Node.SelectSingleNode("/xrds:XRDS/ds:Signature", document.XmlNamespaceResolver);
+ ErrorUtilities.VerifyProtocol(signatureNode != null, OpenIdStrings.MissingElement, "Signature");
+ var signedInfoNode = signatureNode.SelectSingleNode("ds:SignedInfo", document.XmlNamespaceResolver);
+ 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.");
+ ErrorUtilities.VerifyProtocol(
+ signedInfoNode.SelectSingleNode("ds:SignatureMethod[@Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1']", document.XmlNamespaceResolver) != null,
+ "Unrecognized or missing signature method.");
+ 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();
+
+ // Verify that we trust the signer of the certificates.
+ // Start by trying to validate just the certificate used to sign the XRDS document,
+ // since we can do that with partial trust.
+ Logger.OpenId.Debug("Verifying that we trust the certificate used to sign the discovery document.");
+ if (!certs[0].Verify()) {
+ // We couldn't verify just the signing certificate, so try to verify the whole certificate chain.
+ try {
+ Logger.OpenId.Debug("Verifying the whole certificate chain.");
+ VerifyCertChain(certs);
+ Logger.OpenId.Debug("Certificate chain verified.");
+ } catch (SecurityException) {
+ Logger.Yadis.Warn("Signing certificate verification failed and we have insufficient code access security permissions to perform certificate chain validation.");
+ ErrorUtilities.ThrowProtocol(OpenIdStrings.X509CertificateNotTrusted);
+ }
+ }
+
+ // 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);
+
+ // Verify the signature itself
+ byte[] signature = Convert.FromBase64String(response.Headers["Signature"]);
+ var provider = (RSACryptoServiceProvider)certs.First().PublicKey.Key;
+ 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.");
+ }
+
+ /// <summary>
+ /// Verifies the cert chain.
+ /// </summary>
+ /// <param name="certs">The certs.</param>
+ /// <remarks>
+ /// This must be in a method of its own because there is a LinkDemand on the <see cref="X509Chain.Build"/>
+ /// method. By being in a method of its own, the caller of this method may catch a
+ /// <see cref="SecurityException"/> that is thrown if we're not running with full trust and execute
+ /// 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")]
+ private static void VerifyCertChain(List<X509Certificate2> certs) {
+ var chain = new X509Chain();
+ foreach (var cert in certs) {
+ chain.Build(cert);
+ }
+
+ if (chain.ChainStatus.Length > 0) {
+ ErrorUtilities.ThrowProtocol(
+ string.Format(
+ CultureInfo.CurrentCulture,
+ OpenIdStrings.X509CertificateNotTrusted + " {0}",
+ string.Join(", ", chain.ChainStatus.Select(status => status.StatusInformation).ToArray())));
+ }
+ }
+
+ /// <summary>
+ /// Gets the XRDS HTTP response for a given identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="xrdsLocation">The location of the XRDS document to retrieve.</param>
+ /// <returns>
+ /// A HTTP response carrying an XRDS document.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown if the XRDS document could not be obtained.</exception>
+ private static IncomingWebResponse GetXrdsResponse(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, Uri xrdsLocation) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Requires<ArgumentNullException>(xrdsLocation != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>() != null);
+
+ var request = (HttpWebRequest)WebRequest.Create(xrdsLocation);
+ request.CachePolicy = Yadis.IdentifierDiscoveryCachePolicy;
+ request.Accept = ContentTypes.Xrds;
+ var options = identifier.IsDiscoverySecureEndToEnd ? DirectWebRequestOptions.RequireSsl : DirectWebRequestOptions.None;
+ var response = requestHandler.GetResponse(request, options).GetSnapshot(Yadis.MaximumResultToScan);
+ if (!string.Equals(response.ContentType.MediaType, ContentTypes.Xrds, StringComparison.Ordinal)) {
+ Logger.Yadis.WarnFormat("Host-meta pointed to XRDS at {0}, but Content-Type at that URL was unexpected value '{1}'.", xrdsLocation, response.ContentType);
+ }
+
+ return response;
+ }
+
+ /// <summary>
+ /// Gets the XRDS HTTP response for a given identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
+ /// <returns>A HTTP response carrying an XRDS document, or <c>null</c> if one could not be obtained.</returns>
+ /// <exception cref="ProtocolException">Thrown if the XRDS document could not be obtained.</exception>
+ private IncomingWebResponse GetXrdsResponse(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Uri xrdsLocation = this.GetXrdsLocation(identifier, requestHandler, out signingHost);
+ if (xrdsLocation == null) {
+ return null;
+ }
+
+ var response = GetXrdsResponse(identifier, requestHandler, xrdsLocation);
+
+ return response;
+ }
+
+ /// <summary>
+ /// Gets the location of the XRDS document that describes a given identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier under discovery.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
+ /// <returns>An absolute URI, or <c>null</c> if one could not be determined.</returns>
+ private Uri GetXrdsLocation(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ using (var hostMetaResponse = this.GetHostMeta(identifier, requestHandler, out signingHost)) {
+ if (hostMetaResponse == null) {
+ return null;
+ }
+
+ using (var sr = hostMetaResponse.GetResponseReader()) {
+ string line = sr.ReadLine();
+ Match m = HostMetaLink.Match(line);
+ if (m.Success) {
+ Uri location = new Uri(m.Groups["location"].Value);
+ Logger.Yadis.InfoFormat("Found link to XRDS at {0} in host-meta document {1}.", location, hostMetaResponse.FinalUri);
+ return location;
+ }
+ }
+
+ Logger.Yadis.WarnFormat("Could not find link to XRDS in host-meta document: {0}", hostMetaResponse.FinalUri);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the host-meta for a given identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
+ /// <returns>
+ /// The host-meta response, or <c>null</c> if no host-meta document could be obtained.
+ /// </returns>
+ private IncomingWebResponse GetHostMeta(UriIdentifier identifier, IDirectWebRequestHandler requestHandler, out string signingHost) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ foreach (var hostMetaProxy in this.GetHostMetaLocations(identifier)) {
+ var hostMetaLocation = hostMetaProxy.GetProxy(identifier);
+ var request = (HttpWebRequest)WebRequest.Create(hostMetaLocation);
+ request.CachePolicy = Yadis.IdentifierDiscoveryCachePolicy;
+ var options = DirectWebRequestOptions.AcceptAllHttpResponses;
+ if (identifier.IsDiscoverySecureEndToEnd) {
+ options |= DirectWebRequestOptions.RequireSsl;
+ }
+ var response = requestHandler.GetResponse(request, options).GetSnapshot(Yadis.MaximumResultToScan);
+ try {
+ if (response.Status == HttpStatusCode.OK) {
+ Logger.Yadis.InfoFormat("Found host-meta for {0} at: {1}", identifier.Uri.Host, hostMetaLocation);
+ signingHost = hostMetaProxy.GetSigningHost(identifier);
+ return response;
+ } else {
+ Logger.Yadis.InfoFormat("Could not obtain host-meta for {0} from {1}", identifier.Uri.Host, hostMetaLocation);
+ response.Dispose();
+ }
+ } catch {
+ response.Dispose();
+ throw;
+ }
+ }
+
+ signingHost = null;
+ return null;
+ }
+
+ /// <summary>
+ /// Gets the URIs authorized to host host-meta documents on behalf of a given domain.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <returns>A sequence of URIs that MAY provide the host-meta for a given identifier.</returns>
+ private IEnumerable<HostMetaProxy> GetHostMetaLocations(UriIdentifier identifier) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+
+ // First try the proxies, as they are considered more "secure" than the local
+ // host-meta for a domain since the domain may be defaced.
+ IEnumerable<HostMetaProxy> result = this.TrustedHostMetaProxies;
+
+ // Finally, look for the local host-meta.
+ UriBuilder localHostMetaBuilder = new UriBuilder();
+ localHostMetaBuilder.Scheme = identifier.IsDiscoverySecureEndToEnd || identifier.Uri.IsTransportSecure() ? Uri.UriSchemeHttps : Uri.UriSchemeHttp;
+ localHostMetaBuilder.Host = identifier.Uri.Host;
+ localHostMetaBuilder.Path = LocalHostMetaPath;
+ result = result.Concat(new[] { new HostMetaProxy(localHostMetaBuilder.Uri.AbsoluteUri, identifier.Uri.Host) });
+
+ return result;
+ }
+
+ /// <summary>
+ /// A description of a web server that hosts host-meta documents.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "By design")]
+ public class HostMetaProxy {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HostMetaProxy"/> class.
+ /// </summary>
+ /// <param name="proxyFormat">The proxy formatting string.</param>
+ /// <param name="signingHostFormat">The signing host formatting string.</param>
+ public HostMetaProxy(string proxyFormat, string signingHostFormat) {
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(proxyFormat));
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(signingHostFormat));
+ this.ProxyFormat = proxyFormat;
+ this.SigningHostFormat = signingHostFormat;
+ }
+
+ /// <summary>
+ /// Gets the URL of the host-meta proxy.
+ /// </summary>
+ /// <value>The absolute proxy URL, which may include {0} to be replaced with the host of the identifier to be discovered.</value>
+ public string ProxyFormat { get; private set; }
+
+ /// <summary>
+ /// Gets the formatting string to determine the expected host name on the certificate
+ /// that is expected to be used to sign the XRDS document.
+ /// </summary>
+ /// <value>
+ /// Either a string literal, or a formatting string where these placeholders may exist:
+ /// {0} the host on the identifier discovery was originally performed on;
+ /// {1} the host on this proxy.
+ /// </value>
+ public string SigningHostFormat { get; private set; }
+
+ /// <summary>
+ /// Gets the absolute proxy URI.
+ /// </summary>
+ /// <param name="identifier">The identifier being discovered.</param>
+ /// <returns>The an absolute URI.</returns>
+ public virtual Uri GetProxy(UriIdentifier identifier) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ return new Uri(string.Format(CultureInfo.InvariantCulture, this.ProxyFormat, Uri.EscapeDataString(identifier.Uri.Host)));
+ }
+
+ /// <summary>
+ /// Gets the signing host URI.
+ /// </summary>
+ /// <param name="identifier">The identifier being discovered.</param>
+ /// <returns>A host name.</returns>
+ public virtual string GetSigningHost(UriIdentifier identifier) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ return string.Format(CultureInfo.InvariantCulture, this.SigningHostFormat, identifier.Uri.Host, this.GetProxy(identifier).Host);
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <paramref name="obj"/> parameter is null.
+ /// </exception>
+ public override bool Equals(object obj) {
+ var other = obj as HostMetaProxy;
+ if (other == null) {
+ return false;
+ }
+
+ return this.ProxyFormat == other.ProxyFormat && this.SigningHostFormat == other.SigningHostFormat;
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ return this.ProxyFormat.GetHashCode();
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs
new file mode 100644
index 0000000..eb2bf98
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs
@@ -0,0 +1,61 @@
+//-----------------------------------------------------------------------
+// <copyright file="IIdentifierDiscoveryService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ /// <summary>
+ /// A module that provides discovery services for OpenID identifiers.
+ /// </summary>
+ [ContractClass(typeof(IIdentifierDiscoveryServiceContract))]
+ public interface IIdentifierDiscoveryService {
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "By design")]
+ [Pure]
+ IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain);
+ }
+
+ /// <summary>
+ /// Code contract for the <see cref="IIdentifierDiscoveryService"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IIdentifierDiscoveryService))]
+ internal class IIdentifierDiscoveryServiceContract : IIdentifierDiscoveryService {
+ #region IDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ IEnumerable<IdentifierDiscoveryResult> IIdentifierDiscoveryService.Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs
index 831dfa9..36ec784 100644
--- a/src/DotNetOpenAuth/OpenId/Identifier.cs
+++ b/src/DotNetOpenAuth/OpenId/Identifier.cs
@@ -39,6 +39,18 @@ namespace DotNetOpenAuth.OpenId {
public string OriginalString { get; private set; }
/// <summary>
+ /// Gets the Identifier in the form in which it should be serialized.
+ /// </summary>
+ /// <value>
+ /// For Identifiers that were originally deserialized, this is the exact same
+ /// string that was deserialized. For Identifiers instantiated in some other way, this is
+ /// the normalized form of the string used to instantiate the identifier.
+ /// </value>
+ internal virtual string SerializedString {
+ get { return this.IsDeserializedInstance ? this.OriginalString : this.ToString(); }
+ }
+
+ /// <summary>
/// Gets or sets a value indicating whether <see cref="Identifier"/> instances are considered equal
/// based solely on their string reprsentations.
/// </summary>
@@ -59,6 +71,18 @@ namespace DotNetOpenAuth.OpenId {
protected internal bool IsDiscoverySecureEndToEnd { get; private set; }
/// <summary>
+ /// Gets a value indicating whether this instance was initialized from
+ /// deserializing a message.
+ /// </summary>
+ /// <remarks>
+ /// This is interesting because when an Identifier comes from the network,
+ /// we can't normalize it and then expect signatures to still verify.
+ /// But if the Identifier is initialized locally, we can and should normalize it
+ /// before serializing it.
+ /// </remarks>
+ protected bool IsDeserializedInstance { get; private set; }
+
+ /// <summary>
/// Converts the string representation of an Identifier to its strong type.
/// </summary>
/// <param name="identifier">The identifier.</param>
@@ -118,11 +142,32 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(identifier));
Contract.Ensures(Contract.Result<Identifier>() != null);
+ return Parse(identifier, false);
+ }
+
+ /// <summary>
+ /// Parses an identifier string and automatically determines
+ /// whether it is an XRI or URI.
+ /// </summary>
+ /// <param name="identifier">Either a URI or XRI identifier.</param>
+ /// <param name="serializeExactValue">if set to <c>true</c> this Identifier will serialize exactly as given rather than in its normalized form.</param>
+ /// <returns>
+ /// An <see cref="Identifier"/> instance for the given value.
+ /// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Some of these identifiers are not properly formatted to be Uris at this stage.")]
+ public static Identifier Parse(string identifier, bool serializeExactValue) {
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(identifier));
+ Contract.Ensures(Contract.Result<Identifier>() != null);
+
+ Identifier id;
if (XriIdentifier.IsValidXri(identifier)) {
- return new XriIdentifier(identifier);
+ id = new XriIdentifier(identifier);
} else {
- return new UriIdentifier(identifier);
+ id = new UriIdentifier(identifier);
}
+
+ id.IsDeserializedInstance = serializeExactValue;
+ return id;
}
/// <summary>
@@ -212,14 +257,17 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Performs discovery on the Identifier.
+ /// Reparses the specified identifier in order to be assured that the concrete type that
+ /// implements the identifier is one of the well-known ones.
/// </summary>
- /// <param name="requestHandler">The web request handler to use for discovery.</param>
- /// <returns>
- /// An initialized structure containing the discovered provider endpoint information.
- /// </returns>
- [Pure]
- internal abstract IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler);
+ /// <param name="identifier">The identifier.</param>
+ /// <returns>Either <see cref="XriIdentifier"/> or <see cref="UriIdentifier"/>.</returns>
+ internal static Identifier Reparse(Identifier identifier) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Ensures(Contract.Result<Identifier>() != null);
+
+ return Parse(identifier, identifier.IsDeserializedInstance);
+ }
/// <summary>
/// Returns an <see cref="Identifier"/> that has no URI fragment.
diff --git a/src/DotNetOpenAuth/OpenId/IdentifierContract.cs b/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
index 498ae45..4af18e1 100644
--- a/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
+++ b/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
@@ -24,19 +24,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Performs discovery on the Identifier.
- /// </summary>
- /// <param name="requestHandler">The web request handler to use for discovery.</param>
- /// <returns>
- /// An initialized structure containing the discovered provider endpoint information.
- /// </returns>
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- Contract.Requires<ArgumentNullException>(requestHandler != null);
- Contract.Ensures(Contract.Result<IEnumerable<ServiceEndpoint>>() != null);
- throw new NotImplementedException();
- }
-
- /// <summary>
/// Returns an <see cref="Identifier"/> that has no URI fragment.
/// Quietly returns the original <see cref="Identifier"/> if it is not
/// a <see cref="UriIdentifier"/> or no fragment exists.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs b/src/DotNetOpenAuth/OpenId/IdentifierDiscoveryResult.cs
index f8744d0..c851f24 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/IdentifierDiscoveryResult.cs
@@ -1,13 +1,15 @@
//-----------------------------------------------------------------------
-// <copyright file="ServiceEndpoint.cs" company="Andrew Arnott">
+// <copyright file="IdentifierDiscoveryResult.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.OpenId.RelyingParty {
+namespace DotNetOpenAuth.OpenId {
using System;
+ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -15,17 +17,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
+ using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
/// Represents a single OP endpoint from discovery on some OpenID Identifier.
/// </summary>
[DebuggerDisplay("ClaimedIdentifier: {ClaimedIdentifier}, ProviderEndpoint: {ProviderEndpoint}, OpenId: {Protocol.Version}")]
- internal class ServiceEndpoint : IXrdsProviderEndpoint {
+ public sealed class IdentifierDiscoveryResult : IProviderEndpoint {
/// <summary>
- /// The i-name identifier the user actually typed in
- /// or the url identifier with the scheme stripped off.
+ /// Backing field for the <see cref="Protocol"/> property.
/// </summary>
- private string friendlyIdentifierForDisplay;
+ private Protocol protocol;
/// <summary>
/// Backing field for the <see cref="ClaimedIdentifier"/> property.
@@ -33,23 +35,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private Identifier claimedIdentifier;
/// <summary>
- /// The OpenID protocol version used at the identity Provider.
- /// </summary>
- private Protocol protocol;
-
- /// <summary>
- /// The @priority given in the XRDS document for this specific OP endpoint.
- /// </summary>
- private int? uriPriority;
-
- /// <summary>
- /// The @priority given in the XRDS document for this service
- /// (which may consist of several endpoints).
+ /// Backing field for the <see cref="FriendlyIdentifierForDisplay"/> property.
/// </summary>
- private int? servicePriority;
+ private string friendlyIdentifierForDisplay;
/// <summary>
- /// Initializes a new instance of the <see cref="ServiceEndpoint"/> class.
+ /// Initializes a new instance of the <see cref="IdentifierDiscoveryResult"/> class.
/// </summary>
/// <param name="providerEndpoint">The provider endpoint.</param>
/// <param name="claimedIdentifier">The Claimed Identifier.</param>
@@ -57,47 +48,23 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="providerLocalIdentifier">The Provider Local Identifier.</param>
/// <param name="servicePriority">The service priority.</param>
/// <param name="uriPriority">The URI priority.</param>
- private ServiceEndpoint(ProviderEndpointDescription providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, int? servicePriority, int? uriPriority) {
- Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
- Contract.Requires<ArgumentNullException>(providerEndpoint != null);
- this.ProviderDescription = providerEndpoint;
- this.ClaimedIdentifier = claimedIdentifier;
- this.UserSuppliedIdentifier = userSuppliedIdentifier;
- this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier;
- this.servicePriority = servicePriority;
- this.uriPriority = uriPriority;
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ServiceEndpoint"/> class.
- /// </summary>
- /// <param name="providerEndpoint">The provider endpoint.</param>
- /// <param name="claimedIdentifier">The Claimed Identifier.</param>
- /// <param name="userSuppliedIdentifier">The User-supplied Identifier.</param>
- /// <param name="providerLocalIdentifier">The Provider Local Identifier.</param>
- /// <param name="protocol">The protocol.</param>
- /// <remarks>
- /// Used for deserializing <see cref="ServiceEndpoint"/> from authentication responses.
- /// </remarks>
- private ServiceEndpoint(Uri providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, Protocol protocol) {
+ private IdentifierDiscoveryResult(ProviderEndpointDescription providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, int? servicePriority, int? uriPriority) {
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
- Contract.Requires<ArgumentNullException>(providerLocalIdentifier != null);
- Contract.Requires<ArgumentNullException>(protocol != null);
-
+ this.ProviderEndpoint = providerEndpoint.Uri;
+ this.Capabilities = new ReadOnlyCollection<string>(providerEndpoint.Capabilities);
+ this.Version = providerEndpoint.Version;
this.ClaimedIdentifier = claimedIdentifier;
- this.UserSuppliedIdentifier = userSuppliedIdentifier;
- this.ProviderDescription = new ProviderEndpointDescription(providerEndpoint, protocol.Version);
this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier;
- this.protocol = protocol;
+ this.UserSuppliedIdentifier = userSuppliedIdentifier;
+ this.ServicePriority = servicePriority;
+ this.ProviderEndpointPriority = uriPriority;
}
/// <summary>
- /// Gets the URL that the OpenID Provider receives authentication requests at.
+ /// Gets the detected version of OpenID implemented by the Provider.
/// </summary>
- Uri IProviderEndpoint.Uri {
- get { return this.ProviderDescription.Endpoint; }
- }
+ public Version Version { get; private set; }
/// <summary>
/// Gets the Identifier that was presented by the end user to the Relying Party,
@@ -110,19 +77,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public Identifier UserSuppliedIdentifier { get; private set; }
/// <summary>
- /// Gets or sets the Identifier that the end user claims to own.
+ /// Gets the Identifier that the end user claims to control.
/// </summary>
public Identifier ClaimedIdentifier {
get {
return this.claimedIdentifier;
}
- set {
+ internal set {
// Take care to reparse the incoming identifier to make sure it's
// not a derived type that will override expected behavior.
// Elsewhere in this class, we count on the fact that this property
// is either UriIdentifier or XriIdentifier. MockIdentifier messes it up.
- this.claimedIdentifier = value != null ? Identifier.Parse(value) : null;
+ this.claimedIdentifier = value != null ? Identifier.Reparse(value) : null;
}
}
@@ -134,8 +101,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public Identifier ProviderLocalIdentifier { get; private set; }
/// <summary>
- /// Gets the value for the <see cref="IAuthenticationResponse.FriendlyIdentifierForDisplay"/> property.
+ /// Gets a more user-friendly (but NON-secure!) string to display to the user as his identifier.
/// </summary>
+ /// <returns>A human-readable, abbreviated (but not secure) identifier the user MAY recognize as his own.</returns>
public string FriendlyIdentifierForDisplay {
get {
if (this.friendlyIdentifierForDisplay == null) {
@@ -149,8 +117,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
} else if (uri != null) {
if (uri != this.Protocol.ClaimedIdentifierForOPIdentifier) {
- string displayUri = uri.Uri.Host + uri.Uri.AbsolutePath;
- displayUri = displayUri.TrimEnd('/');
+ string displayUri = uri.Uri.Host;
+
+ // We typically want to display the path, because that will often have the username in it.
+ // As Google Apps for Domains and the like become more popular, a standard /openid path
+ // will often appear, which is not helpful to identifying the user so we'll avoid including
+ // that path if it's present.
+ if (!string.Equals(uri.Uri.AbsolutePath, "/openid", StringComparison.OrdinalIgnoreCase)) {
+ displayUri += uri.Uri.AbsolutePath.TrimEnd('/');
+ }
// Multi-byte unicode characters get encoded by the Uri class for transit.
// Since this is for display purposes, we want to reverse this and display a readable
@@ -162,57 +137,45 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.friendlyIdentifierForDisplay = this.ClaimedIdentifier;
}
}
+
return this.friendlyIdentifierForDisplay;
}
}
/// <summary>
- /// Gets the list of services available at this OP Endpoint for the
- /// claimed Identifier. May be null.
+ /// Gets the provider endpoint.
/// </summary>
- public ReadOnlyCollection<string> ProviderSupportedServiceTypeUris {
- get { return this.ProviderDescription.Capabilities; }
- }
+ public Uri ProviderEndpoint { get; private set; }
/// <summary>
- /// Gets the OpenID protocol used by the Provider.
+ /// Gets the @priority given in the XRDS document for this specific OP endpoint.
/// </summary>
- public Protocol Protocol {
- get {
- if (this.protocol == null) {
- this.protocol = Protocol.Lookup(this.ProviderDescription.ProtocolVersion);
- }
-
- return this.protocol;
- }
- }
-
- #region IXrdsProviderEndpoint Members
+ public int? ProviderEndpointPriority { get; private set; }
/// <summary>
- /// Gets the priority associated with this service that may have been given
- /// in the XRDS document.
+ /// Gets the @priority given in the XRDS document for this service
+ /// (which may consist of several endpoints).
/// </summary>
- int? IXrdsProviderEndpoint.ServicePriority {
- get { return this.servicePriority; }
- }
+ public int? ServicePriority { get; private set; }
/// <summary>
- /// Gets the priority associated with the service endpoint URL.
+ /// Gets the collection of service type URIs found in the XRDS document describing this Provider.
/// </summary>
- int? IXrdsProviderEndpoint.UriPriority {
- get { return this.uriPriority; }
- }
+ /// <value>Should never be null, but may be empty.</value>
+ public ReadOnlyCollection<string> Capabilities { get; private set; }
- #endregion
+ #region IProviderEndpoint Members
/// <summary>
- /// Gets the detected version of OpenID implemented by the Provider.
+ /// Gets the URL that the OpenID Provider receives authentication requests at.
/// </summary>
- Version IProviderEndpoint.Version {
- get { return this.ProviderDescription.ProtocolVersion; }
+ /// <value>This value MUST be an absolute HTTP or HTTPS URL.</value>
+ Uri IProviderEndpoint.Uri {
+ get { return this.ProviderEndpoint; }
}
+ #endregion
+
/// <summary>
/// Gets an XRDS sorting routine that uses the XRDS Service/@Priority
/// attribute to determine order.
@@ -220,7 +183,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <remarks>
/// Endpoints lacking any priority value are sorted to the end of the list.
/// </remarks>
- internal static Comparison<IXrdsProviderEndpoint> EndpointOrder {
+ internal static Comparison<IdentifierDiscoveryResult> EndpointOrder {
get {
// Sort first by service type (OpenID 2.0, 1.1, 1.0),
// then by Service/@priority, then by Service/Uri/@priority
@@ -234,11 +197,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
if (result != 0) {
return result;
}
- if (se1.UriPriority.HasValue && se2.UriPriority.HasValue) {
- return se1.UriPriority.Value.CompareTo(se2.UriPriority.Value);
- } else if (se1.UriPriority.HasValue) {
+ if (se1.ProviderEndpointPriority.HasValue && se2.ProviderEndpointPriority.HasValue) {
+ return se1.ProviderEndpointPriority.Value.CompareTo(se2.ProviderEndpointPriority.Value);
+ } else if (se1.ProviderEndpointPriority.HasValue) {
return -1;
- } else if (se2.UriPriority.HasValue) {
+ } else if (se2.ProviderEndpointPriority.HasValue) {
return 1;
} else {
return 0;
@@ -250,11 +213,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return 1;
} else {
// neither service defines a priority, so base ordering by uri priority.
- if (se1.UriPriority.HasValue && se2.UriPriority.HasValue) {
- return se1.UriPriority.Value.CompareTo(se2.UriPriority.Value);
- } else if (se1.UriPriority.HasValue) {
+ if (se1.ProviderEndpointPriority.HasValue && se2.ProviderEndpointPriority.HasValue) {
+ return se1.ProviderEndpointPriority.Value.CompareTo(se2.ProviderEndpointPriority.Value);
+ } else if (se1.ProviderEndpointPriority.HasValue) {
return -1;
- } else if (se2.UriPriority.HasValue) {
+ } else if (se2.ProviderEndpointPriority.HasValue) {
return 1;
} else {
return 0;
@@ -266,35 +229,25 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Gets the URL which accepts OpenID Authentication protocol messages.
+ /// Gets the protocol used by the OpenID Provider.
/// </summary>
- /// <remarks>
- /// Obtained by performing discovery on the User-Supplied Identifier.
- /// This value MUST be an absolute HTTP or HTTPS URL.
- /// </remarks>
- internal Uri ProviderEndpoint {
- get { return this.ProviderDescription.Endpoint; }
- }
+ internal Protocol Protocol {
+ get {
+ if (this.protocol == null) {
+ this.protocol = Protocol.Lookup(this.Version);
+ }
- /// <summary>
- /// Gets a value indicating whether the <see cref="ProviderEndpoint"/> is using an encrypted channel.
- /// </summary>
- internal bool IsSecure {
- get { return string.Equals(this.ProviderEndpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase); }
+ return this.protocol;
+ }
}
/// <summary>
- /// Gets the provider description.
- /// </summary>
- internal ProviderEndpointDescription ProviderDescription { get; private set; }
-
- /// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="se1">The first service endpoint.</param>
/// <param name="se2">The second service endpoint.</param>
/// <returns>The result of the operator.</returns>
- public static bool operator ==(ServiceEndpoint se1, ServiceEndpoint se2) {
+ public static bool operator ==(IdentifierDiscoveryResult se1, IdentifierDiscoveryResult se2) {
return se1.EqualsNullSafe(se2);
}
@@ -304,44 +257,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="se1">The first service endpoint.</param>
/// <param name="se2">The second service endpoint.</param>
/// <returns>The result of the operator.</returns>
- public static bool operator !=(ServiceEndpoint se1, ServiceEndpoint se2) {
+ public static bool operator !=(IdentifierDiscoveryResult se1, IdentifierDiscoveryResult se2) {
return !(se1 == se2);
}
/// <summary>
- /// Checks for the presence of a given Type URI in an XRDS service.
- /// </summary>
- /// <param name="typeUri">The type URI to check for.</param>
- /// <returns>
- /// <c>true</c> if the service type uri is present; <c>false</c> otherwise.
- /// </returns>
- public bool IsTypeUriPresent(string typeUri) {
- return this.ProviderDescription.IsExtensionSupported(typeUri);
- }
-
- /// <summary>
- /// Determines whether a given extension is supported by this endpoint.
- /// </summary>
- /// <typeparam name="T">The type of extension to check support for on this endpoint.</typeparam>
- /// <returns>
- /// <c>true</c> if the extension is supported by this endpoint; otherwise, <c>false</c>.
- /// </returns>
- public bool IsExtensionSupported<T>() where T : IOpenIdMessageExtension, new() {
- return this.ProviderDescription.IsExtensionSupported<T>();
- }
-
- /// <summary>
- /// Determines whether a given extension is supported by this endpoint.
- /// </summary>
- /// <param name="extensionType">The type of extension to check support for on this endpoint.</param>
- /// <returns>
- /// <c>true</c> if the extension is supported by this endpoint; otherwise, <c>false</c>.
- /// </returns>
- public bool IsExtensionSupported(Type extensionType) {
- return this.ProviderDescription.IsExtensionSupported(extensionType);
- }
-
- /// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
@@ -352,7 +272,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The <paramref name="obj"/> parameter is null.
/// </exception>
public override bool Equals(object obj) {
- ServiceEndpoint other = obj as ServiceEndpoint;
+ var other = obj as IdentifierDiscoveryResult;
if (other == null) {
return false;
}
@@ -388,57 +308,95 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
StringBuilder builder = new StringBuilder();
builder.AppendLine("ClaimedIdentifier: " + this.ClaimedIdentifier);
builder.AppendLine("ProviderLocalIdentifier: " + this.ProviderLocalIdentifier);
- builder.AppendLine("ProviderEndpoint: " + this.ProviderEndpoint.AbsoluteUri);
- builder.AppendLine("OpenID version: " + this.Protocol.Version);
+ builder.AppendLine("ProviderEndpoint: " + this.ProviderEndpoint);
+ builder.AppendLine("OpenID version: " + this.Version);
builder.AppendLine("Service Type URIs:");
- if (this.ProviderSupportedServiceTypeUris != null) {
- foreach (string serviceTypeUri in this.ProviderSupportedServiceTypeUris) {
- builder.Append("\t");
- builder.AppendLine(serviceTypeUri);
- }
- } else {
- builder.AppendLine("\t(unavailable)");
+ foreach (string serviceTypeUri in this.Capabilities) {
+ builder.Append("\t");
+ builder.AppendLine(serviceTypeUri);
}
builder.Length -= Environment.NewLine.Length; // trim last newline
return builder.ToString();
}
/// <summary>
- /// Reads previously discovered information about an endpoint
- /// from a solicited authentication assertion for validation.
+ /// Checks whether the OpenId Identifier claims support for a given extension.
/// </summary>
- /// <param name="reader">The reader from which to deserialize the <see cref="ServiceEndpoint"/>.</param>
+ /// <typeparam name="T">The extension whose support is being queried.</typeparam>
/// <returns>
- /// A <see cref="ServiceEndpoint"/> object that has everything
- /// except the <see cref="ProviderSupportedServiceTypeUris"/>
- /// deserialized.
+ /// True if support for the extension is advertised. False otherwise.
/// </returns>
- internal static ServiceEndpoint Deserialize(TextReader reader) {
- var claimedIdentifier = Identifier.Parse(reader.ReadLine());
- var providerLocalIdentifier = Identifier.Parse(reader.ReadLine());
- string userSuppliedIdentifier = reader.ReadLine();
- if (userSuppliedIdentifier.Length == 0) {
- userSuppliedIdentifier = null;
+ /// <remarks>
+ /// Note that a true or false return value is no guarantee of a Provider's
+ /// support for or lack of support for an extension. The return value is
+ /// determined by how the authenticating user filled out his/her XRDS document only.
+ /// The only way to be sure of support for a given extension is to include
+ /// the extension in the request and see if a response comes back for that extension.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "No parameter at all.")]
+ public bool IsExtensionSupported<T>() where T : IOpenIdMessageExtension, new() {
+ T extension = new T();
+ return this.IsExtensionSupported(extension);
+ }
+
+ /// <summary>
+ /// Checks whether the OpenId Identifier claims support for a given extension.
+ /// </summary>
+ /// <param name="extensionType">The extension whose support is being queried.</param>
+ /// <returns>
+ /// True if support for the extension is advertised. False otherwise.
+ /// </returns>
+ /// <remarks>
+ /// Note that a true or false return value is no guarantee of a Provider's
+ /// support for or lack of support for an extension. The return value is
+ /// determined by how the authenticating user filled out his/her XRDS document only.
+ /// The only way to be sure of support for a given extension is to include
+ /// the extension in the request and see if a response comes back for that extension.
+ /// </remarks>
+ public bool IsExtensionSupported(Type extensionType) {
+ var extension = (IOpenIdMessageExtension)Activator.CreateInstance(extensionType);
+ return this.IsExtensionSupported(extension);
+ }
+
+ /// <summary>
+ /// Determines whether a given extension is supported by this endpoint.
+ /// </summary>
+ /// <param name="extension">An instance of the extension to check support for.</param>
+ /// <returns>
+ /// <c>true</c> if the extension is supported by this endpoint; otherwise, <c>false</c>.
+ /// </returns>
+ public bool IsExtensionSupported(IOpenIdMessageExtension extension) {
+ Contract.Requires<ArgumentNullException>(extension != null);
+
+ // Consider the primary case.
+ if (this.IsTypeUriPresent(extension.TypeUri)) {
+ return true;
+ }
+
+ // Consider the secondary cases.
+ if (extension.AdditionalSupportedTypeUris != null) {
+ if (extension.AdditionalSupportedTypeUris.Any(typeUri => this.IsTypeUriPresent(typeUri))) {
+ return true;
+ }
}
- var providerEndpoint = new Uri(reader.ReadLine());
- var protocol = Protocol.FindBestVersion(p => p.Version, new[] { new Version(reader.ReadLine()) });
- return new ServiceEndpoint(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, protocol);
+
+ return false;
}
/// <summary>
- /// Creates a <see cref="ServiceEndpoint"/> instance to represent some OP Identifier.
+ /// Creates a <see cref="IdentifierDiscoveryResult"/> instance to represent some OP Identifier.
/// </summary>
/// <param name="providerIdentifier">The provider identifier (actually the user-supplied identifier).</param>
/// <param name="providerEndpoint">The provider endpoint.</param>
/// <param name="servicePriority">The service priority.</param>
/// <param name="uriPriority">The URI priority.</param>
- /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
- internal static ServiceEndpoint CreateForProviderIdentifier(Identifier providerIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
+ /// <returns>The created <see cref="IdentifierDiscoveryResult"/> instance</returns>
+ internal static IdentifierDiscoveryResult CreateForProviderIdentifier(Identifier providerIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
- Protocol protocol = Protocol.Detect(providerEndpoint.Capabilities);
+ Protocol protocol = Protocol.Lookup(providerEndpoint.Version);
- return new ServiceEndpoint(
+ return new IdentifierDiscoveryResult(
providerEndpoint,
protocol.ClaimedIdentifierForOPIdentifier,
providerIdentifier,
@@ -448,20 +406,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier.
+ /// Creates a <see cref="IdentifierDiscoveryResult"/> instance to represent some Claimed Identifier.
/// </summary>
/// <param name="claimedIdentifier">The claimed identifier.</param>
/// <param name="providerLocalIdentifier">The provider local identifier.</param>
/// <param name="providerEndpoint">The provider endpoint.</param>
/// <param name="servicePriority">The service priority.</param>
/// <param name="uriPriority">The URI priority.</param>
- /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
- internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
+ /// <returns>The created <see cref="IdentifierDiscoveryResult"/> instance</returns>
+ internal static IdentifierDiscoveryResult CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
return CreateForClaimedIdentifier(claimedIdentifier, null, providerLocalIdentifier, providerEndpoint, servicePriority, uriPriority);
}
/// <summary>
- /// Creates a <see cref="ServiceEndpoint"/> instance to represent some Claimed Identifier.
+ /// Creates a <see cref="IdentifierDiscoveryResult"/> instance to represent some Claimed Identifier.
/// </summary>
/// <param name="claimedIdentifier">The claimed identifier.</param>
/// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
@@ -469,24 +427,30 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="providerEndpoint">The provider endpoint.</param>
/// <param name="servicePriority">The service priority.</param>
/// <param name="uriPriority">The URI priority.</param>
- /// <returns>The created <see cref="ServiceEndpoint"/> instance</returns>
- internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
- return new ServiceEndpoint(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, servicePriority, uriPriority);
+ /// <returns>The created <see cref="IdentifierDiscoveryResult"/> instance</returns>
+ internal static IdentifierDiscoveryResult CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) {
+ return new IdentifierDiscoveryResult(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, servicePriority, uriPriority);
}
/// <summary>
- /// Saves the discovered information about this endpoint
- /// for later comparison to validate assertions.
+ /// Determines whether a given type URI is present on the specified provider endpoint.
/// </summary>
- /// <param name="writer">The writer to use for serializing out the fields.</param>
- internal void Serialize(TextWriter writer) {
- writer.WriteLine(this.ClaimedIdentifier);
- writer.WriteLine(this.ProviderLocalIdentifier);
- writer.WriteLine(this.UserSuppliedIdentifier);
- writer.WriteLine(this.ProviderEndpoint);
- writer.WriteLine(this.Protocol.Version);
-
- // No reason to serialize priority. We only needed priority to decide whether to use this endpoint.
+ /// <param name="typeUri">The type URI.</param>
+ /// <returns>
+ /// <c>true</c> if the type URI is present on the specified provider endpoint; otherwise, <c>false</c>.
+ /// </returns>
+ internal bool IsTypeUriPresent(string typeUri) {
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(typeUri));
+ return this.Capabilities.Contains(typeUri);
+ }
+
+ /// <summary>
+ /// Sets the Capabilities property (this method is a test hook.)
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <remarks>The publicize.exe tool should work for the unit tests, but for some reason it fails on the build server.</remarks>
+ internal void SetCapabilitiesForTestHook(ReadOnlyCollection<string> value) {
+ this.Capabilities = value;
}
/// <summary>
@@ -495,22 +459,39 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="endpoint">The endpoint to prioritize.</param>
/// <returns>An arbitary integer, which may be used for sorting against other returned values from this method.</returns>
- private static double GetEndpointPrecedenceOrderByServiceType(IXrdsProviderEndpoint endpoint) {
+ private static double GetEndpointPrecedenceOrderByServiceType(IdentifierDiscoveryResult endpoint) {
// The numbers returned from this method only need to compare against other numbers
// from this method, which makes them arbitrary but relational to only others here.
- if (endpoint.IsTypeUriPresent(Protocol.V20.OPIdentifierServiceTypeURI)) {
+ if (endpoint.Capabilities.Contains(Protocol.V20.OPIdentifierServiceTypeURI)) {
return 0;
}
- if (endpoint.IsTypeUriPresent(Protocol.V20.ClaimedIdentifierServiceTypeURI)) {
+ if (endpoint.Capabilities.Contains(Protocol.V20.ClaimedIdentifierServiceTypeURI)) {
return 1;
}
- if (endpoint.IsTypeUriPresent(Protocol.V11.ClaimedIdentifierServiceTypeURI)) {
+ if (endpoint.Capabilities.Contains(Protocol.V11.ClaimedIdentifierServiceTypeURI)) {
return 2;
}
- if (endpoint.IsTypeUriPresent(Protocol.V10.ClaimedIdentifierServiceTypeURI)) {
+ if (endpoint.Capabilities.Contains(Protocol.V10.ClaimedIdentifierServiceTypeURI)) {
return 3;
}
return 10;
}
+
+#if CONTRACTS_FULL
+ /// <summary>
+ /// Verifies conditions that should be true for any valid state of this object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Called by code contracts.")]
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")]
+ [ContractInvariantMethod]
+ private void ObjectInvariant() {
+ Contract.Invariant(this.ProviderEndpoint != null);
+ Contract.Invariant(this.ClaimedIdentifier != null);
+ Contract.Invariant(this.ProviderLocalIdentifier != null);
+ Contract.Invariant(this.Capabilities != null);
+ Contract.Invariant(this.Version != null);
+ Contract.Invariant(this.Protocol != null);
+ }
+#endif
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
index 5215022..3fd9424 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateRequest.cs
@@ -76,16 +76,16 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Null if no association could be created that meet the security requirements
/// and the provider OpenID version.
/// </returns>
- internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider) {
+ internal static AssociateRequest Create(SecuritySettings securityRequirements, IProviderEndpoint provider) {
Contract.Requires<ArgumentNullException>(securityRequirements != null);
Contract.Requires<ArgumentNullException>(provider != null);
// Apply our knowledge of the endpoint's transport, OpenID version, and
// security requirements to decide the best association.
- bool unencryptedAllowed = provider.Endpoint.IsTransportSecure();
+ bool unencryptedAllowed = provider.Uri.IsTransportSecure();
bool useDiffieHellman = !unencryptedAllowed;
string associationType, sessionType;
- if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.ProtocolVersion), true, securityRequirements, useDiffieHellman, out associationType, out sessionType)) {
+ if (!HmacShaAssociation.TryFindBestAssociation(Protocol.Lookup(provider.Version), true, securityRequirements, useDiffieHellman, out associationType, out sessionType)) {
// There are no associations that meet all requirements.
Logger.OpenId.Warn("Security requirements and protocol combination knock out all possible association types. Dumb mode forced.");
return null;
@@ -106,19 +106,19 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Null if no association could be created that meet the security requirements
/// and the provider OpenID version.
/// </returns>
- internal static AssociateRequest Create(SecuritySettings securityRequirements, ProviderEndpointDescription provider, string associationType, string sessionType) {
+ internal static AssociateRequest Create(SecuritySettings securityRequirements, IProviderEndpoint provider, string associationType, string sessionType) {
Contract.Requires<ArgumentNullException>(securityRequirements != null);
Contract.Requires<ArgumentNullException>(provider != null);
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(associationType));
Contract.Requires<ArgumentNullException>(sessionType != null);
- bool unencryptedAllowed = provider.Endpoint.IsTransportSecure();
+ bool unencryptedAllowed = provider.Uri.IsTransportSecure();
if (unencryptedAllowed) {
- var associateRequest = new AssociateUnencryptedRequest(provider.ProtocolVersion, provider.Endpoint);
+ var associateRequest = new AssociateUnencryptedRequest(provider.Version, provider.Uri);
associateRequest.AssociationType = associationType;
return associateRequest;
} else {
- var associateRequest = new AssociateDiffieHellmanRequest(provider.ProtocolVersion, provider.Endpoint);
+ var associateRequest = new AssociateDiffieHellmanRequest(provider.Version, provider.Uri);
associateRequest.AssociationType = associationType;
associateRequest.SessionType = sessionType;
associateRequest.InitializeRequest();
diff --git a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationRequest.cs
index 5306c54..db69d3d 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationRequest.cs
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
// Copy all message parts from the id_res message into this one,
// except for the openid.mode parameter.
- MessageDictionary checkPayload = channel.MessageDescriptions.GetAccessor(message);
+ MessageDictionary checkPayload = channel.MessageDescriptions.GetAccessor(message, true);
MessageDictionary thisPayload = channel.MessageDescriptions.GetAccessor(this);
foreach (var pair in checkPayload) {
if (!string.Equals(pair.Key, this.Protocol.openid.mode)) {
diff --git a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
index 61825e8..f1bb5ac 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/CheckAuthenticationResponse.cs
@@ -47,7 +47,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
// really doesn't exist. OpenID 2.0 section 11.4.2.2.
IndirectSignedResponse signedResponse = new IndirectSignedResponse(request, provider.Channel);
string invalidateHandle = ((ITamperResistantOpenIdMessage)signedResponse).InvalidateHandle;
- if (invalidateHandle != null && provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, invalidateHandle) == null) {
+ if (!string.IsNullOrEmpty(invalidateHandle) && provider.AssociationStore.GetAssociation(AssociationRelyingPartyType.Smart, invalidateHandle) == null) {
this.InvalidateHandle = invalidateHandle;
}
}
@@ -70,8 +70,10 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <para>This two-step process for invalidating associations is necessary
/// to prevent an attacker from invalidating an association at will by
/// adding "invalidate_handle" parameters to an authentication response.</para>
+ /// <para>For OpenID 1.1, we allow this to be present but empty to put up with poor implementations such as Blogger.</para>
/// </remarks>
- [MessagePart("invalidate_handle", IsRequired = false, AllowEmpty = false)]
+ [MessagePart("invalidate_handle", IsRequired = false, AllowEmpty = true, MaxVersion = "1.1")]
+ [MessagePart("invalidate_handle", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
internal string InvalidateHandle { get; set; }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
index 2f02974..fff4cf6 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
@@ -207,7 +207,11 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Gets or sets the association handle that the Provider wants the Relying Party to not use any more.
/// </summary>
/// <value>If the Relying Party sent an invalid association handle with the request, it SHOULD be included here.</value>
- [MessagePart("openid.invalidate_handle", IsRequired = false, AllowEmpty = false)]
+ /// <remarks>
+ /// For OpenID 1.1, we allow this to be present but empty to put up with poor implementations such as Blogger.
+ /// </remarks>
+ [MessagePart("openid.invalidate_handle", IsRequired = false, AllowEmpty = true, MaxVersion = "1.1")]
+ [MessagePart("openid.invalidate_handle", IsRequired = false, AllowEmpty = false, MinVersion = "2.0")]
string ITamperResistantOpenIdMessage.InvalidateHandle { get; set; }
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
index 636df67..1a6e7e9 100644
--- a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
@@ -70,17 +70,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Performs discovery on the Identifier.
- /// </summary>
- /// <param name="requestHandler">The web request handler to use for discovery.</param>
- /// <returns>
- /// An initialized structure containing the discovered provider endpoint information.
- /// </returns>
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- return Enumerable.Empty<ServiceEndpoint>();
- }
-
- /// <summary>
/// Returns an <see cref="Identifier"/> that has no URI fragment.
/// Quietly returns the original <see cref="Identifier"/> if it is not
/// a <see cref="UriIdentifier"/> or no fragment exists.
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index 33a16f8..43283ac 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:2.0.50727.4927
+// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.OpenId {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class OpenIdStrings {
@@ -196,6 +196,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to This OpenID exploits features that this relying party cannot reliably verify. Please try logging in with a human-readable OpenID or from a different OpenID Provider..
+ /// </summary>
+ internal static string ClaimedIdentifierDefiesDotNetNormalization {
+ get {
+ return ResourceManager.GetString("ClaimedIdentifierDefiesDotNetNormalization", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The ClaimedIdentifier property must be set first..
/// </summary>
internal static string ClaimedIdentifierMustBeSetFirst {
@@ -416,6 +425,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Missing {0} element..
+ /// </summary>
+ internal static string MissingElement {
+ get {
+ return ResourceManager.GetString("MissingElement", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to No recognized association type matches the requested length of {0}..
/// </summary>
internal static string NoAssociationTypeFoundByLength {
@@ -722,6 +740,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The X.509 certificate used to sign this document is not trusted..
+ /// </summary>
+ internal static string X509CertificateNotTrusted {
+ get {
+ return ResourceManager.GetString("X509CertificateNotTrusted", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to XRI support has been disabled at this site..
/// </summary>
internal static string XriResolutionDisabled {
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index c5f506d..fab03a9 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -346,4 +346,13 @@ Discovered endpoint info:
<data name="PropertyNotSet" xml:space="preserve">
<value>The {0} property must be set first.</value>
</data>
+ <data name="X509CertificateNotTrusted" xml:space="preserve">
+ <value>The X.509 certificate used to sign this document is not trusted.</value>
+ </data>
+ <data name="ClaimedIdentifierDefiesDotNetNormalization" xml:space="preserve">
+ <value>This OpenID exploits features that this relying party cannot reliably verify. Please try logging in with a human-readable OpenID or from a different OpenID Provider.</value>
+ </data>
+ <data name="MissingElement" xml:space="preserve">
+ <value>Missing {0} element.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs b/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
index 3e75e61..04eb23c 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
@@ -16,13 +16,14 @@ namespace DotNetOpenAuth.OpenId {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Extensions;
+ using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
/// A set of utilities especially useful to OpenID.
/// </summary>
- internal static class OpenIdUtilities {
+ public static class OpenIdUtilities {
/// <summary>
/// The prefix to designate this library's proprietary parameters added to the protocol.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs b/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
index 664a127..00468ed 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
@@ -27,6 +27,9 @@ namespace DotNetOpenAuth.OpenId {
/// or for Provider's to perform RP discovery/verification as part of authentication.
/// </remarks>
internal static IEnumerable<RelyingPartyEndpointDescription> FindRelyingPartyReceivingEndpoints(this XrdsDocument xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<RelyingPartyEndpointDescription>>() != null);
+
return from service in xrds.FindReturnToServices()
from uri in service.UriElements
select new RelyingPartyEndpointDescription(uri.Uri, service.TypeElementUris);
@@ -39,6 +42,9 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="xrds">The XrdsDocument to search.</param>
/// <returns>A sequence of the icon URLs in preferred order.</returns>
internal static IEnumerable<Uri> FindRelyingPartyIcons(this XrdsDocument xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<Uri>>() != null);
+
return from xrd in xrds.XrdElements
from service in xrd.OpenIdRelyingPartyIcons
from uri in service.UriElements
@@ -55,15 +61,16 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// A sequence of OpenID Providers that can assert ownership of the <paramref name="claimedIdentifier"/>.
/// </returns>
- internal static IEnumerable<ServiceEndpoint> CreateServiceEndpoints(this XrdsDocument xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
- var endpoints = new List<ServiceEndpoint>();
+ internal static IEnumerable<IdentifierDiscoveryResult> CreateServiceEndpoints(this IEnumerable<XrdElement> xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
+ Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+
+ var endpoints = new List<IdentifierDiscoveryResult>();
endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier));
+ endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(claimedIdentifier, userSuppliedIdentifier));
- // If any OP Identifier service elements were found, we must not proceed
- // to return any Claimed Identifier services.
- if (endpoints.Count == 0) {
- endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(claimedIdentifier, userSuppliedIdentifier));
- }
Logger.Yadis.DebugFormat("Total services discovered in XRDS: {0}", endpoints.Count);
Logger.Yadis.Debug(endpoints.ToStringDeferred(true));
return endpoints;
@@ -76,18 +83,14 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="userSuppliedIdentifier">The user-supplied i-name that was used to discover this XRDS document.</param>
/// <returns>A sequence of OpenID Providers that can assert ownership of the canonical ID given in this document.</returns>
- internal static IEnumerable<ServiceEndpoint> CreateServiceEndpoints(this XrdsDocument xrds, XriIdentifier userSuppliedIdentifier) {
+ internal static IEnumerable<IdentifierDiscoveryResult> CreateServiceEndpoints(this IEnumerable<XrdElement> xrds, XriIdentifier userSuppliedIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
- Contract.Ensures(Contract.Result<IEnumerable<ServiceEndpoint>>() != null);
- var endpoints = new List<ServiceEndpoint>();
- endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier));
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
- // If any OP Identifier service elements were found, we must not proceed
- // to return any Claimed Identifier services.
- if (endpoints.Count == 0) {
- endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(userSuppliedIdentifier));
- }
+ var endpoints = new List<IdentifierDiscoveryResult>();
+ endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier));
+ endpoints.AddRange(xrds.GenerateClaimedIdentifierServiceEndpoints(userSuppliedIdentifier));
Logger.Yadis.DebugFormat("Total services discovered in XRDS: {0}", endpoints.Count);
Logger.Yadis.Debug(endpoints.ToStringDeferred(true));
return endpoints;
@@ -99,15 +102,15 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="opIdentifier">The OP Identifier entered (and resolved) by the user. Essentially the user-supplied identifier.</param>
/// <returns>A sequence of the providers that can offer directed identity services.</returns>
- private static IEnumerable<ServiceEndpoint> GenerateOPIdentifierServiceEndpoints(this XrdsDocument xrds, Identifier opIdentifier) {
+ private static IEnumerable<IdentifierDiscoveryResult> GenerateOPIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, Identifier opIdentifier) {
Contract.Requires<ArgumentNullException>(xrds != null);
Contract.Requires<ArgumentNullException>(opIdentifier != null);
- Contract.Ensures(Contract.Result<IEnumerable<ServiceEndpoint>>() != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
return from service in xrds.FindOPIdentifierServices()
from uri in service.UriElements
let protocol = Protocol.FindBestVersion(p => p.OPIdentifierServiceTypeURI, service.TypeElementUris)
let providerDescription = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris)
- select ServiceEndpoint.CreateForProviderIdentifier(opIdentifier, providerDescription, service.Priority, uri.Priority);
+ select IdentifierDiscoveryResult.CreateForProviderIdentifier(opIdentifier, providerDescription, service.Priority, uri.Priority);
}
/// <summary>
@@ -120,12 +123,16 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// A sequence of the providers that can assert ownership of the given identifier.
/// </returns>
- private static IEnumerable<ServiceEndpoint> GenerateClaimedIdentifierServiceEndpoints(this XrdsDocument xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
+ private static IEnumerable<IdentifierDiscoveryResult> GenerateClaimedIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+
return from service in xrds.FindClaimedIdentifierServices()
from uri in service.UriElements
where uri.Uri != null
let providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris)
- select ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority);
+ select IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority);
}
/// <summary>
@@ -135,7 +142,12 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <param name="userSuppliedIdentifier">The i-name supplied by the user.</param>
/// <returns>A sequence of the providers that can assert ownership of the given identifier.</returns>
- private static IEnumerable<ServiceEndpoint> GenerateClaimedIdentifierServiceEndpoints(this XrdsDocument xrds, XriIdentifier userSuppliedIdentifier) {
+ private static IEnumerable<IdentifierDiscoveryResult> GenerateClaimedIdentifierServiceEndpoints(this IEnumerable<XrdElement> xrds, XriIdentifier userSuppliedIdentifier) {
+ // Cannot use code contracts because this method uses yield return.
+ ////Contract.Requires<ArgumentNullException>(xrds != null);
+ ////Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+ ErrorUtilities.VerifyArgumentNotNull(xrds, "xrds");
+
foreach (var service in xrds.FindClaimedIdentifierServices()) {
foreach (var uri in service.UriElements) {
// spec section 7.3.2.3 on Claimed Id -> CanonicalID substitution
@@ -148,7 +160,7 @@ namespace DotNetOpenAuth.OpenId {
// In the case of XRI names, the ClaimedId is actually the CanonicalID.
var claimedIdentifier = new XriIdentifier(service.Xrd.CanonicalID);
var providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris);
- yield return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority);
+ yield return IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority);
}
}
}
@@ -158,8 +170,11 @@ namespace DotNetOpenAuth.OpenId {
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of service elements.</returns>
- private static IEnumerable<ServiceElement> FindOPIdentifierServices(this XrdsDocument xrds) {
- return from xrd in xrds.XrdElements
+ private static IEnumerable<ServiceElement> FindOPIdentifierServices(this IEnumerable<XrdElement> xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
+
+ return from xrd in xrds
from service in xrd.OpenIdProviderIdentifierServices
select service;
}
@@ -170,8 +185,11 @@ namespace DotNetOpenAuth.OpenId {
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of the services offered.</returns>
- private static IEnumerable<ServiceElement> FindClaimedIdentifierServices(this XrdsDocument xrds) {
- return from xrd in xrds.XrdElements
+ private static IEnumerable<ServiceElement> FindClaimedIdentifierServices(this IEnumerable<XrdElement> xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
+
+ return from xrd in xrds
from service in xrd.OpenIdClaimedIdentifierServices
select service;
}
@@ -183,6 +201,9 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
/// <returns>A sequence of service elements.</returns>
private static IEnumerable<ServiceElement> FindReturnToServices(this XrdsDocument xrds) {
+ Contract.Requires<ArgumentNullException>(xrds != null);
+ Contract.Ensures(Contract.Result<IEnumerable<ServiceElement>>() != null);
+
return from xrd in xrds.XrdElements
from service in xrd.OpenIdRelyingPartyReturnToServices
select service;
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index 827ca6c..10c69a3 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -20,10 +20,12 @@ namespace DotNetOpenAuth.OpenId.Provider {
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
+ using RP = DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
/// Offers services for a web page that is acting as an OpenID identity server.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "By design")]
[ContractVerification(true)]
public sealed class OpenIdProvider : IDisposable {
/// <summary>
@@ -43,6 +45,12 @@ namespace DotNetOpenAuth.OpenId.Provider {
private ProviderSecuritySettings securitySettings;
/// <summary>
+ /// The relying party used to perform discovery on identifiers being sent in
+ /// unsolicited positive assertions.
+ /// </summary>
+ private RP.OpenIdRelyingParty relyingParty;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdProvider"/> class.
/// </summary>
public OpenIdProvider()
@@ -160,6 +168,13 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
/// <summary>
+ /// Gets the list of services that can perform discovery on identifiers given to this relying party.
+ /// </summary>
+ internal IList<IIdentifierDiscoveryService> DiscoveryServices {
+ get { return this.RelyingParty.DiscoveryServices; }
+ }
+
+ /// <summary>
/// Gets the association store.
/// </summary>
internal IAssociationStore<AssociationRelyingPartyType> AssociationStore { get; private set; }
@@ -173,6 +188,25 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
/// <summary>
+ /// Gets the relying party used for discovery of identifiers sent in unsolicited assertions.
+ /// </summary>
+ private RP.OpenIdRelyingParty RelyingParty {
+ get {
+ if (this.relyingParty == null) {
+ lock (this) {
+ if (this.relyingParty == null) {
+ // we just need an RP that's capable of discovery, so stateless mode is fine.
+ this.relyingParty = new RP.OpenIdRelyingParty(null);
+ }
+ }
+ }
+
+ this.relyingParty.Channel.WebRequestHandler = this.WebRequestHandler;
+ return this.relyingParty;
+ }
+ }
+
+ /// <summary>
/// Gets the incoming OpenID request if there is one, or null if none was detected.
/// </summary>
/// <returns>The request that the hosting Provider should possibly process and then transmit the response for.</returns>
@@ -314,7 +348,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// web site and log him/her in immediately in one uninterrupted step.
/// </summary>
/// <param name="providerEndpoint">The absolute URL on the Provider site that receives OpenID messages.</param>
- /// <param name="relyingParty">The URL of the Relying Party web site.
+ /// <param name="relyingPartyRealm">The URL of the Relying Party web site.
/// This will typically be the home page, but may be a longer URL if
/// that Relying Party considers the scope of its realm to be more specific.
/// The URL provided here must allow discovery of the Relying Party's
@@ -323,15 +357,15 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <param name="localIdentifier">The Identifier you know your user by internally. This will typically
/// be the same as <paramref name="claimedIdentifier"/>.</param>
/// <param name="extensions">The extensions.</param>
- public void SendUnsolicitedAssertion(Uri providerEndpoint, Realm relyingParty, Identifier claimedIdentifier, Identifier localIdentifier, params IExtensionMessage[] extensions) {
+ public void SendUnsolicitedAssertion(Uri providerEndpoint, Realm relyingPartyRealm, Identifier claimedIdentifier, Identifier localIdentifier, params IExtensionMessage[] extensions) {
Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
Contract.Requires<ArgumentException>(providerEndpoint.IsAbsoluteUri);
- Contract.Requires<ArgumentNullException>(relyingParty != null);
+ Contract.Requires<ArgumentNullException>(relyingPartyRealm != null);
Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
Contract.Requires<ArgumentNullException>(localIdentifier != null);
- this.PrepareUnsolicitedAssertion(providerEndpoint, relyingParty, claimedIdentifier, localIdentifier, extensions).Send();
+ this.PrepareUnsolicitedAssertion(providerEndpoint, relyingPartyRealm, claimedIdentifier, localIdentifier, extensions).Send();
}
/// <summary>
@@ -340,7 +374,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// web site and log him/her in immediately in one uninterrupted step.
/// </summary>
/// <param name="providerEndpoint">The absolute URL on the Provider site that receives OpenID messages.</param>
- /// <param name="relyingParty">The URL of the Relying Party web site.
+ /// <param name="relyingPartyRealm">The URL of the Relying Party web site.
/// This will typically be the home page, but may be a longer URL if
/// that Relying Party considers the scope of its realm to be more specific.
/// The URL provided here must allow discovery of the Relying Party's
@@ -353,10 +387,10 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// A <see cref="OutgoingWebResponse"/> object describing the HTTP response to send
/// the user agent to allow the redirect with assertion to happen.
/// </returns>
- public OutgoingWebResponse PrepareUnsolicitedAssertion(Uri providerEndpoint, Realm relyingParty, Identifier claimedIdentifier, Identifier localIdentifier, params IExtensionMessage[] extensions) {
+ public OutgoingWebResponse PrepareUnsolicitedAssertion(Uri providerEndpoint, Realm relyingPartyRealm, Identifier claimedIdentifier, Identifier localIdentifier, params IExtensionMessage[] extensions) {
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
Contract.Requires<ArgumentException>(providerEndpoint.IsAbsoluteUri);
- Contract.Requires<ArgumentNullException>(relyingParty != null);
+ Contract.Requires<ArgumentNullException>(relyingPartyRealm != null);
Contract.Requires<ArgumentNullException>(claimedIdentifier != null);
Contract.Requires<ArgumentNullException>(localIdentifier != null);
Contract.Requires<InvalidOperationException>(this.Channel.WebRequestHandler != null);
@@ -366,8 +400,8 @@ namespace DotNetOpenAuth.OpenId.Provider {
// do due diligence by performing our own discovery on the claimed identifier
// and make sure that it is tied to this OP and OP local identifier.
if (this.SecuritySettings.UnsolicitedAssertionVerification != ProviderSecuritySettings.UnsolicitedAssertionVerificationLevel.NeverVerify) {
- var serviceEndpoint = DotNetOpenAuth.OpenId.RelyingParty.ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, localIdentifier, new ProviderEndpointDescription(providerEndpoint, Protocol.Default.Version), null, null);
- var discoveredEndpoints = claimedIdentifier.Discover(this.WebRequestHandler);
+ var serviceEndpoint = IdentifierDiscoveryResult.CreateForClaimedIdentifier(claimedIdentifier, localIdentifier, new ProviderEndpointDescription(providerEndpoint, Protocol.Default.Version), null, null);
+ var discoveredEndpoints = this.RelyingParty.Discover(claimedIdentifier);
if (!discoveredEndpoints.Contains(serviceEndpoint)) {
Logger.OpenId.WarnFormat(
"Failed to send unsolicited assertion for {0} because its discovered services did not include this endpoint: {1}{2}{1}Discovered endpoints: {1}{3}",
@@ -385,11 +419,11 @@ namespace DotNetOpenAuth.OpenId.Provider {
Logger.OpenId.InfoFormat("Preparing unsolicited assertion for {0}", claimedIdentifier);
RelyingPartyEndpointDescription returnToEndpoint = null;
- var returnToEndpoints = relyingParty.DiscoverReturnToEndpoints(this.WebRequestHandler, true);
+ var returnToEndpoints = relyingPartyRealm.DiscoverReturnToEndpoints(this.WebRequestHandler, true);
if (returnToEndpoints != null) {
returnToEndpoint = returnToEndpoints.FirstOrDefault();
}
- ErrorUtilities.VerifyProtocol(returnToEndpoint != null, OpenIdStrings.NoRelyingPartyEndpointDiscovered, relyingParty);
+ ErrorUtilities.VerifyProtocol(returnToEndpoint != null, OpenIdStrings.NoRelyingPartyEndpointDiscovered, relyingPartyRealm);
var positiveAssertion = new PositiveAssertionResponse(returnToEndpoint) {
ProviderEndpoint = providerEndpoint,
@@ -428,6 +462,10 @@ namespace DotNetOpenAuth.OpenId.Provider {
if (channel != null) {
channel.Dispose();
}
+
+ if (this.relyingParty != null) {
+ this.relyingParty.Dispose();
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
index 445978e..e792a81 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs
@@ -98,11 +98,15 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </remarks>
public static IAuthenticationRequest PendingAuthenticationRequest {
get {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
Contract.Ensures(Contract.Result<IAuthenticationRequest>() == null || PendingRequest != null);
return HttpContext.Current.Session[PendingRequestKey] as IAuthenticationRequest;
}
set {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
HttpContext.Current.Session[PendingRequestKey] = value;
}
}
@@ -118,11 +122,15 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </remarks>
public static IAnonymousRequest PendingAnonymousRequest {
get {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
Contract.Ensures(Contract.Result<IAnonymousRequest>() == null || PendingRequest != null);
return HttpContext.Current.Session[PendingRequestKey] as IAnonymousRequest;
}
set {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
HttpContext.Current.Session[PendingRequestKey] = value;
}
}
@@ -137,8 +145,17 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// before responding to the relying party's request.
/// </remarks>
public static IHostProcessedRequest PendingRequest {
- get { return HttpContext.Current.Session[PendingRequestKey] as IHostProcessedRequest; }
- set { HttpContext.Current.Session[PendingRequestKey] = value; }
+ get {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
+ return HttpContext.Current.Session[PendingRequestKey] as IHostProcessedRequest;
+ }
+
+ set {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null, MessagingStrings.HttpContextRequired);
+ Contract.Requires<InvalidOperationException>(HttpContext.Current.Session != null, MessagingStrings.SessionRequired);
+ HttpContext.Current.Session[PendingRequestKey] = value;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs b/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs
index 4cfbac5..6514ffd 100644
--- a/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs
+++ b/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -21,7 +22,7 @@ namespace DotNetOpenAuth.OpenId {
/// This is an immutable type.
/// </remarks>
[Serializable]
- internal class ProviderEndpointDescription : IProviderEndpoint {
+ internal sealed class ProviderEndpointDescription : IProviderEndpoint {
/// <summary>
/// Initializes a new instance of the <see cref="ProviderEndpointDescription"/> class.
/// </summary>
@@ -31,8 +32,9 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
Contract.Requires<ArgumentNullException>(openIdVersion != null);
- this.Endpoint = providerEndpoint;
- this.ProtocolVersion = openIdVersion;
+ this.Uri = providerEndpoint;
+ this.Version = openIdVersion;
+ this.Capabilities = new ReadOnlyCollection<string>(EmptyList<string>.Instance);
}
/// <summary>
@@ -44,42 +46,24 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<ArgumentNullException>(providerEndpoint != null);
Contract.Requires<ArgumentNullException>(serviceTypeURIs != null);
- this.Endpoint = providerEndpoint;
+ this.Uri = providerEndpoint;
this.Capabilities = new ReadOnlyCollection<string>(serviceTypeURIs.ToList());
Protocol opIdentifierProtocol = Protocol.FindBestVersion(p => p.OPIdentifierServiceTypeURI, serviceTypeURIs);
Protocol claimedIdentifierProviderVersion = Protocol.FindBestVersion(p => p.ClaimedIdentifierServiceTypeURI, serviceTypeURIs);
if (opIdentifierProtocol != null) {
- this.ProtocolVersion = opIdentifierProtocol.Version;
+ this.Version = opIdentifierProtocol.Version;
} else if (claimedIdentifierProviderVersion != null) {
- this.ProtocolVersion = claimedIdentifierProviderVersion.Version;
+ this.Version = claimedIdentifierProviderVersion.Version;
+ } else {
+ ErrorUtilities.ThrowProtocol(OpenIdStrings.ProviderVersionUnrecognized, this.Uri);
}
-
- ErrorUtilities.VerifyProtocol(this.ProtocolVersion != null, OpenIdStrings.ProviderVersionUnrecognized, this.Endpoint);
}
- #region IProviderEndpoint Properties
-
- /// <summary>
- /// Gets the detected version of OpenID implemented by the Provider.
- /// </summary>
- Version IProviderEndpoint.Version {
- get { return this.ProtocolVersion; }
- }
-
- /// <summary>
- /// Gets the URL that the OpenID Provider receives authentication requests at.
- /// </summary>
- Uri IProviderEndpoint.Uri {
- get { return this.Endpoint; }
- }
-
- #endregion
-
/// <summary>
/// Gets the URL that the OpenID Provider listens for incoming OpenID messages on.
/// </summary>
- internal Uri Endpoint { get; private set; }
+ public Uri Uri { get; private set; }
/// <summary>
/// Gets the OpenID protocol version this endpoint supports.
@@ -88,14 +72,14 @@ namespace DotNetOpenAuth.OpenId {
/// If an endpoint supports multiple versions, each version must be represented
/// by its own <see cref="ProviderEndpointDescription"/> object.
/// </remarks>
- internal Version ProtocolVersion { get; private set; }
+ public Version Version { get; private set; }
/// <summary>
/// Gets the collection of service type URIs found in the XRDS document describing this Provider.
/// </summary>
internal ReadOnlyCollection<string> Capabilities { get; private set; }
- #region IProviderEndpoint Methods
+ #region IProviderEndpoint Members
/// <summary>
/// Checks whether the OpenId Identifier claims support for a given extension.
@@ -111,10 +95,8 @@ namespace DotNetOpenAuth.OpenId {
/// The only way to be sure of support for a given extension is to include
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
- public bool IsExtensionSupported<T>() where T : IOpenIdMessageExtension, new() {
- ErrorUtilities.VerifyOperation(this.Capabilities != null, OpenIdStrings.ExtensionLookupSupportUnavailable);
- T extension = new T();
- return this.IsExtensionSupported(extension);
+ bool IProviderEndpoint.IsExtensionSupported<T>() {
+ throw new NotImplementedException();
}
/// <summary>
@@ -131,52 +113,22 @@ namespace DotNetOpenAuth.OpenId {
/// The only way to be sure of support for a given extension is to include
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
- public bool IsExtensionSupported(Type extensionType) {
- ErrorUtilities.VerifyOperation(this.Capabilities != null, OpenIdStrings.ExtensionLookupSupportUnavailable);
- var extension = (IOpenIdMessageExtension)Activator.CreateInstance(extensionType);
- return this.IsExtensionSupported(extension);
+ bool IProviderEndpoint.IsExtensionSupported(Type extensionType) {
+ throw new NotImplementedException();
}
#endregion
+#if CONTRACTS_FULL
/// <summary>
- /// Determines whether some extension is supported by the Provider.
+ /// Verifies conditions that should be true for any valid state of this object.
/// </summary>
- /// <param name="extensionUri">The extension URI.</param>
- /// <returns>
- /// <c>true</c> if the extension is supported; otherwise, <c>false</c>.
- /// </returns>
- protected internal bool IsExtensionSupported(string extensionUri) {
- Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(extensionUri));
- Contract.Requires<InvalidOperationException>(this.Capabilities != null, OpenIdStrings.ExtensionLookupSupportUnavailable);
- return this.Capabilities.Contains(extensionUri);
- }
-
- /// <summary>
- /// Determines whether a given extension is supported by this endpoint.
- /// </summary>
- /// <param name="extension">An instance of the extension to check support for.</param>
- /// <returns>
- /// <c>true</c> if the extension is supported by this endpoint; otherwise, <c>false</c>.
- /// </returns>
- protected internal bool IsExtensionSupported(IOpenIdMessageExtension extension) {
- Contract.Requires<ArgumentNullException>(extension != null);
- Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(extension.TypeUri));
- Contract.Requires<InvalidOperationException>(this.Capabilities != null, OpenIdStrings.ExtensionLookupSupportUnavailable);
-
- // Consider the primary case.
- if (this.IsExtensionSupported(extension.TypeUri)) {
- return true;
- }
-
- // Consider the secondary cases.
- if (extension.AdditionalSupportedTypeUris != null) {
- if (extension.AdditionalSupportedTypeUris.Any(typeUri => this.IsExtensionSupported(typeUri))) {
- return true;
- }
- }
-
- return false;
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Called by code contracts.")]
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")]
+ [ContractInvariantMethod]
+ private void ObjectInvariant() {
+ Contract.Invariant(this.Capabilities != null);
}
+#endif
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs
index 600e6c0..98e3598 100644
--- a/src/DotNetOpenAuth/OpenId/Realm.cs
+++ b/src/DotNetOpenAuth/OpenId/Realm.cs
@@ -13,6 +13,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
+ using System.Web;
using System.Xml;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Xrds;
@@ -98,6 +99,40 @@ namespace DotNetOpenAuth.OpenId {
: this(SafeUriBuilderToString(realmUriBuilder)) { }
/// <summary>
+ /// Gets the suggested realm to use for the calling web application.
+ /// </summary>
+ /// <value>A realm that matches this applications root URL.</value>
+ /// <remarks>
+ /// <para>For most circumstances the Realm generated by this property is sufficient.
+ /// However a wildcard Realm, such as "http://*.microsoft.com/" may at times be more
+ /// desirable than "http://www.microsoft.com/" in order to allow identifier
+ /// correlation across related web sites for directed identity Providers.</para>
+ /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
+ /// </remarks>
+ public static Realm AutoDetect {
+ get {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
+ Contract.Ensures(Contract.Result<Realm>() != null);
+
+ HttpRequestInfo requestInfo = new HttpRequestInfo(HttpContext.Current.Request);
+ UriBuilder realmUrl = new UriBuilder(requestInfo.UrlBeforeRewriting);
+ realmUrl.Path = HttpContext.Current.Request.ApplicationPath;
+ realmUrl.Query = null;
+ realmUrl.Fragment = null;
+
+ // For RP discovery, the realm url MUST NOT redirect. To prevent this for
+ // virtual directory hosted apps, we need to make sure that the realm path ends
+ // in a slash (since our calculation above guarantees it doesn't end in a specific
+ // page like default.aspx).
+ if (!realmUrl.Path.EndsWith("/", StringComparison.Ordinal)) {
+ realmUrl.Path += "/";
+ }
+
+ return realmUrl.Uri;
+ }
+ }
+
+ /// <summary>
/// Gets a value indicating whether a '*.' prefix to the hostname is
/// used in the realm to allow subdomains or hosts to be added to the URL.
/// </summary>
@@ -145,6 +180,14 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Gets the original string.
+ /// </summary>
+ /// <value>The original string.</value>
+ internal string OriginalString {
+ get { return this.uri.OriginalString; }
+ }
+
+ /// <summary>
/// Gets the realm URL. If the realm includes a wildcard, it is not included here.
/// </summary>
internal Uri NoWildcardUri {
@@ -219,6 +262,7 @@ namespace DotNetOpenAuth.OpenId {
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Not all Realms are valid URLs.")]
[DebuggerStepThrough]
public static implicit operator Realm(string uri) {
+ Contract.Ensures((Contract.Result<Realm>() != null) == (uri != null));
return uri != null ? new Realm(uri) : null;
}
@@ -229,6 +273,7 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>The result of the conversion.</returns>
[DebuggerStepThrough]
public static implicit operator Realm(Uri uri) {
+ Contract.Ensures((Contract.Result<Realm>() != null) == (uri != null));
return uri != null ? new Realm(uri) : null;
}
@@ -239,6 +284,7 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>The result of the conversion.</returns>
[DebuggerStepThrough]
public static implicit operator string(Realm realm) {
+ Contract.Ensures((Contract.Result<string>() != null) == (realm != null));
return realm != null ? realm.ToString() : null;
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs
index bc2b6ca..ac70387 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AssociationManager.cs
@@ -96,7 +96,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="provider">The provider to create an association with.</param>
/// <returns>The association if one exists and has useful life remaining. Otherwise <c>null</c>.</returns>
- internal Association GetExistingAssociation(ProviderEndpointDescription provider) {
+ internal Association GetExistingAssociation(IProviderEndpoint provider) {
Contract.Requires<ArgumentNullException>(provider != null);
// If the RP has no application store for associations, there's no point in creating one.
@@ -104,7 +104,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return null;
}
- Association association = this.associationStore.GetAssociation(provider.Endpoint, this.SecuritySettings);
+ Association association = this.associationStore.GetAssociation(provider.Uri, this.SecuritySettings);
// If the returned association does not fulfill security requirements, ignore it.
if (association != null && !this.SecuritySettings.IsAssociationInPermittedRange(association)) {
@@ -124,7 +124,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="provider">The provider to get an association for.</param>
/// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns>
- internal Association GetOrCreateAssociation(ProviderEndpointDescription provider) {
+ internal Association GetOrCreateAssociation(IProviderEndpoint provider) {
return this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider);
}
@@ -141,7 +141,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// association store.
/// Any new association is automatically added to the <see cref="associationStore"/>.
/// </remarks>
- private Association CreateNewAssociation(ProviderEndpointDescription provider) {
+ private Association CreateNewAssociation(IProviderEndpoint provider) {
Contract.Requires<ArgumentNullException>(provider != null);
// If there is no association store, there is no point in creating an association.
@@ -160,7 +160,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// sometimes causes the CLR to throw:
// "VerificationException: Operation could destabilize the runtime."
// Just give up and use dumb mode in this case.
- Logger.OpenId.ErrorFormat("VerificationException occurred while trying to create an association with {0}. {1}", provider.Endpoint, ex);
+ Logger.OpenId.ErrorFormat("VerificationException occurred while trying to create an association with {0}. {1}", provider.Uri, ex);
return null;
}
}
@@ -175,7 +175,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The newly created association, or null if no association can be created with
/// the given Provider given the current security settings.
/// </returns>
- private Association CreateNewAssociation(ProviderEndpointDescription provider, AssociateRequest associateRequest, int retriesRemaining) {
+ private Association CreateNewAssociation(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining) {
Contract.Requires<ArgumentNullException>(provider != null);
if (associateRequest == null || retriesRemaining < 0) {
@@ -190,7 +190,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
var associateUnsuccessfulResponse = associateResponse as AssociateUnsuccessfulResponse;
if (associateSuccessfulResponse != null) {
Association association = associateSuccessfulResponse.CreateAssociation(associateRequest, null);
- this.associationStore.StoreAssociation(provider.Endpoint, association);
+ this.associationStore.StoreAssociation(provider.Uri, association);
return association;
} else if (associateUnsuccessfulResponse != null) {
if (string.IsNullOrEmpty(associateUnsuccessfulResponse.AssociationType)) {
@@ -198,7 +198,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return null;
}
- if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.ProtocolVersion), associateUnsuccessfulResponse.AssociationType)) {
+ if (!this.securitySettings.IsAssociationInPermittedRange(Protocol.Lookup(provider.Version), associateUnsuccessfulResponse.AssociationType)) {
Logger.OpenId.DebugFormat("Provider rejected an association request and suggested '{0}' as an association to try, which this Relying Party does not support. Giving up.", associateUnsuccessfulResponse.AssociationType);
return null;
}
@@ -209,7 +209,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
// Make sure the Provider isn't suggesting an incompatible pair of association/session types.
- Protocol protocol = Protocol.Lookup(provider.ProtocolVersion);
+ Protocol protocol = Protocol.Lookup(provider.Version);
ErrorUtilities.VerifyProtocol(
HmacShaAssociation.IsDHSessionCompatible(protocol, associateUnsuccessfulResponse.AssociationType, associateUnsuccessfulResponse.SessionType),
OpenIdStrings.IncompatibleAssociationAndSessionTypes,
@@ -231,7 +231,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Since having associations with OPs is not totally critical, we'll log and eat
// the exception so that auth may continue in dumb mode.
- Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Endpoint, ex);
+ Logger.OpenId.ErrorFormat("An error occurred while trying to create an association with {0}. {1}", provider.Uri, ex);
return null;
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index def8f34..09383bb 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -4,8 +4,6 @@
// </copyright>
//-----------------------------------------------------------------------
-using System.Threading;
-
namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
@@ -13,6 +11,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
+ using System.Threading;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.ChannelElements;
@@ -34,12 +33,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private readonly OpenIdRelyingParty RelyingParty;
/// <summary>
- /// The endpoint that describes the particular OpenID Identifier and Provider that
- /// will be used to create the authentication request.
- /// </summary>
- private readonly ServiceEndpoint endpoint;
-
- /// <summary>
/// How an association may or should be created or used in the formulation of the
/// authentication request.
/// </summary>
@@ -69,17 +62,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationRequest"/> class.
/// </summary>
- /// <param name="endpoint">The endpoint that describes the OpenID Identifier and Provider that will complete the authentication.</param>
+ /// <param name="discoveryResult">The endpoint that describes the OpenID Identifier and Provider that will complete the authentication.</param>
/// <param name="realm">The realm, or root URL, of the host web site.</param>
/// <param name="returnToUrl">The base return_to URL that the Provider should return the user to to complete authentication. This should not include callback parameters as these should be added using the <see cref="AddCallbackArguments(string, string)"/> method.</param>
/// <param name="relyingParty">The relying party that created this instance.</param>
- private AuthenticationRequest(ServiceEndpoint endpoint, Realm realm, Uri returnToUrl, OpenIdRelyingParty relyingParty) {
- Contract.Requires<ArgumentNullException>(endpoint != null);
+ private AuthenticationRequest(IdentifierDiscoveryResult discoveryResult, Realm realm, Uri returnToUrl, OpenIdRelyingParty relyingParty) {
+ Contract.Requires<ArgumentNullException>(discoveryResult != null);
Contract.Requires<ArgumentNullException>(realm != null);
Contract.Requires<ArgumentNullException>(returnToUrl != null);
Contract.Requires<ArgumentNullException>(relyingParty != null);
- this.endpoint = endpoint;
+ this.DiscoveryResult = discoveryResult;
this.RelyingParty = relyingParty;
this.Realm = realm;
this.ReturnToUrl = returnToUrl;
@@ -139,7 +132,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// property for a null value.
/// </remarks>
public Identifier ClaimedIdentifier {
- get { return this.IsDirectedIdentity ? null : this.endpoint.ClaimedIdentifier; }
+ get { return this.IsDirectedIdentity ? null : this.DiscoveryResult.ClaimedIdentifier; }
}
/// <summary>
@@ -147,7 +140,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// determine and send the ClaimedIdentifier after authentication.
/// </summary>
public bool IsDirectedIdentity {
- get { return this.endpoint.ClaimedIdentifier == this.endpoint.Protocol.ClaimedIdentifierForOPIdentifier; }
+ get { return this.DiscoveryResult.ClaimedIdentifier == this.DiscoveryResult.Protocol.ClaimedIdentifierForOPIdentifier; }
}
/// <summary>
@@ -166,9 +159,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// location.
/// </summary>
public IProviderEndpoint Provider {
- get { return this.endpoint; }
+ get { return this.DiscoveryResult; }
}
+ /// <summary>
+ /// Gets the discovery result leading to the formulation of this request.
+ /// </summary>
+ /// <value>The discovery result.</value>
+ public IdentifierDiscoveryResult DiscoveryResult { get; private set; }
+
#endregion
/// <summary>
@@ -194,13 +193,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
get { return this.extensions; }
}
- /// <summary>
- /// Gets the service endpoint.
- /// </summary>
- internal ServiceEndpoint Endpoint {
- get { return this.endpoint; }
- }
-
#region IAuthenticationRequest methods
/// <summary>
@@ -367,12 +359,23 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
ErrorUtilities.VerifyProtocol(realm.Contains(returnToUrl), OpenIdStrings.ReturnToNotUnderRealm, returnToUrl, realm);
// Perform discovery right now (not deferred).
- IEnumerable<ServiceEndpoint> serviceEndpoints;
+ IEnumerable<IdentifierDiscoveryResult> serviceEndpoints;
try {
- serviceEndpoints = userSuppliedIdentifier.Discover(relyingParty.WebRequestHandler);
+ var results = relyingParty.Discover(userSuppliedIdentifier).CacheGeneratedResults();
+
+ // If any OP Identifier service elements were found, we must not proceed
+ // to use any Claimed Identifier services, per OpenID 2.0 sections 7.3.2.2 and 11.2.
+ // For a discussion on this topic, see
+ // http://groups.google.com/group/dotnetopenid/browse_thread/thread/4b5a8c6b2210f387/5e25910e4d2252c8
+ // Usually the Discover method we called will automatically filter this for us, but
+ // just to be sure, we'll do it here as well since the RP may be configured to allow
+ // these dual identifiers for assertion verification purposes.
+ var opIdentifiers = results.Where(result => result.ClaimedIdentifier == result.Protocol.ClaimedIdentifierForOPIdentifier).CacheGeneratedResults();
+ var claimedIdentifiers = results.Where(result => result.ClaimedIdentifier != result.Protocol.ClaimedIdentifierForOPIdentifier);
+ serviceEndpoints = opIdentifiers.Any() ? opIdentifiers : claimedIdentifiers;
} catch (ProtocolException ex) {
Logger.Yadis.ErrorFormat("Error while performing discovery on: \"{0}\": {1}", userSuppliedIdentifier, ex);
- serviceEndpoints = EmptyList<ServiceEndpoint>.Instance;
+ serviceEndpoints = Enumerable.Empty<IdentifierDiscoveryResult>();
}
// Filter disallowed endpoints.
@@ -383,6 +386,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Creates an instance of <see cref="AuthenticationRequest"/> FOR TESTING PURPOSES ONLY.
+ /// </summary>
+ /// <param name="discoveryResult">The discovery result.</param>
+ /// <param name="realm">The realm.</param>
+ /// <param name="returnTo">The return to.</param>
+ /// <param name="rp">The relying party.</param>
+ /// <returns>The instantiated <see cref="AuthenticationRequest"/>.</returns>
+ internal static AuthenticationRequest CreateForTest(IdentifierDiscoveryResult discoveryResult, Realm realm, Uri returnTo, OpenIdRelyingParty rp) {
+ return new AuthenticationRequest(discoveryResult, realm, returnTo, rp);
+ }
+
+ /// <summary>
/// Performs deferred request generation for the <see cref="Create"/> method.
/// </summary>
/// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
@@ -399,7 +414,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// All data validation and cleansing steps must have ALREADY taken place
/// before calling this method.
/// </remarks>
- private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<ServiceEndpoint> serviceEndpoints, bool createNewAssociationsAsNeeded) {
+ private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<IdentifierDiscoveryResult> serviceEndpoints, bool createNewAssociationsAsNeeded) {
// DO NOT USE CODE CONTRACTS IN THIS METHOD, since it uses yield return
ErrorUtilities.VerifyArgumentNotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty");
@@ -411,12 +426,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
ErrorUtilities.VerifyOperation(!relyingParty.SecuritySettings.RequireAssociation || relyingParty.AssociationManager.HasAssociationStore, OpenIdStrings.AssociationStoreRequired);
Logger.Yadis.InfoFormat("Performing discovery on user-supplied identifier: {0}", userSuppliedIdentifier);
- IEnumerable<ServiceEndpoint> endpoints = FilterAndSortEndpoints(serviceEndpoints, relyingParty);
+ IEnumerable<IdentifierDiscoveryResult> endpoints = FilterAndSortEndpoints(serviceEndpoints, relyingParty);
// Maintain a list of endpoints that we could not form an association with.
// We'll fallback to generating requests to these if the ones we CAN create
// an association with run out.
- var failedAssociationEndpoints = new List<ServiceEndpoint>(0);
+ var failedAssociationEndpoints = new List<IdentifierDiscoveryResult>(0);
foreach (var endpoint in endpoints) {
Logger.OpenId.DebugFormat("Creating authentication request for user supplied Identifier: {0}", userSuppliedIdentifier);
@@ -427,7 +442,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// In some scenarios (like the AJAX control wanting ALL auth requests possible),
// we don't want to create associations with every Provider. But we'll use
// associations where they are already formed from previous authentications.
- association = createNewAssociationsAsNeeded ? relyingParty.AssociationManager.GetOrCreateAssociation(endpoint.ProviderDescription) : relyingParty.AssociationManager.GetExistingAssociation(endpoint.ProviderDescription);
+ association = createNewAssociationsAsNeeded ? relyingParty.AssociationManager.GetOrCreateAssociation(endpoint) : relyingParty.AssociationManager.GetExistingAssociation(endpoint);
if (association == null && createNewAssociationsAsNeeded) {
Logger.OpenId.WarnFormat("Failed to create association with {0}. Skipping to next endpoint.", endpoint.ProviderEndpoint);
@@ -470,17 +485,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <param name="endpoints">The endpoints.</param>
/// <param name="relyingParty">The relying party.</param>
/// <returns>A filtered and sorted list of endpoints; may be empty if the input was empty or the filter removed all endpoints.</returns>
- private static List<ServiceEndpoint> FilterAndSortEndpoints(IEnumerable<ServiceEndpoint> endpoints, OpenIdRelyingParty relyingParty) {
+ private static List<IdentifierDiscoveryResult> FilterAndSortEndpoints(IEnumerable<IdentifierDiscoveryResult> endpoints, OpenIdRelyingParty 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 => ((ServiceEndpoint)ep).Protocol.Version >= Protocol.Lookup(relyingParty.SecuritySettings.MinimumRequiredOpenIdVersion).Version;
+ EndpointSelector versionFilter = ep => ep.Version >= Protocol.Lookup(relyingParty.SecuritySettings.MinimumRequiredOpenIdVersion).Version;
EndpointSelector hostingSiteFilter = relyingParty.EndpointFilter ?? (ep => true);
bool anyFilteredOut = false;
- var filteredEndpoints = new List<IXrdsProviderEndpoint>();
- foreach (ServiceEndpoint endpoint in endpoints) {
+ var filteredEndpoints = new List<IdentifierDiscoveryResult>();
+ foreach (var endpoint in endpoints) {
if (versionFilter(endpoint) && hostingSiteFilter(endpoint)) {
filteredEndpoints.Add(endpoint);
} else {
@@ -489,10 +504,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
// Sort endpoints so that the first one in the list is the most preferred one.
- filteredEndpoints.Sort(relyingParty.EndpointOrder);
+ filteredEndpoints.OrderBy(ep => ep, relyingParty.EndpointOrder);
- List<ServiceEndpoint> endpointList = new List<ServiceEndpoint>(filteredEndpoints.Count);
- foreach (ServiceEndpoint endpoint in filteredEndpoints) {
+ var endpointList = new List<IdentifierDiscoveryResult>(filteredEndpoints.Count);
+ foreach (var endpoint in filteredEndpoints) {
endpointList.Add(endpoint);
}
@@ -521,20 +536,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
SignedResponseRequest request;
if (!this.IsExtensionOnly) {
- CheckIdRequest authRequest = new CheckIdRequest(this.endpoint.Protocol.Version, this.endpoint.ProviderEndpoint, this.Mode);
- authRequest.ClaimedIdentifier = this.endpoint.ClaimedIdentifier;
- authRequest.LocalIdentifier = this.endpoint.ProviderLocalIdentifier;
+ CheckIdRequest authRequest = new CheckIdRequest(this.DiscoveryResult.Version, this.DiscoveryResult.ProviderEndpoint, this.Mode);
+ authRequest.ClaimedIdentifier = this.DiscoveryResult.ClaimedIdentifier;
+ authRequest.LocalIdentifier = this.DiscoveryResult.ProviderLocalIdentifier;
request = authRequest;
} else {
- request = new SignedResponseRequest(this.endpoint.Protocol.Version, this.endpoint.ProviderEndpoint, this.Mode);
+ request = new SignedResponseRequest(this.DiscoveryResult.Version, this.DiscoveryResult.ProviderEndpoint, this.Mode);
}
request.Realm = this.Realm;
request.ReturnTo = this.ReturnToUrl;
request.AssociationHandle = association != null ? association.Handle : null;
request.SignReturnTo = this.returnToArgsMustBeSigned;
request.AddReturnToArguments(this.returnToArgs);
- if (this.endpoint.UserSuppliedIdentifier != null) {
- request.AddReturnToArguments(UserSuppliedIdentifierParameterName, this.endpoint.UserSuppliedIdentifier.OriginalString);
+ if (this.DiscoveryResult.UserSuppliedIdentifier != null) {
+ request.AddReturnToArguments(UserSuppliedIdentifierParameterName, this.DiscoveryResult.UserSuppliedIdentifier.OriginalString);
}
foreach (IOpenIdMessageExtension extension in this.extensions) {
request.Extensions.Add(extension);
@@ -551,7 +566,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Association association = null;
switch (this.associationPreference) {
case AssociationPreference.IfPossible:
- association = this.RelyingParty.AssociationManager.GetOrCreateAssociation(this.endpoint.ProviderDescription);
+ association = this.RelyingParty.AssociationManager.GetOrCreateAssociation(this.DiscoveryResult);
if (association == null) {
// Avoid trying to create the association again if the redirecting response
// is generated again.
@@ -559,7 +574,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
break;
case AssociationPreference.IfAlreadyEstablished:
- association = this.RelyingParty.AssociationManager.GetExistingAssociation(this.endpoint.ProviderDescription);
+ association = this.RelyingParty.AssociationManager.GetExistingAssociation(this.DiscoveryResult);
break;
case AssociationPreference.Never:
break;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/DuplicateRequestedHostsComparer.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/DuplicateRequestedHostsComparer.cs
new file mode 100644
index 0000000..94eb5ba
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/DuplicateRequestedHostsComparer.cs
@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------
+// <copyright file="DuplicateRequestedHostsComparer.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// An authentication request comparer that judges equality solely on the OP endpoint hostname.
+ /// </summary>
+ internal class DuplicateRequestedHostsComparer : IEqualityComparer<IAuthenticationRequest> {
+ /// <summary>
+ /// The singleton instance of this comparer.
+ /// </summary>
+ private static IEqualityComparer<IAuthenticationRequest> instance = new DuplicateRequestedHostsComparer();
+
+ /// <summary>
+ /// Prevents a default instance of the <see cref="DuplicateRequestedHostsComparer"/> class from being created.
+ /// </summary>
+ private DuplicateRequestedHostsComparer() {
+ }
+
+ /// <summary>
+ /// Gets the singleton instance of this comparer.
+ /// </summary>
+ internal static IEqualityComparer<IAuthenticationRequest> Instance {
+ get { return instance; }
+ }
+
+ #region IEqualityComparer<IAuthenticationRequest> Members
+
+ /// <summary>
+ /// Determines whether the specified objects are equal.
+ /// </summary>
+ /// <param name="x">The first object to compare.</param>
+ /// <param name="y">The second object to compare.</param>
+ /// <returns>
+ /// true if the specified objects are equal; otherwise, false.
+ /// </returns>
+ public bool Equals(IAuthenticationRequest x, IAuthenticationRequest y) {
+ if (x == null && y == null) {
+ return true;
+ }
+
+ if (x == null || y == null) {
+ return false;
+ }
+
+ // We'll distinguish based on the host name only, which
+ // admittedly is only a heuristic, but if we remove one that really wasn't a duplicate, well,
+ // this multiple OP attempt thing was just a convenience feature anyway.
+ return string.Equals(x.Provider.Uri.Host, y.Provider.Uri.Host, StringComparison.OrdinalIgnoreCase);
+ }
+
+ /// <summary>
+ /// Returns a hash code for the specified object.
+ /// </summary>
+ /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
+ /// <returns>A hash code for the specified object.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.
+ /// </exception>
+ public int GetHashCode(IAuthenticationRequest obj) {
+ return obj.Provider.Uri.Host.GetHashCode();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
index 3808c85..65db0bd 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
@@ -97,6 +97,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
IProviderEndpoint Provider { get; }
/// <summary>
+ /// Gets the discovery result leading to the formulation of this request.
+ /// </summary>
+ /// <value>The discovery result.</value>
+ IdentifierDiscoveryResult DiscoveryResult { get; }
+
+ /// <summary>
/// Makes a dictionary of key/value pairs available when the authentication is completed.
/// </summary>
/// <param name="arguments">The arguments to add to the request's return_to URI. Values must not be null.</param>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
index 41cc4e9..cd36cc7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
@@ -32,11 +32,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
Realm IAuthenticationRequest.Realm {
- get { throw new NotImplementedException(); }
+ get {
+ Contract.Ensures(Contract.Result<Realm>() != null);
+ throw new NotImplementedException();
+ }
}
Identifier IAuthenticationRequest.ClaimedIdentifier {
- get { throw new NotImplementedException(); }
+ get {
+ throw new NotImplementedException();
+ }
}
bool IAuthenticationRequest.IsDirectedIdentity {
@@ -54,7 +59,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
IProviderEndpoint IAuthenticationRequest.Provider {
- get { throw new NotImplementedException(); }
+ get {
+ Contract.Ensures(Contract.Result<IProviderEndpoint>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ IdentifierDiscoveryResult IAuthenticationRequest.DiscoveryResult {
+ get {
+ Contract.Ensures(Contract.Result<IdentifierDiscoveryResult>() != null);
+ throw new NotImplementedException();
+ }
}
void IAuthenticationRequest.AddCallbackArguments(IDictionary<string, string> arguments) {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IProviderEndpoint.cs
index a90ddd4..5d8918d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IProviderEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IProviderEndpoint.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
+ using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
@@ -30,6 +31,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets the URL that the OpenID Provider receives authentication requests at.
/// </summary>
+ /// <value>
+ /// This value MUST be an absolute HTTP or HTTPS URL.
+ /// </value>
Uri Uri { get; }
/// <summary>
@@ -45,6 +49,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "No parameter at all.")]
+ [Obsolete("Use IAuthenticationRequest.DiscoveryResult.IsExtensionSupported instead.")]
bool IsExtensionSupported<T>() where T : IOpenIdMessageExtension, new();
/// <summary>
@@ -59,6 +64,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The only way to be sure of support for a given extension is to include
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
+ [Obsolete("Use IAuthenticationRequest.DiscoveryResult.IsExtensionSupported instead.")]
bool IsExtensionSupported(Type extensionType);
}
@@ -67,20 +73,32 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
[ContractClassFor(typeof(IProviderEndpoint))]
internal abstract class IProviderEndpointContract : IProviderEndpoint {
+ /// <summary>
+ /// Prevents a default instance of the <see cref="IProviderEndpointContract"/> class from being created.
+ /// </summary>
+ private IProviderEndpointContract() {
+ }
+
#region IProviderEndpoint Members
/// <summary>
/// Gets the detected version of OpenID implemented by the Provider.
/// </summary>
Version IProviderEndpoint.Version {
- get { throw new NotImplementedException(); }
+ get {
+ Contract.Ensures(Contract.Result<Version>() != null);
+ throw new System.NotImplementedException();
+ }
}
/// <summary>
/// Gets the URL that the OpenID Provider receives authentication requests at.
/// </summary>
Uri IProviderEndpoint.Uri {
- get { throw new NotImplementedException(); }
+ get {
+ Contract.Ensures(Contract.Result<Uri>() != null);
+ throw new System.NotImplementedException();
+ }
}
/// <summary>
@@ -118,7 +136,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
bool IProviderEndpoint.IsExtensionSupported(Type extensionType) {
Contract.Requires<ArgumentNullException>(extensionType != null);
Contract.Requires<ArgumentException>(typeof(IOpenIdMessageExtension).IsAssignableFrom(extensionType));
- ////ErrorUtilities.VerifyArgument(typeof(IOpenIdMessageExtension).IsAssignableFrom(extensionType), string.Format(CultureInfo.CurrentCulture, OpenIdStrings.TypeMustImplementX, typeof(IOpenIdMessageExtension).FullName));
throw new NotImplementedException();
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpoint.cs
deleted file mode 100644
index 89b4ef0..0000000
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpoint.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="IXrdsProviderEndpoint.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId.RelyingParty {
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Diagnostics.Contracts;
-
- /// <summary>
- /// An <see cref="IProviderEndpoint"/> interface with additional members for use
- /// in sorting for most preferred endpoint.
- /// </summary>
- [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xrds", Justification = "Xrds is an acronym.")]
- [ContractClass(typeof(IXrdsProviderEndpointContract))]
- public interface IXrdsProviderEndpoint : IProviderEndpoint {
- /// <summary>
- /// Gets the priority associated with this service that may have been given
- /// in the XRDS document.
- /// </summary>
- int? ServicePriority { get; }
-
- /// <summary>
- /// Gets the priority associated with the service endpoint URL.
- /// </summary>
- /// <remarks>
- /// When sorting by priority, this property should be considered second after
- /// <see cref="ServicePriority"/>.
- /// </remarks>
- int? UriPriority { get; }
-
- /// <summary>
- /// Checks for the presence of a given Type URI in an XRDS service.
- /// </summary>
- /// <param name="typeUri">The type URI to check for.</param>
- /// <returns><c>true</c> if the service type uri is present; <c>false</c> otherwise.</returns>
- bool IsTypeUriPresent(string typeUri);
- }
-}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpointContract.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpointContract.cs
deleted file mode 100644
index e0e2b0b..0000000
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IXrdsProviderEndpointContract.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// <auto-generated />
-
-namespace DotNetOpenAuth.OpenId.RelyingParty {
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Diagnostics.Contracts;
- using System.Globalization;
- using DotNetOpenAuth.OpenId.Messages;
-
- [ContractClassFor(typeof(IXrdsProviderEndpoint))]
- internal abstract class IXrdsProviderEndpointContract : IXrdsProviderEndpoint {
- #region IXrdsProviderEndpoint Properties
-
- int? IXrdsProviderEndpoint.ServicePriority {
- get { throw new System.NotImplementedException(); }
- }
-
- int? IXrdsProviderEndpoint.UriPriority {
- get { throw new System.NotImplementedException(); }
- }
-
- #endregion
-
- #region IProviderEndpoint Properties
-
- Version IProviderEndpoint.Version {
- get { throw new System.NotImplementedException(); }
- }
-
- Uri IProviderEndpoint.Uri {
- get { throw new System.NotImplementedException(); }
- }
-
- #endregion
-
- #region IXrdsProviderEndpoint Methods
-
- bool IXrdsProviderEndpoint.IsTypeUriPresent(string typeUri) {
- throw new System.NotImplementedException();
- }
-
- #endregion
-
- #region IProviderEndpoint Methods
-
- bool IProviderEndpoint.IsExtensionSupported<T>() {
- throw new System.NotImplementedException();
- }
-
- bool IProviderEndpoint.IsExtensionSupported(System.Type extensionType) {
- Contract.Requires<ArgumentNullException>(extensionType != null);
- Contract.Requires<ArgumentException>(typeof(IOpenIdMessageExtension).IsAssignableFrom(extensionType));
- ////ErrorUtilities.VerifyArgument(typeof(IOpenIdMessageExtension).IsAssignableFrom(extensionType), string.Format(CultureInfo.CurrentCulture, OpenIdStrings.TypeMustImplementX, typeof(IOpenIdMessageExtension).FullName));
- throw new System.NotImplementedException();
- }
-
- #endregion
- }
-}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs
new file mode 100644
index 0000000..ae9fbdc
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxRelyingParty.cs
@@ -0,0 +1,238 @@
+//-----------------------------------------------------------------------
+// <copyright file="OpenIdAjaxRelyingParty.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Mime;
+ using System.Text;
+ using System.Web;
+ using System.Web.Script.Serialization;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions;
+ using DotNetOpenAuth.OpenId.Extensions.UI;
+
+ /// <summary>
+ /// Provides the programmatic facilities to act as an AJAX-enabled OpenID relying party.
+ /// </summary>
+ public class OpenIdAjaxRelyingParty : OpenIdRelyingParty {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdAjaxRelyingParty"/> class.
+ /// </summary>
+ public OpenIdAjaxRelyingParty() {
+ Reporting.RecordFeatureUse(this);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdAjaxRelyingParty"/> class.
+ /// </summary>
+ /// <param name="applicationStore">The application store. If <c>null</c>, the relying party will always operate in "dumb mode".</param>
+ public OpenIdAjaxRelyingParty(IRelyingPartyApplicationStore applicationStore)
+ : base(applicationStore) {
+ Reporting.RecordFeatureUse(this);
+ }
+
+ /// <summary>
+ /// Generates AJAX-ready authentication requests that can satisfy the requirements of some OpenID Identifier.
+ /// </summary>
+ /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param>
+ /// <param name="realm">The shorest URL that describes this relying party web site's address.
+ /// For example, if your login page is found at https://www.example.com/login.aspx,
+ /// your realm would typically be https://www.example.com/.</param>
+ /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication
+ /// responses from the OpenID Provider.</param>
+ /// <returns>
+ /// A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier.
+ /// Never null, but may be empty.
+ /// </returns>
+ /// <remarks>
+ /// <para>Any individual generated request can satisfy the authentication.
+ /// The generated requests are sorted in preferred order.
+ /// Each request is generated as it is enumerated to. Associations are created only as
+ /// <see cref="IAuthenticationRequest.RedirectingResponse"/> is called.</para>
+ /// <para>No exception is thrown if no OpenID endpoints were discovered.
+ /// An empty enumerable is returned instead.</para>
+ /// </remarks>
+ public override IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) {
+ var requests = base.CreateRequests(userSuppliedIdentifier, realm, returnToUrl);
+
+ // Alter the requests so that have AJAX characteristics.
+ // Some OPs may be listed multiple times (one with HTTPS and the other with HTTP, for example).
+ // Since we're gathering OPs to try one after the other, just take the first choice of each OP
+ // and don't try it multiple times.
+ requests = requests.Distinct(DuplicateRequestedHostsComparer.Instance);
+
+ // Configure each generated request.
+ int reqIndex = 0;
+ foreach (var req in requests) {
+ // Inform ourselves in return_to that we're in a popup.
+ req.SetUntrustedCallbackArgument(OpenIdRelyingPartyControlBase.UIPopupCallbackKey, "1");
+
+ if (req.DiscoveryResult.IsExtensionSupported<UIRequest>()) {
+ // Inform the OP that we'll be using a popup window consistent with the UI extension.
+ req.AddExtension(new UIRequest());
+
+ // Provide a hint for the client javascript about whether the OP supports the UI extension.
+ // This is so the window can be made the correct size for the extension.
+ // If the OP doesn't advertise support for the extension, the javascript will use
+ // a bigger popup window.
+ req.SetUntrustedCallbackArgument(OpenIdRelyingPartyControlBase.PopupUISupportedJSHint, "1");
+ }
+
+ req.SetUntrustedCallbackArgument("index", (reqIndex++).ToString(CultureInfo.InvariantCulture));
+
+ // If the ReturnToUrl was explicitly set, we'll need to reset our first parameter
+ if (string.IsNullOrEmpty(HttpUtility.ParseQueryString(req.ReturnToUrl.Query)[AuthenticationRequest.UserSuppliedIdentifierParameterName])) {
+ req.SetUntrustedCallbackArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName, userSuppliedIdentifier.OriginalString);
+ }
+
+ // Our javascript needs to let the user know which endpoint responded. So we force it here.
+ // This gives us the info even for 1.0 OPs and 2.0 setup_required responses.
+ req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.OPEndpointParameterName, req.Provider.Uri.AbsoluteUri);
+ req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.ClaimedIdParameterName, (string)req.ClaimedIdentifier ?? string.Empty);
+
+ // Inform ourselves in return_to that we're in a popup or iframe.
+ req.SetUntrustedCallbackArgument(OpenIdRelyingPartyAjaxControlBase.UIPopupCallbackKey, "1");
+
+ // We append a # at the end so that if the OP happens to support it,
+ // the OpenID response "query string" is appended after the hash rather than before, resulting in the
+ // browser being super-speedy in closing the popup window since it doesn't try to pull a newer version
+ // of the static resource down from the server merely because of a changed URL.
+ // http://www.nabble.com/Re:-Defining-how-OpenID-should-behave-with-fragments-in-the-return_to-url-p22694227.html
+ ////TODO:
+
+ yield return req;
+ }
+ }
+
+ /// <summary>
+ /// Serializes discovery results on some <i>single</i> identifier on behalf of Javascript running on the browser.
+ /// </summary>
+ /// <param name="requests">The discovery results from just <i>one</i> identifier to serialize as a JSON response.</param>
+ /// <returns>
+ /// The JSON result to return to the user agent.
+ /// </returns>
+ /// <remarks>
+ /// We prepare a JSON object with this interface:
+ /// <code>
+ /// class jsonResponse {
+ /// string claimedIdentifier;
+ /// Array requests; // never null
+ /// string error; // null if no error
+ /// }
+ /// </code>
+ /// Each element in the requests array looks like this:
+ /// <code>
+ /// class jsonAuthRequest {
+ /// string endpoint; // URL to the OP endpoint
+ /// string immediate; // URL to initiate an immediate request
+ /// string setup; // URL to initiate a setup request.
+ /// }
+ /// </code>
+ /// </remarks>
+ public OutgoingWebResponse AsAjaxDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) {
+ Contract.Requires<ArgumentNullException>(requests != null);
+
+ var serializer = new JavaScriptSerializer();
+ return new OutgoingWebResponse {
+ Body = serializer.Serialize(this.AsJsonDiscoveryResult(requests)),
+ };
+ }
+
+ /// <summary>
+ /// Serializes discovery on a set of identifiers for preloading into an HTML page that carries
+ /// an AJAX-aware OpenID control.
+ /// </summary>
+ /// <param name="requests">The discovery results to serialize as a JSON response.</param>
+ /// <returns>
+ /// The JSON result to return to the user agent.
+ /// </returns>
+ public string AsAjaxPreloadedDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) {
+ Contract.Requires<ArgumentNullException>(requests != null);
+
+ var serializer = new JavaScriptSerializer();
+ string json = serializer.Serialize(this.AsJsonPreloadedDiscoveryResult(requests));
+
+ string script = "window.dnoa_internal.loadPreloadedDiscoveryResults(" + json + ");";
+ return script;
+ }
+
+ /// <summary>
+ /// Converts a sequence of authentication requests to a JSON object for seeding an AJAX-enabled login page.
+ /// </summary>
+ /// <param name="requests">The discovery results from just <i>one</i> identifier to serialize as a JSON response.</param>
+ /// <returns>A JSON object, not yet serialized.</returns>
+ internal object AsJsonDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) {
+ Contract.Requires<ArgumentNullException>(requests != null);
+
+ requests = requests.CacheGeneratedResults();
+
+ if (requests.Any()) {
+ return new {
+ claimedIdentifier = (string)requests.First().ClaimedIdentifier,
+ requests = requests.Select(req => new {
+ endpoint = req.Provider.Uri.AbsoluteUri,
+ immediate = this.GetRedirectUrl(req, true),
+ setup = this.GetRedirectUrl(req, false),
+ }).ToArray()
+ };
+ } else {
+ return new {
+ requests = new object[0],
+ error = OpenIdStrings.OpenIdEndpointNotFound,
+ };
+ }
+ }
+
+ /// <summary>
+ /// Serializes discovery on a set of identifiers for preloading into an HTML page that carries
+ /// an AJAX-aware OpenID control.
+ /// </summary>
+ /// <param name="requests">The discovery results to serialize as a JSON response.</param>
+ /// <returns>
+ /// A JSON object, not yet serialized to a string.
+ /// </returns>
+ private object AsJsonPreloadedDiscoveryResult(IEnumerable<IAuthenticationRequest> requests) {
+ Contract.Requires<ArgumentNullException>(requests != null);
+
+ // We prepare a JSON object with this interface:
+ // Array discoveryWrappers;
+ // Where each element in the above array has this interface:
+ // class discoveryWrapper {
+ // string userSuppliedIdentifier;
+ // jsonResponse discoveryResult; // contains result of call to SerializeDiscoveryAsJson(Identifier)
+ // }
+ var json = (from request in requests
+ group request by request.DiscoveryResult.UserSuppliedIdentifier into requestsByIdentifier
+ select new {
+ userSuppliedIdentifier = (string)requestsByIdentifier.Key,
+ discoveryResult = this.AsJsonDiscoveryResult(requestsByIdentifier),
+ }).ToArray();
+
+ return json;
+ }
+
+ /// <summary>
+ /// Gets the full URL that carries an OpenID message, even if it exceeds the normal maximum size of a URL,
+ /// for purposes of sending to an AJAX component running in the browser.
+ /// </summary>
+ /// <param name="request">The authentication request.</param>
+ /// <param name="immediate"><c>true</c>to create a checkid_immediate request;
+ /// <c>false</c> to create a checkid_setup request.</param>
+ /// <returns>The absolute URL that carries the entire OpenID message.</returns>
+ private Uri GetRedirectUrl(IAuthenticationRequest request, bool immediate) {
+ Contract.Requires<ArgumentNullException>(request != null);
+
+ request.Mode = immediate ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup;
+ return request.RedirectingResponse.GetDirectUriRequest(this.Channel);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index 097d065..d80bf6a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -64,6 +64,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
internal const bool DownloadYahooUILibraryDefault = true;
+ /// <summary>
+ /// The default value for the <see cref="Throttle"/> property.
+ /// </summary>
+ internal const int ThrottleDefault = 3;
+
#region Property viewstate keys
/// <summary>
@@ -221,11 +226,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string AuthenticationFailedToolTipDefault = "Authentication failed.";
/// <summary>
- /// The default value for the <see cref="Throttle"/> property.
- /// </summary>
- private const int ThrottleDefault = 3;
-
- /// <summary>
/// The default value for the <see cref="LogOnText"/> property.
/// </summary>
private const string LogOnTextDefault = "LOG IN";
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
index f89ec0a..4aa78a5 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
@@ -643,11 +643,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
set {
base.UsePersistentCookie = value;
- // use conditional here to prevent infinite recursion
- // with CheckedChanged event.
- bool rememberMe = value != LogOnPersistence.Session;
- if (this.rememberMeCheckBox.Checked != rememberMe) {
- this.rememberMeCheckBox.Checked = rememberMe;
+ if (this.rememberMeCheckBox != null) {
+ // use conditional here to prevent infinite recursion
+ // with CheckedChanged event.
+ bool rememberMe = value != LogOnPersistence.Session;
+ if (this.rememberMeCheckBox.Checked != rememberMe) {
+ this.rememberMeCheckBox.Checked = rememberMe;
+ }
}
}
}
@@ -700,79 +702,104 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// top row, left cell
cell = new TableCell();
- this.label = new HtmlGenericControl("label");
- this.label.InnerText = LabelTextDefault;
- cell.Controls.Add(this.label);
- row1.Cells.Add(cell);
+ 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();
- cell.Controls.Add(new InPlaceControl(this));
- row1.Cells.Add(cell);
+ try {
+ cell.Controls.Add(new InPlaceControl(this));
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
// top row, right cell
cell = new TableCell();
- this.loginButton = new Button();
- this.loginButton.ID = "loginButton";
- this.loginButton.Text = ButtonTextDefault;
- this.loginButton.ToolTip = ButtonToolTipDefault;
- this.loginButton.Click += this.LoginButton_Click;
- this.loginButton.ValidationGroup = ValidationGroupDefault;
+ try {
+ this.loginButton = new Button();
+ this.loginButton.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);
+ cell.Controls.Add(this.loginButton);
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
// middle row, left cell
row2.Cells.Add(new TableCell());
// middle row, middle cell
cell = new TableCell();
- 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);
+ 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();
- 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);
+ 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();
@@ -780,17 +807,27 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// bottom row, middle cell
cell = new TableCell();
- this.rememberMeCheckBox = new CheckBox();
- this.rememberMeCheckBox.Text = RememberMeTextDefault;
- this.rememberMeCheckBox.Checked = RememberMeDefault;
- this.rememberMeCheckBox.Visible = RememberMeVisibleDefault;
- this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged;
- cell.Controls.Add(this.rememberMeCheckBox);
- row3.Cells.Add(cell);
+ 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();
- row3.Cells.Add(cell);
+ try {
+ row3.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
// this sets all the controls' tab indexes
this.TabIndex = TabIndexDefault;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
index dbf9530..8684bd1 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
@@ -762,13 +762,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
IRelyingPartyApplicationStore store = this.Stateless ? null :
(this.CustomApplicationStore ?? DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.ApplicationStore.CreateInstance(OpenIdRelyingParty.HttpApplicationStore));
var rp = new OpenIdRelyingParty(store);
-
- // Only set RequireSsl to true, as we don't want to override
- // a .config setting of true with false.
- if (this.RequireSsl) {
- rp.SecuritySettings.RequireSsl = true;
+ try {
+ // Only set RequireSsl to true, as we don't want to override
+ // a .config setting of true with false.
+ if (this.RequireSsl) {
+ rp.SecuritySettings.RequireSsl = true;
+ }
+ return rp;
+ } catch {
+ rp.Dispose();
+ throw;
}
- return rp;
}
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index 5e67d5b..a416f3a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -12,7 +12,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
+ using System.Globalization;
using System.Linq;
+ using System.Net;
+ using System.Net.Mime;
+ using System.Text;
using System.Web;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -30,13 +34,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <c>True</c> if the endpoint should be considered.
/// <c>False</c> to remove it from the pool of acceptable providers.
/// </returns>
- public delegate bool EndpointSelector(IXrdsProviderEndpoint endpoint);
+ public delegate bool EndpointSelector(IProviderEndpoint endpoint);
/// <summary>
- /// Provides the programmatic facilities to act as an OpenId consumer.
+ /// Provides the programmatic facilities to act as an OpenID relying party.
/// </summary>
[ContractVerification(true)]
- public sealed class OpenIdRelyingParty : IDisposable {
+ public class OpenIdRelyingParty : IDisposable {
/// <summary>
/// The name of the key to use in the HttpApplication cache to store the
/// instance of <see cref="StandardRelyingPartyApplicationStore"/> to use.
@@ -49,6 +53,27 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private readonly ObservableCollection<IRelyingPartyBehavior> behaviors = new ObservableCollection<IRelyingPartyBehavior>();
/// <summary>
+ /// Backing field for the <see cref="DiscoveryServices"/> property.
+ /// </summary>
+ private readonly IList<IIdentifierDiscoveryService> discoveryServices = new List<IIdentifierDiscoveryService>(2);
+
+ /// <summary>
+ /// Backing field for the <see cref="NonVerifyingRelyingParty"/> property.
+ /// </summary>
+ private OpenIdRelyingParty nonVerifyingRelyingParty;
+
+ /// <summary>
+ /// The lock to obtain when initializing the <see cref="nonVerifyingRelyingParty"/> member.
+ /// </summary>
+ private object nonVerifyingRelyingPartyInitLock = new object();
+
+ /// <summary>
+ /// A dictionary of extension response types and the javascript member
+ /// name to map them to on the user agent.
+ /// </summary>
+ private Dictionary<Type, string> clientScriptExtensions = new Dictionary<Type, string>();
+
+ /// <summary>
/// Backing field for the <see cref="SecuritySettings"/> property.
/// </summary>
private RelyingPartySecuritySettings securitySettings;
@@ -56,7 +81,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Backing store for the <see cref="EndpointOrder"/> property.
/// </summary>
- private Comparison<IXrdsProviderEndpoint> endpointOrder = DefaultEndpointOrder;
+ private Comparison<IdentifierDiscoveryResult> endpointOrder = DefaultEndpointOrder;
/// <summary>
/// Backing field for the <see cref="Channel"/> property.
@@ -73,7 +98,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingParty"/> class.
/// </summary>
- /// <param name="applicationStore">The application store. If null, the relying party will always operate in "dumb mode".</param>
+ /// <param name="applicationStore">The application store. If <c>null</c>, the relying party will always operate in "dumb mode".</param>
public OpenIdRelyingParty(IRelyingPartyApplicationStore applicationStore)
: this(applicationStore, applicationStore) {
}
@@ -90,6 +115,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Contract.Requires<ArgumentException>(associationStore == null || nonceStore != null, OpenIdStrings.AssociationStoreRequiresNonceStore);
this.securitySettings = DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.SecuritySettings.CreateSecuritySettings();
+
+ foreach (var discoveryService in DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.DiscoveryServices.CreateInstances(true)) {
+ this.discoveryServices.Add(discoveryService);
+ }
+
this.behaviors.CollectionChanged += this.OnBehaviorsChanged;
foreach (var behavior in DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.Behaviors.CreateInstances(false)) {
this.behaviors.Add(behavior);
@@ -98,11 +128,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Without a nonce store, we must rely on the Provider to protect against
// replay attacks. But only 2.0+ Providers can be expected to provide
// replay protection.
- if (nonceStore == null) {
- if (this.SecuritySettings.MinimumRequiredOpenIdVersion < ProtocolVersion.V20) {
- Logger.OpenId.Warn("Raising minimum OpenID version requirement for Providers to 2.0 to protect this stateless RP from replay attacks.");
- this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
- }
+ if (nonceStore == null &&
+ this.SecuritySettings.ProtectDownlevelReplayAttacks &&
+ this.SecuritySettings.MinimumRequiredOpenIdVersion < ProtocolVersion.V20) {
+ Logger.OpenId.Warn("Raising minimum OpenID version requirement for Providers to 2.0 to protect this stateless RP from replay attacks.");
+ this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20;
}
this.channel = new OpenIdChannel(associationStore, nonceStore, this.SecuritySettings);
@@ -119,8 +149,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Endpoints lacking any priority value are sorted to the end of the list.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Advanced)]
- public static Comparison<IXrdsProviderEndpoint> DefaultEndpointOrder {
- get { return ServiceEndpoint.EndpointOrder; }
+ public static Comparison<IdentifierDiscoveryResult> DefaultEndpointOrder {
+ get { return IdentifierDiscoveryResult.EndpointOrder; }
}
/// <summary>
@@ -202,7 +232,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// can be set to the value of <see cref="DefaultEndpointOrder"/>.
/// </remarks>
[EditorBrowsable(EditorBrowsableState.Advanced)]
- public Comparison<IXrdsProviderEndpoint> EndpointOrder {
+ public Comparison<IdentifierDiscoveryResult> EndpointOrder {
get {
return this.endpointOrder;
}
@@ -232,6 +262,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets the list of services that can perform discovery on identifiers given to this relying party.
+ /// </summary>
+ public IList<IIdentifierDiscoveryService> DiscoveryServices {
+ get { return this.discoveryServices; }
+ }
+
+ /// <summary>
/// Gets a value indicating whether this Relying Party can sign its return_to
/// parameter in outgoing authentication requests.
/// </summary>
@@ -253,6 +290,24 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
internal AssociationManager AssociationManager { get; private set; }
/// <summary>
+ /// Gets the <see cref="OpenIdRelyingParty"/> instance used to process authentication responses
+ /// without verifying the assertion or consuming nonces.
+ /// </summary>
+ protected OpenIdRelyingParty NonVerifyingRelyingParty {
+ get {
+ if (this.nonVerifyingRelyingParty == null) {
+ lock (this.nonVerifyingRelyingPartyInitLock) {
+ if (this.nonVerifyingRelyingParty == null) {
+ this.nonVerifyingRelyingParty = OpenIdRelyingParty.CreateNonVerifying();
+ }
+ }
+ }
+
+ return this.nonVerifyingRelyingParty;
+ }
+ }
+
+ /// <summary>
/// Creates an authentication request to verify that a user controls
/// some given Identifier.
/// </summary>
@@ -372,13 +427,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>No exception is thrown if no OpenID endpoints were discovered.
/// An empty enumerable is returned instead.</para>
/// </remarks>
- public IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) {
+ public virtual IEnumerable<IAuthenticationRequest> CreateRequests(Identifier userSuppliedIdentifier, Realm realm, Uri returnToUrl) {
Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
Contract.Requires<ArgumentNullException>(realm != null);
Contract.Requires<ArgumentNullException>(returnToUrl != null);
Contract.Ensures(Contract.Result<IEnumerable<IAuthenticationRequest>>() != null);
- return AuthenticationRequest.Create(userSuppliedIdentifier, this, realm, returnToUrl, true).Cast<IAuthenticationRequest>();
+ return AuthenticationRequest.Create(userSuppliedIdentifier, this, realm, returnToUrl, true).Cast<IAuthenticationRequest>().CacheGeneratedResults();
}
/// <summary>
@@ -459,21 +514,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
Contract.Ensures(Contract.Result<IEnumerable<IAuthenticationRequest>>() != null);
- // Build the realm URL
- UriBuilder realmUrl = new UriBuilder(this.Channel.GetRequestFromContext().UrlBeforeRewriting);
- realmUrl.Path = HttpContext.Current.Request.ApplicationPath;
- realmUrl.Query = null;
- realmUrl.Fragment = null;
-
- // For RP discovery, the realm url MUST NOT redirect. To prevent this for
- // virtual directory hosted apps, we need to make sure that the realm path ends
- // in a slash (since our calculation above guarantees it doesn't end in a specific
- // page like default.aspx).
- if (!realmUrl.Path.EndsWith("/", StringComparison.Ordinal)) {
- realmUrl.Path += "/";
- }
-
- return this.CreateRequests(userSuppliedIdentifier, new Realm(realmUrl.Uri));
+ return this.CreateRequests(userSuppliedIdentifier, Realm.AutoDetect);
}
/// <summary>
@@ -484,6 +525,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
/// </remarks>
public IAuthenticationResponse GetResponse() {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
return this.GetResponse(this.Channel.GetRequestFromContext());
}
@@ -530,6 +572,52 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
+ /// <summary>
+ /// Processes the response received in a popup window or iframe to an AJAX-directed OpenID authentication.
+ /// </summary>
+ /// <returns>The HTTP response to send to this HTTP request.</returns>
+ /// <remarks>
+ /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
+ /// </remarks>
+ public OutgoingWebResponse ProcessResponseFromPopup() {
+ Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
+ Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
+
+ return this.ProcessResponseFromPopup(this.Channel.GetRequestFromContext());
+ }
+
+ /// <summary>
+ /// Processes the response received in a popup window or iframe to an AJAX-directed OpenID authentication.
+ /// </summary>
+ /// <param name="request">The incoming HTTP request that is expected to carry an OpenID authentication response.</param>
+ /// <returns>The HTTP response to send to this HTTP request.</returns>
+ public OutgoingWebResponse ProcessResponseFromPopup(HttpRequestInfo request) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
+
+ return this.ProcessResponseFromPopup(request, null);
+ }
+
+ /// <summary>
+ /// Allows an OpenID extension to read data out of an unverified positive authentication assertion
+ /// and send it down to the client browser so that Javascript running on the page can perform
+ /// some preprocessing on the extension data.
+ /// </summary>
+ /// <typeparam name="T">The extension <i>response</i> type that will read data from the assertion.</typeparam>
+ /// <param name="propertyName">The property name on the openid_identifier input box object that will be used to store the extension data. For example: sreg</param>
+ /// <remarks>
+ /// This method should be called before <see cref="ProcessResponseFromPopup()"/>.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "By design")]
+ public void RegisterClientScriptExtension<T>(string propertyName) where T : IClientScriptExtensionResponse {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(propertyName));
+ ErrorUtilities.VerifyArgumentNamed(!this.clientScriptExtensions.ContainsValue(propertyName), "propertyName", OpenIdStrings.ClientScriptExtensionPropertyNameCollision, propertyName);
+ foreach (var ext in this.clientScriptExtensions.Keys) {
+ ErrorUtilities.VerifyArgument(ext != typeof(T), OpenIdStrings.ClientScriptExtensionTypeCollision, typeof(T).FullName);
+ }
+ this.clientScriptExtensions.Add(typeof(T), propertyName);
+ }
+
#region IDisposable Members
/// <summary>
@@ -577,11 +665,112 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Processes the response received in a popup window or iframe to an AJAX-directed OpenID authentication.
+ /// </summary>
+ /// <param name="request">The incoming HTTP request that is expected to carry an OpenID authentication response.</param>
+ /// <param name="callback">The callback fired after the response status has been determined but before the Javascript response is formulated.</param>
+ /// <returns>
+ /// The HTTP response to send to this HTTP request.
+ /// </returns>
+ 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.");
+
+ // Give the caller a chance to notify the hosting page and fill up the clientScriptExtensions collection.
+ if (callback != null) {
+ callback(authResponse.Status);
+ }
+
+ Logger.OpenId.DebugFormat("Popup or iframe callback from OP: {0}", request.Url);
+ Logger.Controls.DebugFormat(
+ "An authentication response was found in a popup window or iframe using a non-verifying RP with status: {0}",
+ authResponse.Status);
+ if (authResponse.Status == AuthenticationStatus.Authenticated) {
+ var extensionsDictionary = new Dictionary<string, string>();
+ foreach (var pair in this.clientScriptExtensions) {
+ IClientScriptExtensionResponse extension = (IClientScriptExtensionResponse)authResponse.GetExtension(pair.Key);
+ if (extension == null) {
+ continue;
+ }
+ var positiveResponse = (PositiveAuthenticationResponse)authResponse;
+ string js = extension.InitializeJavaScriptData(positiveResponse.Response);
+ if (!string.IsNullOrEmpty(js)) {
+ extensionsDictionary[pair.Value] = js;
+ }
+ }
+
+ extensionsJson = MessagingUtilities.CreateJsonObject(extensionsDictionary, true);
+ }
+
+ string payload = "document.URL";
+ if (request.HttpMethod == "POST") {
+ // Promote all form variables to the query string, but since it won't be passed
+ // to any server (this is a javascript window-to-window transfer) the length of
+ // it can be arbitrarily long, whereas it was POSTed here probably because it
+ // was too long for HTTP transit.
+ UriBuilder payloadUri = new UriBuilder(request.Url);
+ payloadUri.AppendQueryArgs(request.Form.ToDictionary());
+ payload = MessagingUtilities.GetSafeJavascriptValue(payloadUri.Uri.AbsoluteUri);
+ }
+
+ if (!string.IsNullOrEmpty(extensionsJson)) {
+ payload += ", " + extensionsJson;
+ }
+
+ return InvokeParentPageScript("dnoa_internal.processAuthorizationResult(" + payload + ")");
+ }
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to discover services for.</param>
+ /// <returns>A non-null sequence of services discovered for the identifier.</returns>
+ internal IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Ensures(Contract.Result<IEnumerable<IdentifierDiscoveryResult>>() != null);
+
+ IEnumerable<IdentifierDiscoveryResult> results = Enumerable.Empty<IdentifierDiscoveryResult>();
+ foreach (var discoverer in this.DiscoveryServices) {
+ bool abortDiscoveryChain;
+ var discoveryResults = discoverer.Discover(identifier, this.WebRequestHandler, out abortDiscoveryChain).CacheGeneratedResults();
+ results = results.Concat(discoveryResults);
+ if (abortDiscoveryChain) {
+ Logger.OpenId.InfoFormat("Further discovery on '{0}' was stopped by the {1} discovery service.", identifier, discoverer.GetType().Name);
+ break;
+ }
+ }
+
+ // If any OP Identifier service elements were found, we must not proceed
+ // to use any Claimed Identifier services, per OpenID 2.0 sections 7.3.2.2 and 11.2.
+ // For a discussion on this topic, see
+ // http://groups.google.com/group/dotnetopenid/browse_thread/thread/4b5a8c6b2210f387/5e25910e4d2252c8
+ // Sometimes the IIdentifierDiscoveryService will automatically filter this for us, but
+ // just to be sure, we'll do it here as well.
+ if (!this.SecuritySettings.AllowDualPurposeIdentifiers) {
+ results = results.CacheGeneratedResults(); // avoid performing discovery repeatedly
+ var opIdentifiers = results.Where(result => result.ClaimedIdentifier == result.Protocol.ClaimedIdentifierForOPIdentifier);
+ var claimedIdentifiers = results.Where(result => result.ClaimedIdentifier != result.Protocol.ClaimedIdentifierForOPIdentifier);
+ results = opIdentifiers.Any() ? opIdentifiers : claimedIdentifiers;
+ }
+
+ return results;
+ }
+
+ /// <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>
- private void Dispose(bool disposing) {
+ protected virtual void Dispose(bool disposing) {
if (disposing) {
+ if (this.nonVerifyingRelyingParty != null) {
+ this.nonVerifyingRelyingParty.Dispose();
+ this.nonVerifyingRelyingParty = null;
+ }
+
// Tear off the instance member as a local variable for thread safety.
IDisposable disposableChannel = this.channel as IDisposable;
if (disposableChannel != null) {
@@ -591,6 +780,42 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Invokes a method on a parent frame or window and closes the calling popup window if applicable.
+ /// </summary>
+ /// <param name="methodCall">The method to call on the parent window, including
+ /// parameters. (i.e. "callback('arg1', 2)"). No escaping is done by this method.</param>
+ /// <returns>The entire HTTP response to send to the popup window or iframe to perform the invocation.</returns>
+ private static OutgoingWebResponse InvokeParentPageScript(string methodCall) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(methodCall));
+
+ Logger.OpenId.DebugFormat("Sending Javascript callback: {0}", methodCall);
+ StringBuilder builder = new StringBuilder();
+ builder.AppendLine("<html><body><script type='text/javascript' language='javascript'><!--");
+ builder.AppendLine("//<![CDATA[");
+ builder.Append(@" var inPopup = !window.frameElement;
+ var objSrc = inPopup ? window.opener : window.frameElement;
+");
+
+ // Something about calling objSrc.{0} can somehow cause FireFox to forget about the inPopup variable,
+ // so we have to actually put the test for it ABOVE the call to objSrc.{0} so that it already
+ // whether to call window.self.close() after the call.
+ string htmlFormat = @" if (inPopup) {{
+ objSrc.{0};
+ window.self.close();
+ }} else {{
+ objSrc.{0};
+ }}";
+ builder.AppendFormat(CultureInfo.InvariantCulture, htmlFormat, methodCall);
+ builder.AppendLine("//]]>--></script>");
+ builder.AppendLine("</body></html>");
+
+ var response = new OutgoingWebResponse();
+ response.Body = builder.ToString();
+ response.Headers.Add(HttpResponseHeader.ContentType, new ContentType("text/html").ToString());
+ return response;
+ }
+
+ /// <summary>
/// Called by derived classes when behaviors are added or removed.
/// </summary>
/// <param name="sender">The collection being modified.</param>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
index 0254346..f22645f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
@@ -16,6 +16,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Linq;
using System.Text;
using System.Web;
+ using System.Web.Script.Serialization;
using System.Web.UI;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -31,30 +32,30 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
internal const string EmbeddedAjaxJavascriptResource = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase.js";
/// <summary>
- /// The name of the javascript function that will initiate a synchronous callback.
+ /// The "dnoa.op_endpoint" string.
/// </summary>
- protected const string CallbackJSFunction = "window.dnoa_internal.callback";
+ internal const string OPEndpointParameterName = OpenIdUtilities.CustomParameterPrefix + "op_endpoint";
/// <summary>
- /// The name of the javascript function that will initiate an asynchronous callback.
+ /// The "dnoa.claimed_id" string.
/// </summary>
- protected const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync";
+ internal const string ClaimedIdParameterName = OpenIdUtilities.CustomParameterPrefix + "claimed_id";
/// <summary>
/// The name of the javascript field that stores the maximum time a positive assertion is
/// good for before it must be refreshed.
/// </summary>
- private const string MaxPositiveAssertionLifetimeJsName = "window.dnoa_internal.maxPositiveAssertionLifetime";
+ internal const string MaxPositiveAssertionLifetimeJsName = "window.dnoa_internal.maxPositiveAssertionLifetime";
/// <summary>
- /// The "dnoa.op_endpoint" string.
+ /// The name of the javascript function that will initiate an asynchronous callback.
/// </summary>
- private const string OPEndpointParameterName = OpenIdUtilities.CustomParameterPrefix + "op_endpoint";
+ protected internal const string CallbackJSFunctionAsync = "window.dnoa_internal.callbackAsync";
/// <summary>
- /// The "dnoa.claimed_id" string.
+ /// The name of the javascript function that will initiate a synchronous callback.
/// </summary>
- private const string ClaimedIdParameterName = OpenIdUtilities.CustomParameterPrefix + "claimed_id";
+ protected const string CallbackJSFunction = "window.dnoa_internal.callback";
#region Property viewstate keys
@@ -86,11 +87,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const LogOnSiteNotification LogOnModeDefault = LogOnSiteNotification.None;
/// <summary>
- /// Backing field for the <see cref="RelyingPartyNonVerifying"/> property.
- /// </summary>
- private static OpenIdRelyingParty relyingPartyNonVerifying;
-
- /// <summary>
/// The authentication response that just came in.
/// </summary>
private IAuthenticationResponse authenticationResponse;
@@ -102,12 +98,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private string discoveryResult;
/// <summary>
- /// A dictionary of extension response types and the javascript member
- /// name to map them to on the user agent.
- /// </summary>
- private Dictionary<Type, string> clientScriptExtensions = new Dictionary<Type, string>();
-
- /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartyAjaxControlBase"/> class.
/// </summary>
protected OpenIdRelyingPartyAjaxControlBase() {
@@ -152,6 +142,31 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use.
+ /// </summary>
+ /// <value>
+ /// The default value is an <see cref="OpenIdRelyingParty"/> instance initialized according to the web.config file.
+ /// </value>
+ /// <remarks>
+ /// A performance optimization would be to store off the
+ /// instance as a static member in your web site and set it
+ /// to this property in your <see cref="Control.Load">Page.Load</see>
+ /// event since instantiating these instances can be expensive on
+ /// heavily trafficked web pages.
+ /// </remarks>
+ public override OpenIdRelyingParty RelyingParty {
+ get {
+ return base.RelyingParty;
+ }
+
+ set {
+ // Make sure we get an AJAX-ready instance.
+ ErrorUtilities.VerifyArgument(value is OpenIdAjaxRelyingParty, OpenIdStrings.TypeMustImplementX, typeof(OpenIdAjaxRelyingParty).Name);
+ base.RelyingParty = value;
+ }
+ }
+
+ /// <summary>
/// Gets the completed authentication response.
/// </summary>
public IAuthenticationResponse AuthenticationResponse {
@@ -193,22 +208,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Gets the name of the open id auth data form key (for the value as stored at the user agent as a FORM field).
+ /// Gets the relying party as its AJAX type.
/// </summary>
- /// <value>Usually a concatenation of the control's name and <c>"_openidAuthData"</c>.</value>
- protected abstract string OpenIdAuthDataFormKey { get; }
+ protected OpenIdAjaxRelyingParty AjaxRelyingParty {
+ get { return (OpenIdAjaxRelyingParty)this.RelyingParty; }
+ }
/// <summary>
- /// Gets the relying party to use when verification of incoming messages is NOT wanted.
+ /// Gets the name of the open id auth data form key (for the value as stored at the user agent as a FORM field).
/// </summary>
- private static OpenIdRelyingParty RelyingPartyNonVerifying {
- get {
- if (relyingPartyNonVerifying == null) {
- relyingPartyNonVerifying = OpenIdRelyingParty.CreateNonVerifying();
- }
- return relyingPartyNonVerifying;
- }
- }
+ /// <value>Usually a concatenation of the control's name and <c>"_openidAuthData"</c>.</value>
+ protected abstract string OpenIdAuthDataFormKey { get; }
/// <summary>
/// Gets or sets a value indicating whether an authentication in the page's view state
@@ -232,11 +242,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "By design")]
public void RegisterClientScriptExtension<T>(string propertyName) where T : IClientScriptExtensionResponse {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(propertyName));
- ErrorUtilities.VerifyArgumentNamed(!this.clientScriptExtensions.ContainsValue(propertyName), "propertyName", OpenIdStrings.ClientScriptExtensionPropertyNameCollision, propertyName);
- foreach (var ext in this.clientScriptExtensions.Keys) {
- ErrorUtilities.VerifyArgument(ext != typeof(T), OpenIdStrings.ClientScriptExtensionTypeCollision, typeof(T).FullName);
- }
- this.clientScriptExtensions.Add(typeof(T), propertyName);
+ this.RelyingParty.RegisterClientScriptExtension<T>(propertyName);
}
#region ICallbackEventHandler Members
@@ -263,27 +269,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
- /// Creates the authentication requests for a given user-supplied Identifier.
- /// </summary>
- /// <param name="identifier">The identifier to create a request for.</param>
- /// <returns>
- /// A sequence of authentication requests, any one of which may be
- /// used to determine the user's control of the <see cref="IAuthenticationRequest.ClaimedIdentifier"/>.
- /// </returns>
- protected internal override IEnumerable<IAuthenticationRequest> CreateRequests(Identifier identifier) {
- // If this control is actually a member of another OpenID RP control,
- // delegate creation of requests to the parent control.
- var parentOwner = this.ParentControls.OfType<OpenIdRelyingPartyControlBase>().FirstOrDefault();
- if (parentOwner != null) {
- return parentOwner.CreateRequests(identifier);
- } else {
- // We delegate all our logic to another method, since invoking base. methods
- // within an iterator method results in unverifiable code.
- return this.CreateRequestsCore(base.CreateRequests(identifier));
- }
- }
-
- /// <summary>
/// Returns the results of a callback event that targets a control.
/// </summary>
/// <returns>The result of the callback.</returns>
@@ -305,7 +290,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Logger.OpenId.InfoFormat("AJAX discovery on {0} requested.", userSuppliedIdentifier);
this.Identifier = userSuppliedIdentifier;
- this.discoveryResult = this.SerializeDiscoveryAsJson(this.Identifier);
+
+ var serializer = new JavaScriptSerializer();
+ IEnumerable<IAuthenticationRequest> requests = this.CreateRequests(this.Identifier);
+ this.discoveryResult = serializer.Serialize(this.AjaxRelyingParty.AsJsonDiscoveryResult(requests));
+ }
+
+ /// <summary>
+ /// Creates the relying party instance used to generate authentication requests.
+ /// </summary>
+ /// <param name="store">The store to pass to the relying party constructor.</param>
+ /// <returns>The instantiated relying party.</returns>
+ protected override OpenIdRelyingParty CreateRelyingParty(IRelyingPartyApplicationStore store) {
+ return new OpenIdAjaxRelyingParty(store);
}
/// <summary>
@@ -323,8 +320,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="identifiers">The identifiers to perform discovery on.</param>
protected void PreloadDiscovery(IEnumerable<Identifier> identifiers) {
- string discoveryResults = this.SerializeDiscoveryAsJson(identifiers);
- string script = "window.dnoa_internal.loadPreloadedDiscoveryResults(" + discoveryResults + ");";
+ string script = this.AjaxRelyingParty.AsAjaxPreloadedDiscoveryResult(
+ identifiers.SelectMany(id => this.CreateRequests(id)));
this.Page.ClientScript.RegisterClientScriptBlock(typeof(OpenIdRelyingPartyAjaxControlBase), this.ClientID, script, true);
}
@@ -402,6 +399,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
protected override void Render(HtmlTextWriter writer) {
+ Contract.Assume(writer != null, "Missing contract.");
base.Render(writer);
// Emit a hidden field to let the javascript on the user agent know if an
@@ -420,172 +418,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Notifies the user agent via an AJAX response of a completed authentication attempt.
/// </summary>
protected override void ScriptClosingPopupOrIFrame() {
- Logger.OpenId.DebugFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
- string extensionsJson = null;
-
- var authResponse = RelyingPartyNonVerifying.GetResponse();
- Logger.Controls.DebugFormat(
- "The {0} control checked for an authentication response from a popup window or iframe using a non-verifying RP and found: {1}",
- this.ID,
- authResponse.Status);
- if (authResponse.Status == AuthenticationStatus.Authenticated) {
- this.OnUnconfirmedPositiveAssertion(); // event handler will fill the clientScriptExtensions collection.
- var extensionsDictionary = new Dictionary<string, string>();
- foreach (var pair in this.clientScriptExtensions) {
- IClientScriptExtensionResponse extension = (IClientScriptExtensionResponse)authResponse.GetExtension(pair.Key);
- if (extension == null) {
- continue;
- }
- var positiveResponse = (PositiveAuthenticationResponse)authResponse;
- string js = extension.InitializeJavaScriptData(positiveResponse.Response);
- if (!string.IsNullOrEmpty(js)) {
- extensionsDictionary[pair.Value] = js;
- }
+ Action<AuthenticationStatus> callback = status => {
+ if (status == AuthenticationStatus.Authenticated) {
+ this.OnUnconfirmedPositiveAssertion(); // event handler will fill the clientScriptExtensions collection.
}
+ };
- extensionsJson = MessagingUtilities.CreateJsonObject(extensionsDictionary, true);
- }
-
- string payload = "document.URL";
- if (Page.Request.HttpMethod == "POST") {
- // Promote all form variables to the query string, but since it won't be passed
- // to any server (this is a javascript window-to-window transfer) the length of
- // it can be arbitrarily long, whereas it was POSTed here probably because it
- // was too long for HTTP transit.
- UriBuilder payloadUri = new UriBuilder(Page.Request.Url);
- payloadUri.AppendQueryArgs(Page.Request.Form.ToDictionary());
- payload = MessagingUtilities.GetSafeJavascriptValue(payloadUri.Uri.AbsoluteUri);
- }
-
- if (!string.IsNullOrEmpty(extensionsJson)) {
- payload += ", " + extensionsJson;
- }
-
- this.CallbackUserAgentMethod("dnoa_internal.processAuthorizationResult(" + payload + ")");
- }
-
- /// <summary>
- /// Serializes the discovery of multiple identifiers as a JSON object.
- /// </summary>
- /// <param name="identifiers">The identifiers to perform discovery on and create requests for.</param>
- /// <returns>The serialized JSON object.</returns>
- private string SerializeDiscoveryAsJson(IEnumerable<Identifier> identifiers) {
- ErrorUtilities.VerifyArgumentNotNull(identifiers, "identifiers");
-
- // We prepare a JSON object with this interface:
- // Array discoveryWrappers;
- // Where each element in the above array has this interface:
- // class discoveryWrapper {
- // string userSuppliedIdentifier;
- // jsonResponse discoveryResult; // contains result of call to SerializeDiscoveryAsJson(Identifier)
- // }
- StringBuilder discoveryResultBuilder = new StringBuilder();
- discoveryResultBuilder.Append("[");
- foreach (var identifier in identifiers) { // TODO: parallelize discovery on these identifiers
- discoveryResultBuilder.Append("{");
- discoveryResultBuilder.AppendFormat("userSuppliedIdentifier: {0},", MessagingUtilities.GetSafeJavascriptValue(identifier));
- discoveryResultBuilder.AppendFormat("discoveryResult: {0}", this.SerializeDiscoveryAsJson(identifier));
- discoveryResultBuilder.Append("},");
- }
-
- discoveryResultBuilder.Length -= 1; // trim last comma
- discoveryResultBuilder.Append("]");
- return discoveryResultBuilder.ToString();
- }
-
- /// <summary>
- /// Serializes the results of discovery and the created auth requests as a JSON object
- /// for the user agent to initiate.
- /// </summary>
- /// <param name="identifier">The identifier to perform discovery on.</param>
- /// <returns>The JSON string.</returns>
- private string SerializeDiscoveryAsJson(Identifier identifier) {
- ErrorUtilities.VerifyArgumentNotNull(identifier, "identifier");
-
- // We prepare a JSON object with this interface:
- // class jsonResponse {
- // string claimedIdentifier;
- // Array requests; // never null
- // string error; // null if no error
- // }
- // Each element in the requests array looks like this:
- // class jsonAuthRequest {
- // string endpoint; // URL to the OP endpoint
- // string immediate; // URL to initiate an immediate request
- // string setup; // URL to initiate a setup request.
- // }
- StringBuilder discoveryResultBuilder = new StringBuilder();
- discoveryResultBuilder.Append("{");
- try {
- IEnumerable<IAuthenticationRequest> requests = this.CreateRequests(identifier).CacheGeneratedResults();
- if (requests.Any()) {
- discoveryResultBuilder.AppendFormat("claimedIdentifier: {0},", MessagingUtilities.GetSafeJavascriptValue(requests.First().ClaimedIdentifier));
- discoveryResultBuilder.Append("requests: [");
- foreach (IAuthenticationRequest request in requests) {
- discoveryResultBuilder.Append("{");
- discoveryResultBuilder.AppendFormat("endpoint: {0},", MessagingUtilities.GetSafeJavascriptValue(request.Provider.Uri.AbsoluteUri));
- request.Mode = AuthenticationRequestMode.Immediate;
- OutgoingWebResponse response = request.RedirectingResponse;
- discoveryResultBuilder.AppendFormat("immediate: {0},", MessagingUtilities.GetSafeJavascriptValue(response.GetDirectUriRequest(this.RelyingParty.Channel).AbsoluteUri));
- request.Mode = AuthenticationRequestMode.Setup;
- response = request.RedirectingResponse;
- discoveryResultBuilder.AppendFormat("setup: {0}", MessagingUtilities.GetSafeJavascriptValue(response.GetDirectUriRequest(this.RelyingParty.Channel).AbsoluteUri));
- discoveryResultBuilder.Append("},");
- }
- discoveryResultBuilder.Length -= 1; // trim off last comma
- discoveryResultBuilder.Append("]");
- } else {
- discoveryResultBuilder.Append("requests: [],");
- discoveryResultBuilder.AppendFormat("error: {0}", MessagingUtilities.GetSafeJavascriptValue(OpenIdStrings.OpenIdEndpointNotFound));
- }
- } catch (ProtocolException ex) {
- discoveryResultBuilder.Append("requests: [],");
- discoveryResultBuilder.AppendFormat("error: {0}", MessagingUtilities.GetSafeJavascriptValue(ex.Message));
- }
-
- discoveryResultBuilder.Append("}");
- return discoveryResultBuilder.ToString();
- }
-
- /// <summary>
- /// Creates the authentication requests for a given user-supplied Identifier.
- /// </summary>
- /// <param name="requests">The authentication requests to prepare.</param>
- /// <returns>
- /// A sequence of authentication requests, any one of which may be
- /// used to determine the user's control of the <see cref="IAuthenticationRequest.ClaimedIdentifier"/>.
- /// </returns>
- private IEnumerable<IAuthenticationRequest> CreateRequestsCore(IEnumerable<IAuthenticationRequest> requests) {
- ErrorUtilities.VerifyArgumentNotNull(requests, "requests"); // NO CODE CONTRACTS! (yield return used here)
-
- // Configure each generated request.
- int reqIndex = 0;
- foreach (var req in requests) {
- req.SetUntrustedCallbackArgument("index", (reqIndex++).ToString(CultureInfo.InvariantCulture));
-
- // If the ReturnToUrl was explicitly set, we'll need to reset our first parameter
- if (string.IsNullOrEmpty(HttpUtility.ParseQueryString(req.ReturnToUrl.Query)[AuthenticationRequest.UserSuppliedIdentifierParameterName])) {
- Identifier userSuppliedIdentifier = ((AuthenticationRequest)req).Endpoint.UserSuppliedIdentifier;
- req.SetUntrustedCallbackArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName, userSuppliedIdentifier.OriginalString);
- }
-
- // Our javascript needs to let the user know which endpoint responded. So we force it here.
- // This gives us the info even for 1.0 OPs and 2.0 setup_required responses.
- req.SetUntrustedCallbackArgument(OPEndpointParameterName, req.Provider.Uri.AbsoluteUri);
- req.SetUntrustedCallbackArgument(ClaimedIdParameterName, (string)req.ClaimedIdentifier ?? string.Empty);
-
- // Inform ourselves in return_to that we're in a popup or iframe.
- req.SetUntrustedCallbackArgument(UIPopupCallbackKey, "1");
-
- // We append a # at the end so that if the OP happens to support it,
- // the OpenID response "query string" is appended after the hash rather than before, resulting in the
- // browser being super-speedy in closing the popup window since it doesn't try to pull a newer version
- // of the static resource down from the server merely because of a changed URL.
- // http://www.nabble.com/Re:-Defining-how-OpenID-should-behave-with-fragments-in-the-return_to-url-p22694227.html
- ////TODO:
+ OutgoingWebResponse response = this.RelyingParty.ProcessResponseFromPopup(
+ this.RelyingParty.Channel.GetRequestFromContext(),
+ callback);
- yield return req;
- }
+ response.Send();
}
/// <summary>
@@ -615,33 +458,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Invokes a method on a parent frame/window's OpenIdAjaxTextBox,
- /// and closes the calling popup window if applicable.
- /// </summary>
- /// <param name="methodCall">The method to call on the OpenIdAjaxTextBox, including
- /// parameters. (i.e. "callback('arg1', 2)"). No escaping is done by this method.</param>
- private void CallbackUserAgentMethod(string methodCall) {
- Logger.OpenId.DebugFormat("Sending Javascript callback: {0}", methodCall);
- Page.Response.Write(@"<html><body><script language='javascript'>
- var inPopup = !window.frameElement;
- var objSrc = inPopup ? window.opener : window.frameElement;
-");
-
- // Something about calling objSrc.{0} can somehow cause FireFox to forget about the inPopup variable,
- // so we have to actually put the test for it ABOVE the call to objSrc.{0} so that it already
- // whether to call window.self.close() after the call.
- string htmlFormat = @" if (inPopup) {{
- objSrc.{0};
- window.self.close();
- }} else {{
- objSrc.{0};
- }}
-</script></body></html>";
- Page.Response.Write(string.Format(CultureInfo.InvariantCulture, htmlFormat, methodCall));
- Page.Response.End();
- }
-
- /// <summary>
/// Sets the window.aspnetapppath variable on the user agent so that cookies can be set with the proper path.
/// </summary>
private void SetWebAppPathOnUserAgent() {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
index 6faad56..4de5188 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
@@ -701,7 +701,7 @@ window.dnoa_internal.PositiveAssertion = function(uri) {
};
window.dnoa_internal.clone = function(obj) {
- if (obj === null || typeof (obj) != 'object') {
+ if (obj === null || typeof (obj) != 'object' || !isNaN(obj)) { // !isNaN catches Date objects
return obj;
}
@@ -710,6 +710,10 @@ window.dnoa_internal.clone = function(obj) {
temp[key] = window.dnoa_internal.clone(obj[key]);
}
+ // Copy over some built-in methods that were not included in the above loop,
+ // but nevertheless may have been overridden.
+ temp.toString = window.dnoa_internal.clone(obj.toString);
+
return temp;
};
@@ -732,7 +736,7 @@ window.dnoa_internal.clearExpiredPositiveAssertions = function() {
var discoveryResult = window.dnoa_internal.discoveryResults[identifier];
if (typeof (discoveryResult) != 'object') { continue; } // skip functions
for (var i = 0; i < discoveryResult.length; i++) {
- if (discoveryResult[i].result === window.dnoa_internal.authSuccess) {
+ if (discoveryResult[i] && discoveryResult[i].result === window.dnoa_internal.authSuccess) {
if (new Date() - discoveryResult[i].successReceived > window.dnoa_internal.maxPositiveAssertionLifetime) {
// This positive assertion is too old, and may eventually be rejected by DNOA during verification.
// Let's clear out the positive assertion so it can be renewed.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 02df7a2..5090ecd 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -92,6 +92,21 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
internal const string ReturnToReceivingControlId = OpenIdUtilities.CustomParameterPrefix + "receiver";
+ #region Protected internal callback parameter names
+
+ /// <summary>
+ /// The callback parameter to use for recognizing when the callback is in a popup window or hidden iframe.
+ /// </summary>
+ protected internal const string UIPopupCallbackKey = OpenIdUtilities.CustomParameterPrefix + "uipopup";
+
+ /// <summary>
+ /// The parameter name to include in the formulated auth request so that javascript can know whether
+ /// the OP advertises support for the UI extension.
+ /// </summary>
+ protected internal const string PopupUISupportedJSHint = OpenIdUtilities.CustomParameterPrefix + "popupUISupported";
+
+ #endregion
+
#region Property category constants
/// <summary>
@@ -111,18 +126,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
- #region Callback parameter names
-
- /// <summary>
- /// The callback parameter to use for recognizing when the callback is in a popup window or hidden iframe.
- /// </summary>
- protected const string UIPopupCallbackKey = OpenIdUtilities.CustomParameterPrefix + "uipopup";
-
- /// <summary>
- /// The parameter name to include in the formulated auth request so that javascript can know whether
- /// the OP advertises support for the UI extension.
- /// </summary>
- protected const string PopupUISupportedJSHint = OpenIdUtilities.CustomParameterPrefix + "popupUISupported";
+ #region Private callback parameter names
/// <summary>
/// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property.
@@ -293,10 +297,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// heavily trafficked web pages.
/// </remarks>
[Browsable(false)]
- public OpenIdRelyingParty RelyingParty {
+ public virtual OpenIdRelyingParty RelyingParty {
get {
if (this.relyingParty == null) {
this.relyingParty = this.CreateRelyingParty();
+ this.ConfigureRelyingParty(this.relyingParty);
this.relyingPartyOwned = true;
}
return this.relyingParty;
@@ -353,6 +358,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
set {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(value));
+
if (Page != null && !DesignMode) {
// Validate new value by trying to construct a Realm object based on it.
new Realm(OpenIdUtilities.GetResolvedRealm(this.Page, value, this.RelyingParty.Channel.GetRequestFromContext())); // throws an exception on failure.
@@ -556,8 +563,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
protected internal virtual IEnumerable<IAuthenticationRequest> CreateRequests(Identifier identifier) {
Contract.Requires<ArgumentNullException>(identifier != null);
- // Delegate to a private method to keep 'yield return' and Code Contract separate.
- return this.CreateRequestsCore(identifier);
+ // If this control is actually a member of another OpenID RP control,
+ // delegate creation of requests to the parent control.
+ var parentOwner = this.ParentControls.OfType<OpenIdRelyingPartyControlBase>().FirstOrDefault();
+ if (parentOwner != null) {
+ return parentOwner.CreateRequests(identifier);
+ } else {
+ // Delegate to a private method to keep 'yield return' and Code Contract separate.
+ return this.CreateRequestsCore(identifier);
+ }
}
/// <summary>
@@ -634,6 +648,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Notifies the user agent via an AJAX response of a completed authentication attempt.
+ /// </summary>
+ protected virtual void ScriptClosingPopupOrIFrame() {
+ this.RelyingParty.ProcessResponseFromPopup();
+ }
+
+ /// <summary>
/// Called when the <see cref="Identifier"/> property is changed.
/// </summary>
protected virtual void OnIdentifierChanged() {
@@ -769,29 +790,32 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Creates the relying party instance used to generate authentication requests.
/// </summary>
/// <returns>The instantiated relying party.</returns>
- protected virtual OpenIdRelyingParty CreateRelyingParty() {
- return this.CreateRelyingParty(true);
+ protected OpenIdRelyingParty CreateRelyingParty() {
+ IRelyingPartyApplicationStore store = this.Stateless ? null : DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.ApplicationStore.CreateInstance(OpenIdRelyingParty.HttpApplicationStore);
+ return this.CreateRelyingParty(store);
}
/// <summary>
/// Creates the relying party instance used to generate authentication requests.
/// </summary>
- /// <param name="verifySignature">
- /// A value indicating whether message protections should be applied to the processed messages.
- /// Use <c>false</c> to postpone verification to a later time without invalidating nonces.
- /// </param>
+ /// <param name="store">The store to pass to the relying party constructor.</param>
/// <returns>The instantiated relying party.</returns>
- protected virtual OpenIdRelyingParty CreateRelyingParty(bool verifySignature) {
- IRelyingPartyApplicationStore store = this.Stateless ? null : DotNetOpenAuthSection.Configuration.OpenId.RelyingParty.ApplicationStore.CreateInstance(OpenIdRelyingParty.HttpApplicationStore);
- var rp = verifySignature ? new OpenIdRelyingParty(store) : OpenIdRelyingParty.CreateNonVerifying();
+ protected virtual OpenIdRelyingParty CreateRelyingParty(IRelyingPartyApplicationStore store) {
+ return new OpenIdRelyingParty(store);
+ }
+
+ /// <summary>
+ /// Configures the relying party.
+ /// </summary>
+ /// <param name="relyingParty">The relying party.</param>
+ protected virtual void ConfigureRelyingParty(OpenIdRelyingParty relyingParty) {
+ Contract.Requires<ArgumentNullException>(relyingParty != null);
// Only set RequireSsl to true, as we don't want to override
// a .config setting of true with false.
if (this.RequireSsl) {
- rp.SecuritySettings.RequireSsl = true;
+ relyingParty.SecuritySettings.RequireSsl = true;
}
-
- return rp;
}
/// <summary>
@@ -810,7 +834,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
case PopupBehavior.Always:
return true;
case PopupBehavior.IfProviderSupported:
- return request.Provider.IsExtensionSupported<UIRequest>();
+ return request.DiscoveryResult.IsExtensionSupported<UIRequest>();
default:
throw ErrorUtilities.ThrowInternal("Unexpected value for Popup property.");
}
@@ -841,21 +865,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Wires the popup window to close itself and pass the authentication result to the parent window.
- /// </summary>
- protected virtual void ScriptClosingPopupOrIFrame() {
- StringBuilder startupScript = new StringBuilder();
- startupScript.AppendLine("window.opener.dnoa_internal.processAuthorizationResult(document.URL);");
- startupScript.AppendLine("window.close();");
-
- this.Page.ClientScript.RegisterStartupScript(typeof(OpenIdRelyingPartyControlBase), "loginPopupClose", startupScript.ToString(), true);
-
- // TODO: alternately we should probably take over rendering this page here to avoid
- // a lot of unnecessary work on the server and possible momentary display of the
- // page in the popup window.
- }
-
- /// <summary>
/// Creates the identifier-persisting cookie, either for saving or deleting.
/// </summary>
/// <param name="response">The positive authentication response; or <c>null</c> to clear the cookie.</param>
@@ -937,9 +946,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Inform ourselves in return_to that we're in a popup.
req.SetUntrustedCallbackArgument(UIPopupCallbackKey, "1");
- if (req.Provider.IsExtensionSupported<UIRequest>()) {
+ if (req.DiscoveryResult.IsExtensionSupported<UIRequest>()) {
// Inform the OP that we'll be using a popup window consistent with the UI extension.
- req.AddExtension(new UIRequest());
+ // But beware that the extension MAY have already been added if we're using
+ // the OpenIdAjaxRelyingParty class.
+ if (!((AuthenticationRequest)req).Extensions.OfType<UIRequest>().Any()) {
+ req.AddExtension(new UIRequest());
+ }
// Provide a hint for the client javascript about whether the OP supports the UI extension.
// This is so the window can be made the correct size for the extension.
@@ -1029,67 +1042,5 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return false;
}
-
- /// <summary>
- /// An authentication request comparer that judges equality solely on the OP endpoint hostname.
- /// </summary>
- private class DuplicateRequestedHostsComparer : IEqualityComparer<IAuthenticationRequest> {
- /// <summary>
- /// The singleton instance of this comparer.
- /// </summary>
- private static IEqualityComparer<IAuthenticationRequest> instance = new DuplicateRequestedHostsComparer();
-
- /// <summary>
- /// Prevents a default instance of the <see cref="DuplicateRequestedHostsComparer"/> class from being created.
- /// </summary>
- private DuplicateRequestedHostsComparer() {
- }
-
- /// <summary>
- /// Gets the singleton instance of this comparer.
- /// </summary>
- internal static IEqualityComparer<IAuthenticationRequest> Instance {
- get { return instance; }
- }
-
- #region IEqualityComparer<IAuthenticationRequest> Members
-
- /// <summary>
- /// Determines whether the specified objects are equal.
- /// </summary>
- /// <param name="x">The first object to compare.</param>
- /// <param name="y">The second object to compare.</param>
- /// <returns>
- /// true if the specified objects are equal; otherwise, false.
- /// </returns>
- public bool Equals(IAuthenticationRequest x, IAuthenticationRequest y) {
- if (x == null && y == null) {
- return true;
- }
-
- if (x == null || y == null) {
- return false;
- }
-
- // We'll distinguish based on the host name only, which
- // admittedly is only a heuristic, but if we remove one that really wasn't a duplicate, well,
- // this multiple OP attempt thing was just a convenience feature anyway.
- return string.Equals(x.Provider.Uri.Host, y.Provider.Uri.Host, StringComparison.OrdinalIgnoreCase);
- }
-
- /// <summary>
- /// Returns a hash code for the specified object.
- /// </summary>
- /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
- /// <returns>A hash code for the specified object.</returns>
- /// <exception cref="T:System.ArgumentNullException">
- /// The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.
- /// </exception>
- public int GetHashCode(IAuthenticationRequest obj) {
- return obj.Provider.Uri.Host.GetHashCode();
- }
-
- #endregion
- }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
index e93383d..b7a54eb 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.cs
@@ -81,11 +81,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private HiddenField positiveAssertionField;
/// <summary>
- /// A field to store the value to set on the <see cref="textBox"/> control after it's created.
- /// </summary>
- private bool downloadYuiLibrary = OpenIdAjaxTextBox.DownloadYahooUILibraryDefault;
-
- /// <summary>
/// Initializes a new instance of the <see cref="OpenIdSelector"/> class.
/// </summary>
public OpenIdSelector() {
@@ -102,6 +97,50 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public event EventHandler<TokenProcessingErrorEventArgs> TokenProcessingError;
/// <summary>
+ /// Gets the text box where applicable.
+ /// </summary>
+ public OpenIdAjaxTextBox TextBox {
+ get {
+ this.EnsureChildControlsAreCreatedSafe();
+ return this.textBox;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum number of OpenID Providers to simultaneously try to authenticate with.
+ /// </summary>
+ [Browsable(true), DefaultValue(OpenIdAjaxTextBox.ThrottleDefault), Category(BehaviorCategory)]
+ [Description("The maximum number of OpenID Providers to simultaneously try to authenticate with.")]
+ public int Throttle {
+ get {
+ this.EnsureChildControlsAreCreatedSafe();
+ return this.textBox.Throttle;
+ }
+
+ set {
+ this.EnsureChildControlsAreCreatedSafe();
+ this.textBox.Throttle = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the time duration for the AJAX control to wait for an OP to respond before reporting failure to the user.
+ /// </summary>
+ [Browsable(true), DefaultValue(typeof(TimeSpan), "00:00:08"), Category(BehaviorCategory)]
+ [Description("The time duration for the AJAX control to wait for an OP to respond before reporting failure to the user.")]
+ public TimeSpan Timeout {
+ get {
+ this.EnsureChildControlsAreCreatedSafe();
+ return this.textBox.Timeout;
+ }
+
+ set {
+ this.EnsureChildControlsAreCreatedSafe();
+ this.textBox.Timeout = value;
+ }
+ }
+
+ /// <summary>
/// Gets or sets the tool tip text that appears on the green checkmark when authentication succeeds.
/// </summary>
[Bindable(true), DefaultValue(AuthenticatedAsToolTipDefault), Localizable(true), Category(AppearanceCategory)]
@@ -126,19 +165,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Description("Whether a split button will be used for the \"log in\" when the user provides an identifier that delegates to more than one Provider.")]
public bool DownloadYahooUILibrary {
get {
- return this.textBox != null ? this.textBox.DownloadYahooUILibrary : this.downloadYuiLibrary;
+ this.EnsureChildControlsAreCreatedSafe();
+ return this.textBox.DownloadYahooUILibrary;
}
set {
- // We don't just call EnsureChildControls() and then set the property on
- // this.textBox itself because (apparently) setting this property in the ASPX
- // page and thus calling this EnsureID() via EnsureChildControls() this early
- // results in no ID.
- if (this.textBox != null) {
- this.textBox.DownloadYahooUILibrary = value;
- } else {
- this.downloadYuiLibrary = value;
- }
+ this.EnsureChildControlsAreCreatedSafe();
+ this.textBox.DownloadYahooUILibrary = value;
}
}
@@ -207,10 +240,37 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
/// </summary>
protected override void CreateChildControls() {
+ this.EnsureChildControlsAreCreatedSafe();
+
base.CreateChildControls();
+
+ // Now do the ID specific work.
this.EnsureID();
ErrorUtilities.VerifyInternal(!string.IsNullOrEmpty(this.UniqueID), "Control.EnsureID() failed to give us a unique ID. Try setting an ID on the OpenIdSelector control. But please also file this bug with the project owners.");
+ this.Controls.Add(this.textBox);
+
+ this.positiveAssertionField.ID = this.ID + AuthDataFormKeySuffix;
+ this.Controls.Add(this.positiveAssertionField);
+ }
+
+ /// <summary>
+ /// Ensures that the child controls have been built, but doesn't set control
+ /// properties that require executing <see cref="Control.EnsureID"/> in order to avoid
+ /// certain initialization order problems.
+ /// </summary>
+ /// <remarks>
+ /// We don't just call EnsureChildControls() and then set the property on
+ /// this.textBox itself because (apparently) setting this property in the ASPX
+ /// page and thus calling this EnsureID() via EnsureChildControls() this early
+ /// results in no ID.
+ /// </remarks>
+ protected virtual void EnsureChildControlsAreCreatedSafe() {
+ // If we've already created the child controls, this method is a no-op.
+ if (this.textBox != null) {
+ return;
+ }
+
var selectorButton = this.Buttons.OfType<SelectorInfoCardButton>().FirstOrDefault();
if (selectorButton != null) {
var selector = selectorButton.InfoCardSelector;
@@ -225,12 +285,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.textBox.ID = "openid_identifier";
this.textBox.HookFormSubmit = false;
this.textBox.ShowLogOnPostBackButton = true;
- this.textBox.DownloadYahooUILibrary = this.downloadYuiLibrary;
- this.Controls.Add(this.textBox);
this.positiveAssertionField = new HiddenField();
- this.positiveAssertionField.ID = this.ID + AuthDataFormKeySuffix;
- this.Controls.Add(this.positiveAssertionField);
}
/// <summary>
@@ -254,11 +310,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.EnsureValidButtons();
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;
+ }
// Import the .js file where most of the code is.
this.Page.ClientScript.RegisterClientScriptResource(typeof(OpenIdSelector), EmbeddedScriptResourceName);
@@ -288,6 +349,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
protected override void Render(HtmlTextWriter writer) {
+ Contract.Assume(writer != null, "Missing contract");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders");
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
index c58e06e..297ea23 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdSelector.js
@@ -178,15 +178,19 @@ $(function() {
ajaxbox.focus();
}
});
+
+ $(ajaxbox.form).keydown(function(e) {
+ if (e.keyCode == $.ui.keyCode.ENTER) {
+ // we do NOT want to submit the form on ENTER.
+ e.preventDefault();
+ }
+ });
}
// Make popup window close on escape (the dialog style is already taken care of)
$(document).keydown(function(e) {
if (e.keyCode == $.ui.keyCode.ESCAPE) {
window.close();
- } else if (e.keyCode == $.ui.keyCode.ENTER) {
- // we do NOT want to submit the form on ENTER.
- e.preventDefault();
}
});
}); \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
index 4d635fb..335b435 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox.EmbeddedLogoResourceName, "image/gif")]
+[assembly: System.Web.UI.WebResource(DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox.EmbeddedLogoResourceName, "image/png")]
#pragma warning disable 0809 // marking inherited, unsupported properties as obsolete to discourage their use
@@ -45,7 +45,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The name of the manifest stream containing the
/// OpenID logo that is placed inside the text box.
/// </summary>
- internal const string EmbeddedLogoResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.openid_login.gif";
+ internal const string EmbeddedLogoResourceName = Util.DefaultNamespace + ".OpenId.RelyingParty.openid_login.png";
/// <summary>
/// Default value for <see cref="TabIndex"/> property.
@@ -584,6 +584,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
protected override void Render(HtmlTextWriter writer) {
+ Contract.Assume(writer != null, "Missing contract.");
+
if (this.ShowLogo) {
string logoUrl = Page.ClientScript.GetWebResourceUrl(
typeof(OpenIdTextBox), EmbeddedLogoResourceName);
@@ -625,6 +627,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// true if the server control's state changes as a result of the postback; otherwise, false.
/// </returns>
protected virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) {
+ Contract.Assume(postCollection != null, "Missing contract");
+
// If the control was temporarily hidden, it won't be in the Form data,
// and we'll just implicitly keep the last Text setting.
if (postCollection[this.Name] != null) {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
index 6e7d7ef..5cfa191 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAnonymousResponse.cs
@@ -26,7 +26,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Information about the OP endpoint that issued this assertion.
/// </summary>
- private readonly ProviderEndpointDescription provider;
+ private readonly IProviderEndpoint provider;
/// <summary>
/// Initializes a new instance of the <see cref="PositiveAnonymousResponse"/> class.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index 695aa1e..3e2298c 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -28,7 +28,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
: base(response) {
Contract.Requires<ArgumentNullException>(relyingParty != null);
- this.Endpoint = ServiceEndpoint.CreateForClaimedIdentifier(
+ this.Endpoint = IdentifierDiscoveryResult.CreateForClaimedIdentifier(
this.Response.ClaimedIdentifier,
this.Response.GetReturnToArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName),
this.Response.LocalIdentifier,
@@ -114,7 +114,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// the claimed identifier to avoid a Provider asserting an Identifier
/// for which it has no authority.
/// </remarks>
- internal ServiceEndpoint Endpoint { get; private set; }
+ internal IdentifierDiscoveryResult Endpoint { get; private set; }
/// <summary>
/// Gets the positive assertion response message.
@@ -146,6 +146,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
+ // Check whether this particular identifier presents a problem with HTTP discovery
+ // due to limitations in the .NET Uri class.
+ UriIdentifier claimedIdUri = claimedId as UriIdentifier;
+ if (claimedIdUri != null && claimedIdUri.ProblematicNormalization) {
+ ErrorUtilities.VerifyProtocol(relyingParty.SecuritySettings.AllowApproximateIdentifierDiscovery, OpenIdStrings.ClaimedIdentifierDefiesDotNetNormalization);
+ Logger.OpenId.WarnFormat("Positive assertion for claimed identifier {0} cannot be precisely verified under partial trust hosting due to .NET limitation. An approximate verification will be attempted.", claimedId);
+ }
+
// While it LOOKS like we're performing discovery over HTTP again
// Yadis.IdentifierDiscoveryCachePolicy is set to HttpRequestCacheLevel.CacheIfAvailable
// which means that the .NET runtime is caching our discoveries for us. This turns out
@@ -155,7 +163,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// is signed by the RP before it's considered reliable. In 1.x stateless mode, this RP
// doesn't (and can't) sign its own return_to URL, so its cached discovery information
// is merely a hint that must be verified by performing discovery again here.
- var discoveryResults = claimedId.Discover(relyingParty.WebRequestHandler);
+ var discoveryResults = relyingParty.Discover(claimedId);
ErrorUtilities.VerifyProtocol(
discoveryResults.Contains(this.Endpoint),
OpenIdStrings.IssuedAssertionFailsIdentifierDiscovery,
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
index ff29498..a7686c5 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
@@ -16,11 +16,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
public sealed class RelyingPartySecuritySettings : SecuritySettings {
/// <summary>
+ /// The default value for the <see cref="ProtectDownlevelReplayAttacks"/> property.
+ /// </summary>
+ internal const bool ProtectDownlevelReplayAttacksDefault = true;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="RelyingPartySecuritySettings"/> class.
/// </summary>
internal RelyingPartySecuritySettings()
: base(false) {
this.PrivateSecretMaximumAge = TimeSpan.FromDays(7);
+ this.ProtectDownlevelReplayAttacks = ProtectDownlevelReplayAttacksDefault;
+ this.AllowApproximateIdentifierDiscovery = true;
}
/// <summary>
@@ -111,11 +118,51 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public bool RequireAssociation { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether identifiers that are both OP Identifiers and Claimed Identifiers
+ /// should ever be recognized as claimed identifiers.
+ /// </summary>
+ /// <value>
+ /// The default value is <c>false</c>, per the OpenID 2.0 spec.
+ /// </value>
+ /// <remarks>
+ /// OpenID 2.0 sections 7.3.2.2 and 11.2 specify that OP Identifiers never be recognized as Claimed Identifiers.
+ /// However, for some scenarios it may be desirable for an RP to override this behavior and allow this.
+ /// The security ramifications of setting this property to <c>true</c> have not been fully explored and
+ /// therefore this setting should only be changed with caution.
+ /// </remarks>
+ public bool AllowDualPurposeIdentifiers { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether certain Claimed Identifiers that exploit
+ /// features that .NET does not have the ability to send exact HTTP requests for will
+ /// still be allowed by using an approximate HTTP request.
+ /// </summary>
+ /// <value>
+ /// The default value is <c>true</c>.
+ /// </value>
+ public bool AllowApproximateIdentifierDiscovery { 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.
+ /// </summary>
+ /// <value>The default value is <c>true</c>.</value>
+ /// <remarks>
+ /// <para>Nonces for protection against replay attacks were not mandated
+ /// by OpenID 1.x, which leaves users open to replay attacks.</para>
+ /// <para>This feature works by adding a signed nonce to the authentication request.
+ /// This might increase the request size beyond what some OpenID 1.1 Providers
+ /// (such as Blogger) are capable of handling.</para>
+ /// </remarks>
+ internal bool ProtectDownlevelReplayAttacks { get; set; }
+
+ /// <summary>
/// Filters out any disallowed endpoints.
/// </summary>
/// <param name="endpoints">The endpoints discovered on an Identifier.</param>
/// <returns>A sequence of endpoints that satisfy all security requirements.</returns>
- internal IEnumerable<ServiceEndpoint> FilterEndpoints(IEnumerable<ServiceEndpoint> endpoints) {
+ internal IEnumerable<IdentifierDiscoveryResult> FilterEndpoints(IEnumerable<IdentifierDiscoveryResult> endpoints) {
return endpoints
.Where(se => !this.RejectDelegatingIdentifiers || se.ClaimedIdentifier == se.ProviderLocalIdentifier)
.Where(se => !this.RequireDirectedIdentity || se.ClaimedIdentifier == se.Protocol.ClaimedIdentifierForOPIdentifier);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
index 15b6ca7..ac4dcbf 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorOpenIdButton.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Drawing.Design;
@@ -24,6 +25,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Initializes a new instance of the <see cref="SelectorOpenIdButton"/> class.
+ /// </summary>
+ /// <param name="imageUrl">The image to display on the button.</param>
+ public SelectorOpenIdButton(string imageUrl)
+ : this() {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
+
+ this.Image = imageUrl;
+ }
+
+ /// <summary>
/// Gets or sets the path to the image to display on the button's surface.
/// </summary>
/// <value>The virtual path to the image.</value>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
index 3a05287..2195e73 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SelectorProviderButton.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Drawing.Design;
@@ -25,6 +26,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Initializes a new instance of the <see cref="SelectorProviderButton"/> class.
+ /// </summary>
+ /// <param name="providerIdentifier">The OP Identifier.</param>
+ /// <param name="imageUrl">The image to display on the button.</param>
+ public SelectorProviderButton(Identifier providerIdentifier, string imageUrl)
+ : this() {
+ Contract.Requires<ArgumentNullException>(providerIdentifier != null);
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
+
+ this.OPIdentifier = providerIdentifier;
+ this.Image = imageUrl;
+ }
+
+ /// <summary>
/// Gets or sets the path to the image to display on the button's surface.
/// </summary>
/// <value>The virtual path to the image.</value>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs
index 912b8f4..678f69a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs
@@ -6,6 +6,8 @@
namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
+ using System.Collections.ObjectModel;
+ using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
/// <summary>
@@ -13,7 +15,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// assertions (particularly unsolicited ones) are received from OP endpoints that
/// are deemed permissible by the host RP.
/// </summary>
- internal class SimpleXrdsProviderEndpoint : IXrdsProviderEndpoint {
+ internal class SimpleXrdsProviderEndpoint : IProviderEndpoint {
/// <summary>
/// Initializes a new instance of the <see cref="SimpleXrdsProviderEndpoint"/> class.
/// </summary>
@@ -23,29 +25,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.Version = positiveAssertion.Version;
}
- #region IXrdsProviderEndpoint Properties
-
- /// <summary>
- /// Gets the priority associated with this service that may have been given
- /// in the XRDS document.
- /// </summary>
- public int? ServicePriority {
- get { return null; }
- }
-
- /// <summary>
- /// Gets the priority associated with the service endpoint URL.
- /// </summary>
- /// <remarks>
- /// When sorting by priority, this property should be considered second after
- /// <see cref="ServicePriority"/>.
- /// </remarks>
- public int? UriPriority {
- get { return null; }
- }
-
- #endregion
-
#region IProviderEndpoint Members
/// <summary>
@@ -56,7 +35,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets the URL that the OpenID Provider receives authentication requests at.
/// </summary>
- /// <value></value>
public Uri Uri { get; private set; }
/// <summary>
@@ -73,8 +51,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The only way to be sure of support for a given extension is to include
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
- public bool IsExtensionSupported<T>() where T : DotNetOpenAuth.OpenId.Messages.IOpenIdMessageExtension, new() {
- throw new NotSupportedException();
+ bool IProviderEndpoint.IsExtensionSupported<T>() {
+ throw new NotImplementedException();
}
/// <summary>
@@ -91,23 +69,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The only way to be sure of support for a given extension is to include
/// the extension in the request and see if a response comes back for that extension.
/// </remarks>
- public bool IsExtensionSupported(Type extensionType) {
- throw new NotSupportedException();
- }
-
- #endregion
-
- #region IXrdsProviderEndpoint Methods
-
- /// <summary>
- /// Checks for the presence of a given Type URI in an XRDS service.
- /// </summary>
- /// <param name="typeUri">The type URI to check for.</param>
- /// <returns>
- /// <c>true</c> if the service type uri is present; <c>false</c> otherwise.
- /// </returns>
- public bool IsTypeUriPresent(string typeUri) {
- throw new NotSupportedException();
+ bool IProviderEndpoint.IsExtensionSupported(Type extensionType) {
+ throw new NotImplementedException();
}
#endregion
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.gif b/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.gif
deleted file mode 100644
index cde836c..0000000
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.gif
+++ /dev/null
Binary files differ
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.png b/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.png
new file mode 100644
index 0000000..caebd58
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/openid_login.png
Binary files differ
diff --git a/src/DotNetOpenAuth/OpenId/UriDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/UriDiscoveryService.cs
new file mode 100644
index 0000000..7d17fd9
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/UriDiscoveryService.cs
@@ -0,0 +1,139 @@
+//-----------------------------------------------------------------------
+// <copyright file="UriDiscoveryService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Web.UI.HtmlControls;
+ using System.Xml;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Xrds;
+ using DotNetOpenAuth.Yadis;
+
+ /// <summary>
+ /// The discovery service for URI identifiers.
+ /// </summary>
+ public class UriDiscoveryService : IIdentifierDiscoveryService {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UriDiscoveryService"/> class.
+ /// </summary>
+ public UriDiscoveryService() {
+ }
+
+ #region IDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ public IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ abortDiscoveryChain = false;
+ var uriIdentifier = identifier as UriIdentifier;
+ if (uriIdentifier == null) {
+ return Enumerable.Empty<IdentifierDiscoveryResult>();
+ }
+
+ var endpoints = new List<IdentifierDiscoveryResult>();
+
+ // Attempt YADIS discovery
+ DiscoveryResult yadisResult = Yadis.Discover(requestHandler, uriIdentifier, identifier.IsDiscoverySecureEndToEnd);
+ if (yadisResult != null) {
+ if (yadisResult.IsXrds) {
+ try {
+ XrdsDocument xrds = new XrdsDocument(yadisResult.ResponseText);
+ var xrdsEndpoints = xrds.XrdElements.CreateServiceEndpoints(yadisResult.NormalizedUri, uriIdentifier);
+
+ // Filter out insecure endpoints if high security is required.
+ if (uriIdentifier.IsDiscoverySecureEndToEnd) {
+ xrdsEndpoints = xrdsEndpoints.Where(se => se.ProviderEndpoint.IsTransportSecure());
+ }
+ endpoints.AddRange(xrdsEndpoints);
+ } catch (XmlException ex) {
+ Logger.Yadis.Error("Error while parsing the XRDS document. Falling back to HTML discovery.", ex);
+ }
+ }
+
+ // Failing YADIS discovery of an XRDS document, we try HTML discovery.
+ if (endpoints.Count == 0) {
+ yadisResult.TryRevertToHtmlResponse();
+ var htmlEndpoints = new List<IdentifierDiscoveryResult>(DiscoverFromHtml(yadisResult.NormalizedUri, uriIdentifier, yadisResult.ResponseText));
+ if (htmlEndpoints.Any()) {
+ Logger.Yadis.DebugFormat("Total services discovered in HTML: {0}", htmlEndpoints.Count);
+ Logger.Yadis.Debug(htmlEndpoints.ToStringDeferred(true));
+ endpoints.AddRange(htmlEndpoints.Where(ep => !uriIdentifier.IsDiscoverySecureEndToEnd || ep.ProviderEndpoint.IsTransportSecure()));
+ if (endpoints.Count == 0) {
+ Logger.Yadis.Info("No HTML discovered endpoints met the security requirements.");
+ }
+ } else {
+ Logger.Yadis.Debug("HTML discovery failed to find any endpoints.");
+ }
+ } else {
+ Logger.Yadis.Debug("Skipping HTML discovery because XRDS contained service endpoints.");
+ }
+ }
+ return endpoints;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Searches HTML for the HEAD META tags that describe OpenID provider services.
+ /// </summary>
+ /// <param name="claimedIdentifier">The final URL that provided this HTML document.
+ /// This may not be the same as (this) userSuppliedIdentifier if the
+ /// userSuppliedIdentifier pointed to a 301 Redirect.</param>
+ /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
+ /// <param name="html">The HTML that was downloaded and should be searched.</param>
+ /// <returns>
+ /// A sequence of any discovered ServiceEndpoints.
+ /// </returns>
+ private static IEnumerable<IdentifierDiscoveryResult> DiscoverFromHtml(Uri claimedIdentifier, UriIdentifier userSuppliedIdentifier, string html) {
+ var linkTags = new List<HtmlLink>(HtmlParser.HeadTags<HtmlLink>(html));
+ foreach (var protocol in Protocol.AllPracticalVersions) {
+ // rel attributes are supposed to be interpreted with case INsensitivity,
+ // and is a space-delimited list of values. (http://www.htmlhelp.com/reference/html40/values.html#linktypes)
+ var serverLinkTag = linkTags.WithAttribute("rel").FirstOrDefault(tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryProviderKey) + @"\b", RegexOptions.IgnoreCase));
+ if (serverLinkTag == null) {
+ continue;
+ }
+
+ Uri providerEndpoint = null;
+ if (Uri.TryCreate(serverLinkTag.Href, UriKind.Absolute, out providerEndpoint)) {
+ // See if a LocalId tag of the discovered version exists
+ Identifier providerLocalIdentifier = null;
+ var delegateLinkTag = linkTags.WithAttribute("rel").FirstOrDefault(tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryLocalIdKey) + @"\b", RegexOptions.IgnoreCase));
+ if (delegateLinkTag != null) {
+ if (Identifier.IsValid(delegateLinkTag.Href)) {
+ providerLocalIdentifier = delegateLinkTag.Href;
+ } else {
+ Logger.Yadis.WarnFormat("Skipping endpoint data because local id is badly formed ({0}).", delegateLinkTag.Href);
+ continue; // skip to next version
+ }
+ }
+
+ // Choose the TypeURI to match the OpenID version detected.
+ string[] typeURIs = { protocol.ClaimedIdentifierServiceTypeURI };
+ yield return IdentifierDiscoveryResult.CreateForClaimedIdentifier(
+ claimedIdentifier,
+ userSuppliedIdentifier,
+ providerLocalIdentifier,
+ new ProviderEndpointDescription(providerEndpoint, typeURIs),
+ (int?)null,
+ (int?)null);
+ }
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
index 28d8b37..639ff57 100644
--- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
@@ -10,6 +10,9 @@ namespace DotNetOpenAuth.OpenId {
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
+ using System.Reflection;
+ using System.Security;
+ using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI.HtmlControls;
using System.Xml;
@@ -30,6 +33,68 @@ namespace DotNetOpenAuth.OpenId {
private static readonly string[] allowedSchemes = { "http", "https" };
/// <summary>
+ /// The special scheme to use for HTTP URLs that should not have their paths compressed.
+ /// </summary>
+ private static NonPathCompressingUriParser roundTrippingHttpParser = new NonPathCompressingUriParser(Uri.UriSchemeHttp);
+
+ /// <summary>
+ /// The special scheme to use for HTTPS URLs that should not have their paths compressed.
+ /// </summary>
+ private static NonPathCompressingUriParser roundTrippingHttpsParser = new NonPathCompressingUriParser(Uri.UriSchemeHttps);
+
+ /// <summary>
+ /// The special scheme to use for HTTP URLs that should not have their paths compressed.
+ /// </summary>
+ private static NonPathCompressingUriParser publishableHttpParser = new NonPathCompressingUriParser(Uri.UriSchemeHttp);
+
+ /// <summary>
+ /// The special scheme to use for HTTPS URLs that should not have their paths compressed.
+ /// </summary>
+ private static NonPathCompressingUriParser publishableHttpsParser = new NonPathCompressingUriParser(Uri.UriSchemeHttps);
+
+ /// <summary>
+ /// A value indicating whether scheme substitution is being used to workaround
+ /// .NET path compression that invalidates some OpenIDs that have trailing periods
+ /// in one of their path segments.
+ /// </summary>
+ private static bool schemeSubstitution;
+
+ /// <summary>
+ /// Initializes static members of the <see cref="UriIdentifier"/> class.
+ /// </summary>
+ /// <remarks>
+ /// This method attempts to workaround the .NET Uri class parsing bug described here:
+ /// https://connect.microsoft.com/VisualStudio/feedback/details/386695/system-uri-incorrectly-strips-trailing-dots?wa=wsignin1.0#tabs
+ /// since some identifiers (like some of the pseudonymous identifiers from Yahoo) include path segments
+ /// that end with periods, which the Uri class will typically trim off.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "Some things just can't be done in a field initializer.")]
+ static UriIdentifier() {
+ // Our first attempt to handle trailing periods in path segments is to leverage
+ // full trust if it's available to rewrite the rules.
+ // In fact this is the ONLY way in .NET 3.5 (and arguably in .NET 4.0) to send
+ // outbound HTTP requests with trailing periods, so it's the only way to perform
+ // discovery on such an identifier.
+ try {
+ UriParser.Register(roundTrippingHttpParser, "dnoarthttp", 80);
+ UriParser.Register(roundTrippingHttpsParser, "dnoarthttps", 443);
+ UriParser.Register(publishableHttpParser, "dnoahttp", 80);
+ UriParser.Register(publishableHttpsParser, "dnoahttps", 443);
+ roundTrippingHttpParser.Initialize(false);
+ roundTrippingHttpsParser.Initialize(false);
+ publishableHttpParser.Initialize(true);
+ publishableHttpsParser.Initialize(true);
+ schemeSubstitution = true;
+ Logger.OpenId.Debug(".NET Uri class path compression overridden.");
+ Reporting.RecordFeatureUse("FullTrust");
+ } catch (SecurityException) {
+ // We must be running in partial trust. Nothing more we can do.
+ Logger.OpenId.Warn("Unable to coerce .NET to stop compressing URI paths due to partial trust limitations. Some URL identifiers may be unable to complete login.");
+ Reporting.RecordFeatureUse("PartialTrust");
+ }
+ }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="UriIdentifier"/> class.
/// </summary>
/// <param name="uri">The value this identifier will represent.</param>
@@ -62,7 +127,8 @@ namespace DotNetOpenAuth.OpenId {
/// Initializes a new instance of the <see cref="UriIdentifier"/> class.
/// </summary>
/// <param name="uri">The value this identifier will represent.</param>
- internal UriIdentifier(Uri uri) : this(uri, false) {
+ internal UriIdentifier(Uri uri)
+ : this(uri, false) {
}
/// <summary>
@@ -73,7 +139,13 @@ namespace DotNetOpenAuth.OpenId {
internal UriIdentifier(Uri uri, bool requireSslDiscovery)
: base(uri != null ? uri.OriginalString : null, requireSslDiscovery) {
Contract.Requires<ArgumentNullException>(uri != null);
- if (!TryCanonicalize(new UriBuilder(uri), out uri)) {
+
+ string uriAsString = uri.OriginalString;
+ if (schemeSubstitution) {
+ uriAsString = NormalSchemeToSpecialRoundTrippingScheme(uriAsString);
+ }
+
+ if (!TryCanonicalize(uriAsString, out uri)) {
throw new UriFormatException();
}
if (requireSslDiscovery && uri.Scheme != Uri.UriSchemeHttps) {
@@ -96,6 +168,26 @@ namespace DotNetOpenAuth.OpenId {
internal bool SchemeImplicitlyPrepended { get; private set; }
/// <summary>
+ /// Gets a value indicating whether this Identifier has characters or patterns that
+ /// the <see cref="Uri"/> class normalizes away and invalidating the Identifier.
+ /// </summary>
+ internal bool ProblematicNormalization {
+ get {
+ if (schemeSubstitution) {
+ // With full trust, we have no problematic URIs
+ return false;
+ }
+
+ var simpleUri = new SimpleUri(this.OriginalString);
+ if (simpleUri.Path.EndsWith(".", StringComparison.Ordinal) || simpleUri.Path.Contains("./")) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ /// <summary>
/// Converts a <see cref="UriIdentifier"/> instance to a <see cref="Uri"/> instance.
/// </summary>
/// <param name="identifier">The identifier to convert to an ordinary <see cref="Uri"/> instance.</param>
@@ -137,7 +229,12 @@ namespace DotNetOpenAuth.OpenId {
if (other == null) {
return false;
}
- return this.Uri == other.Uri;
+
+ if (this.ProblematicNormalization || other.ProblematicNormalization) {
+ return new SimpleUri(this.OriginalString).Equals(new SimpleUri(other.OriginalString));
+ } else {
+ return this.Uri == other.Uri;
+ }
}
/// <summary>
@@ -157,16 +254,13 @@ namespace DotNetOpenAuth.OpenId {
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
/// </returns>
public override string ToString() {
- return Uri.AbsoluteUri;
- }
-#if UNUSED
- static bool TryCanonicalize(string uri, out string canonicalUri) {
- Uri normalizedUri;
- bool result = TryCanonicalize(uri, out normalizedUri);
- canonicalUri = normalizedUri.AbsoluteUri;
- return result;
+ if (this.ProblematicNormalization) {
+ return new SimpleUri(this.OriginalString).ToString();
+ } else {
+ return this.Uri.AbsoluteUri;
+ }
}
-#endif
+
/// <summary>
/// Determines whether a URI is a valid OpenID Identifier (of any kind).
/// </summary>
@@ -207,54 +301,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Performs discovery on the Identifier.
- /// </summary>
- /// <param name="requestHandler">The web request handler to use for discovery.</param>
- /// <returns>
- /// An initialized structure containing the discovered provider endpoint information.
- /// </returns>
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>();
-
- // Attempt YADIS discovery
- DiscoveryResult yadisResult = Yadis.Discover(requestHandler, this, IsDiscoverySecureEndToEnd);
- if (yadisResult != null) {
- if (yadisResult.IsXrds) {
- try {
- XrdsDocument xrds = new XrdsDocument(yadisResult.ResponseText);
- var xrdsEndpoints = xrds.CreateServiceEndpoints(yadisResult.NormalizedUri, this);
-
- // Filter out insecure endpoints if high security is required.
- if (IsDiscoverySecureEndToEnd) {
- xrdsEndpoints = xrdsEndpoints.Where(se => se.IsSecure);
- }
- endpoints.AddRange(xrdsEndpoints);
- } catch (XmlException ex) {
- Logger.Yadis.Error("Error while parsing the XRDS document. Falling back to HTML discovery.", ex);
- }
- }
-
- // Failing YADIS discovery of an XRDS document, we try HTML discovery.
- if (endpoints.Count == 0) {
- var htmlEndpoints = new List<ServiceEndpoint>(DiscoverFromHtml(yadisResult.NormalizedUri, this, yadisResult.ResponseText));
- if (htmlEndpoints.Any()) {
- Logger.Yadis.DebugFormat("Total services discovered in HTML: {0}", htmlEndpoints.Count);
- Logger.Yadis.Debug(htmlEndpoints.ToStringDeferred(true));
- endpoints.AddRange(htmlEndpoints.Where(ep => !IsDiscoverySecureEndToEnd || ep.IsSecure));
- if (endpoints.Count == 0) {
- Logger.Yadis.Info("No HTML discovered endpoints met the security requirements.");
- }
- } else {
- Logger.Yadis.Debug("HTML discovery failed to find any endpoints.");
- }
- } else {
- Logger.Yadis.Debug("Skipping HTML discovery because XRDS contained service endpoints.");
- }
- }
- return endpoints;
- }
-
- /// <summary>
/// Returns an <see cref="Identifier"/> that has no URI fragment.
/// Quietly returns the original <see cref="Identifier"/> if it is not
/// a <see cref="UriIdentifier"/> or no fragment exists.
@@ -270,9 +316,7 @@ namespace DotNetOpenAuth.OpenId {
}
// Strip the fragment.
- UriBuilder builder = new UriBuilder(Uri);
- builder.Fragment = null;
- return builder.Uri;
+ return new UriIdentifier(this.OriginalString.Substring(0, this.OriginalString.IndexOf('#')));
}
/// <summary>
@@ -318,54 +362,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Searches HTML for the HEAD META tags that describe OpenID provider services.
- /// </summary>
- /// <param name="claimedIdentifier">The final URL that provided this HTML document.
- /// This may not be the same as (this) userSuppliedIdentifier if the
- /// userSuppliedIdentifier pointed to a 301 Redirect.</param>
- /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
- /// <param name="html">The HTML that was downloaded and should be searched.</param>
- /// <returns>
- /// A sequence of any discovered ServiceEndpoints.
- /// </returns>
- private static IEnumerable<ServiceEndpoint> DiscoverFromHtml(Uri claimedIdentifier, UriIdentifier userSuppliedIdentifier, string html) {
- var linkTags = new List<HtmlLink>(HtmlParser.HeadTags<HtmlLink>(html));
- foreach (var protocol in Protocol.AllPracticalVersions) {
- // rel attributes are supposed to be interpreted with case INsensitivity,
- // and is a space-delimited list of values. (http://www.htmlhelp.com/reference/html40/values.html#linktypes)
- var serverLinkTag = linkTags.WithAttribute("rel").FirstOrDefault(tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryProviderKey) + @"\b", RegexOptions.IgnoreCase));
- if (serverLinkTag == null) {
- continue;
- }
-
- Uri providerEndpoint = null;
- if (Uri.TryCreate(serverLinkTag.Href, UriKind.Absolute, out providerEndpoint)) {
- // See if a LocalId tag of the discovered version exists
- Identifier providerLocalIdentifier = null;
- var delegateLinkTag = linkTags.WithAttribute("rel").FirstOrDefault(tag => Regex.IsMatch(tag.Attributes["rel"], @"\b" + Regex.Escape(protocol.HtmlDiscoveryLocalIdKey) + @"\b", RegexOptions.IgnoreCase));
- if (delegateLinkTag != null) {
- if (Identifier.IsValid(delegateLinkTag.Href)) {
- providerLocalIdentifier = delegateLinkTag.Href;
- } else {
- Logger.Yadis.WarnFormat("Skipping endpoint data because local id is badly formed ({0}).", delegateLinkTag.Href);
- continue; // skip to next version
- }
- }
-
- // Choose the TypeURI to match the OpenID version detected.
- string[] typeURIs = { protocol.ClaimedIdentifierServiceTypeURI };
- yield return ServiceEndpoint.CreateForClaimedIdentifier(
- claimedIdentifier,
- userSuppliedIdentifier,
- providerLocalIdentifier,
- new ProviderEndpointDescription(providerEndpoint, typeURIs),
- (int?)null,
- (int?)null);
- }
- }
- }
-
- /// <summary>
/// Determines whether the given URI is using a scheme in the list of allowed schemes.
/// </summary>
/// <param name="uri">The URI whose scheme is to be checked.</param>
@@ -431,8 +427,12 @@ namespace DotNetOpenAuth.OpenId {
schemePrepended = true;
}
+ if (schemeSubstitution) {
+ uri = NormalSchemeToSpecialRoundTrippingScheme(uri);
+ }
+
// Use a UriBuilder because it helps to normalize the URL as well.
- return TryCanonicalize(new UriBuilder(uri), out canonicalUri);
+ return TryCanonicalize(uri, out canonicalUri);
} catch (UriFormatException) {
// We try not to land here with checks in the try block, but just in case.
return false;
@@ -440,9 +440,9 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Removes the fragment from a URL and sets the host to lowercase.
+ /// Fixes up the scheme if appropriate.
/// </summary>
- /// <param name="uriBuilder">The URI builder with the value to canonicalize.</param>
+ /// <param name="uri">The URI to canonicalize.</param>
/// <param name="canonicalUri">The resulting canonical URI.</param>
/// <returns><c>true</c> if the canonicalization was successful; <c>false</c> otherwise.</returns>
/// <remarks>
@@ -452,12 +452,48 @@ namespace DotNetOpenAuth.OpenId {
/// For this, you should lookup the value stored in IAuthenticationResponse.ClaimedIdentifier.
/// </remarks>
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "The user will see the result of this operation and they want to see it in lower case.")]
- private static bool TryCanonicalize(UriBuilder uriBuilder, out Uri canonicalUri) {
- uriBuilder.Host = uriBuilder.Host.ToLowerInvariant();
- canonicalUri = uriBuilder.Uri;
+ private static bool TryCanonicalize(string uri, out Uri canonicalUri) {
+ Contract.Requires<ArgumentNullException>(uri != null);
+
+ if (schemeSubstitution) {
+ UriBuilder uriBuilder = new UriBuilder(uri);
+
+ // Swap out our round-trippable scheme for the publishable (hidden) scheme.
+ uriBuilder.Scheme = uriBuilder.Scheme == roundTrippingHttpParser.RegisteredScheme ? publishableHttpParser.RegisteredScheme : publishableHttpsParser.RegisteredScheme;
+ canonicalUri = uriBuilder.Uri;
+ } else {
+ canonicalUri = new Uri(uri);
+ }
+
return true;
}
+ /// <summary>
+ /// Gets the special non-compressing scheme or URL for a standard scheme or URL.
+ /// </summary>
+ /// <param name="normal">The ordinary URL or scheme name.</param>
+ /// <returns>The non-compressing equivalent scheme or URL for the given value.</returns>
+ private static string NormalSchemeToSpecialRoundTrippingScheme(string normal) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(normal));
+ Contract.Requires<InternalErrorException>(schemeSubstitution);
+ Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
+
+ int delimiterIndex = normal.IndexOf(Uri.SchemeDelimiter);
+ string normalScheme = delimiterIndex < 0 ? normal : normal.Substring(0, delimiterIndex);
+ string nonCompressingScheme;
+ if (string.Equals(normalScheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(normalScheme, publishableHttpParser.RegisteredScheme, StringComparison.OrdinalIgnoreCase)) {
+ nonCompressingScheme = roundTrippingHttpParser.RegisteredScheme;
+ } else if (string.Equals(normalScheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(normalScheme, publishableHttpsParser.RegisteredScheme, StringComparison.OrdinalIgnoreCase)) {
+ nonCompressingScheme = roundTrippingHttpsParser.RegisteredScheme;
+ } else {
+ throw new NotSupportedException();
+ }
+
+ return delimiterIndex < 0 ? nonCompressingScheme : nonCompressingScheme + normal.Substring(delimiterIndex);
+ }
+
#if CONTRACTS_FULL
/// <summary>
/// Verifies conditions that should be true for any valid state of this object.
@@ -470,5 +506,193 @@ namespace DotNetOpenAuth.OpenId {
Contract.Invariant(this.Uri.AbsoluteUri != null);
}
#endif
+
+ /// <summary>
+ /// A simple URI class that doesn't suffer from the parsing problems of the <see cref="Uri"/> class.
+ /// </summary>
+ internal class SimpleUri {
+ /// <summary>
+ /// URI characters that separate the URI Path from subsequent elements.
+ /// </summary>
+ private static readonly char[] PathEndingCharacters = new char[] { '?', '#' };
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SimpleUri"/> class.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ internal SimpleUri(string value) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(value));
+
+ // Leverage the Uri class's parsing where we can.
+ Uri uri = new Uri(value);
+ this.Scheme = uri.Scheme;
+ this.Authority = uri.Authority;
+ this.Query = uri.Query;
+ this.Fragment = uri.Fragment;
+
+ // Get the Path out ourselves, since the default Uri parser compresses it too much for OpenID.
+ int schemeLength = value.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal);
+ Contract.Assume(schemeLength > 0);
+ int hostStart = schemeLength + Uri.SchemeDelimiter.Length;
+ int hostFinish = value.IndexOf('/', hostStart);
+ if (hostFinish < 0) {
+ this.Path = "/";
+ } else {
+ int pathFinish = value.IndexOfAny(PathEndingCharacters, hostFinish);
+ Contract.Assume(pathFinish >= hostFinish || pathFinish < 0);
+ if (pathFinish < 0) {
+ this.Path = value.Substring(hostFinish);
+ } else {
+ this.Path = value.Substring(hostFinish, pathFinish - hostFinish);
+ }
+ }
+
+ this.Path = NormalizePathEscaping(this.Path);
+ }
+
+ /// <summary>
+ /// Gets the scheme.
+ /// </summary>
+ /// <value>The scheme.</value>
+ public string Scheme { get; private set; }
+
+ /// <summary>
+ /// Gets the authority.
+ /// </summary>
+ /// <value>The authority.</value>
+ public string Authority { get; private set; }
+
+ /// <summary>
+ /// Gets the path of the URI.
+ /// </summary>
+ /// <value>The path from the URI.</value>
+ public string Path { get; private set; }
+
+ /// <summary>
+ /// Gets the query.
+ /// </summary>
+ /// <value>The query.</value>
+ public string Query { get; private set; }
+
+ /// <summary>
+ /// Gets the fragment.
+ /// </summary>
+ /// <value>The fragment.</value>
+ public string Fragment { get; private set; }
+
+ /// <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() {
+ return this.Scheme + Uri.SchemeDelimiter + this.Authority + this.Path + this.Query + this.Fragment;
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
+ /// </summary>
+ /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
+ /// </returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <paramref name="obj"/> parameter is null.
+ /// </exception>
+ public override bool Equals(object obj) {
+ SimpleUri other = obj as SimpleUri;
+ if (other == null) {
+ return false;
+ }
+
+ // Note that this equality check is intentionally leaving off the Fragment part
+ // to match Uri behavior, and is intentionally being case sensitive and insensitive
+ // for different parts.
+ return string.Equals(this.Scheme, other.Scheme, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals(this.Authority, other.Authority, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals(this.Path, other.Path, StringComparison.Ordinal) &&
+ string.Equals(this.Query, other.Query, StringComparison.Ordinal);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this instance.
+ /// </summary>
+ /// <returns>
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ /// </returns>
+ public override int GetHashCode() {
+ int hashCode = 0;
+ hashCode += StringComparer.OrdinalIgnoreCase.GetHashCode(this.Scheme);
+ hashCode += StringComparer.OrdinalIgnoreCase.GetHashCode(this.Authority);
+ hashCode += StringComparer.Ordinal.GetHashCode(this.Path);
+ hashCode += StringComparer.Ordinal.GetHashCode(this.Query);
+ return hashCode;
+ }
+
+ /// <summary>
+ /// Normalizes the characters that are escaped in the given URI path.
+ /// </summary>
+ /// <param name="path">The path to normalize.</param>
+ /// <returns>The given path, with exactly those characters escaped which should be.</returns>
+ private static string NormalizePathEscaping(string path) {
+ Contract.Requires<ArgumentNullException>(path != null);
+
+ string[] segments = path.Split('/');
+ for (int i = 0; i < segments.Length; i++) {
+ segments[i] = Uri.EscapeDataString(Uri.UnescapeDataString(segments[i]));
+ }
+
+ return string.Join("/", segments);
+ }
+ }
+
+ /// <summary>
+ /// A URI parser that does not compress paths, such as trimming trailing periods from path segments.
+ /// </summary>
+ private class NonPathCompressingUriParser : GenericUriParser {
+ /// <summary>
+ /// The field that stores the scheme that this parser is registered under.
+ /// </summary>
+ private static FieldInfo schemeField;
+
+ /// <summary>
+ /// The standard "http" or "https" scheme that this parser is subverting.
+ /// </summary>
+ private string standardScheme;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NonPathCompressingUriParser"/> class.
+ /// </summary>
+ /// <param name="standardScheme">The standard scheme that this parser will be subverting.</param>
+ public NonPathCompressingUriParser(string standardScheme)
+ : base(GenericUriParserOptions.DontCompressPath | GenericUriParserOptions.IriParsing | GenericUriParserOptions.Idn) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(standardScheme));
+ this.standardScheme = standardScheme;
+ }
+
+ /// <summary>
+ /// Gets the scheme this parser is registered under.
+ /// </summary>
+ /// <value>The registered scheme.</value>
+ internal string RegisteredScheme { get; private set; }
+
+ /// <summary>
+ /// Initializes this parser with the actual scheme it should appear to be.
+ /// </summary>
+ /// <param name="hideNonStandardScheme">if set to <c>true</c> Uris using this scheme will look like they're using the original standard scheme.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "Schemes are traditionally displayed in lowercase.")]
+ internal void Initialize(bool hideNonStandardScheme) {
+ if (schemeField == null) {
+ schemeField = typeof(UriParser).GetField("m_Scheme", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+
+ this.RegisteredScheme = (string)schemeField.GetValue(this);
+
+ if (hideNonStandardScheme) {
+ schemeField.SetValue(this, this.standardScheme.ToLowerInvariant());
+ }
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs b/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs
new file mode 100644
index 0000000..b1a3430
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs
@@ -0,0 +1,108 @@
+//-----------------------------------------------------------------------
+// <copyright file="XriDiscoveryProxyService.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Linq;
+ using System.Text;
+ using System.Xml;
+ using DotNetOpenAuth.Configuration;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Xrds;
+ using DotNetOpenAuth.Yadis;
+
+ /// <summary>
+ /// The discovery service for XRI identifiers that uses an XRI proxy resolver for discovery.
+ /// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Justification = "Acronym")]
+ public class XriDiscoveryProxyService : IIdentifierDiscoveryService {
+ /// <summary>
+ /// The magic URL that will provide us an XRDS document for a given XRI identifier.
+ /// </summary>
+ /// <remarks>
+ /// We use application/xrd+xml instead of application/xrds+xml because it gets
+ /// xri.net to automatically give us exactly the right XRD element for community i-names
+ /// automatically, saving us having to choose which one to use out of the result.
+ /// The ssl=true parameter tells the proxy resolver to accept only SSL connections
+ /// when resolving community i-names.
+ /// </remarks>
+ private const string XriResolverProxyTemplate = "https://{1}/{0}?_xrd_r=application/xrd%2Bxml;sep=false";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="XriDiscoveryProxyService"/> class.
+ /// </summary>
+ public XriDiscoveryProxyService() {
+ }
+
+ #region IDiscoveryService Members
+
+ /// <summary>
+ /// Performs discovery on the specified identifier.
+ /// </summary>
+ /// <param name="identifier">The identifier to perform discovery on.</param>
+ /// <param name="requestHandler">The means to place outgoing HTTP requests.</param>
+ /// <param name="abortDiscoveryChain">if set to <c>true</c>, no further discovery services will be called for this identifier.</param>
+ /// <returns>
+ /// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
+ /// </returns>
+ public IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain) {
+ abortDiscoveryChain = false;
+ var xriIdentifier = identifier as XriIdentifier;
+ if (xriIdentifier == null) {
+ return Enumerable.Empty<IdentifierDiscoveryResult>();
+ }
+
+ return DownloadXrds(xriIdentifier, requestHandler).XrdElements.CreateServiceEndpoints(xriIdentifier);
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Downloads the XRDS document for this XRI.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <returns>The XRDS document.</returns>
+ private static XrdsDocument DownloadXrds(XriIdentifier identifier, IDirectWebRequestHandler requestHandler) {
+ Contract.Requires<ArgumentNullException>(identifier != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Ensures(Contract.Result<XrdsDocument>() != null);
+ XrdsDocument doc;
+ using (var xrdsResponse = Yadis.Request(requestHandler, GetXrdsUrl(identifier), identifier.IsDiscoverySecureEndToEnd)) {
+ doc = new XrdsDocument(XmlReader.Create(xrdsResponse.ResponseStream));
+ }
+ ErrorUtilities.VerifyProtocol(doc.IsXrdResolutionSuccessful, OpenIdStrings.XriResolutionFailed);
+ return doc;
+ }
+
+ /// <summary>
+ /// Gets the URL from which this XRI's XRDS document may be downloaded.
+ /// </summary>
+ /// <param name="identifier">The identifier.</param>
+ /// <returns>The URI to HTTP GET from to get the services.</returns>
+ private static Uri GetXrdsUrl(XriIdentifier identifier) {
+ ErrorUtilities.VerifyProtocol(DotNetOpenAuthSection.Configuration.OpenId.XriResolver.Enabled, OpenIdStrings.XriResolutionDisabled);
+ string xriResolverProxy = XriResolverProxyTemplate;
+ if (identifier.IsDiscoverySecureEndToEnd) {
+ // Indicate to xri.net that we require SSL to be used for delegated resolution
+ // of community i-names.
+ xriResolverProxy += ";https=true";
+ }
+
+ return new Uri(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ xriResolverProxy,
+ identifier,
+ DotNetOpenAuthSection.Configuration.OpenId.XriResolver.Proxy.Name));
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
index baba2e5..729f603 100644
--- a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
@@ -35,23 +35,6 @@ namespace DotNetOpenAuth.OpenId {
private const string XriScheme = "xri://";
/// <summary>
- /// The magic URL that will provide us an XRDS document for a given XRI identifier.
- /// </summary>
- /// <remarks>
- /// We use application/xrd+xml instead of application/xrds+xml because it gets
- /// xri.net to automatically give us exactly the right XRD element for community i-names
- /// automatically, saving us having to choose which one to use out of the result.
- /// The ssl=true parameter tells the proxy resolver to accept only SSL connections
- /// when resolving community i-names.
- /// </remarks>
- private const string XriResolverProxyTemplate = "https://{1}/{0}?_xrd_r=application/xrd%2Bxml;sep=false";
-
- /// <summary>
- /// The XRI proxy resolver to use for finding XRDS documents from an XRI.
- /// </summary>
- private readonly string xriResolverProxy;
-
- /// <summary>
/// Backing store for the <see cref="CanonicalXri"/> property.
/// </summary>
private readonly string canonicalXri;
@@ -79,12 +62,6 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(xri));
Contract.Requires<FormatException>(IsValidXri(xri), OpenIdStrings.InvalidXri);
Contract.Assume(xri != null); // Proven by IsValidXri
- this.xriResolverProxy = XriResolverProxyTemplate;
- if (requireSsl) {
- // Indicate to xri.net that we require SSL to be used for delegated resolution
- // of community i-names.
- this.xriResolverProxy += ";https=true";
- }
this.OriginalXri = xri;
this.canonicalXri = CanonicalizeXri(xri);
}
@@ -105,21 +82,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Gets the URL from which this XRI's XRDS document may be downloaded.
- /// </summary>
- private Uri XrdsUrl {
- get {
- ErrorUtilities.VerifyProtocol(DotNetOpenAuthSection.Configuration.OpenId.XriResolver.Enabled, OpenIdStrings.XriResolutionDisabled);
- return new Uri(
- string.Format(
- CultureInfo.InvariantCulture,
- this.xriResolverProxy,
- this,
- DotNetOpenAuthSection.Configuration.OpenId.XriResolver.Proxy.Name));
- }
- }
-
- /// <summary>
/// Tests equality between this XRI and another XRI.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
@@ -180,30 +142,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Performs discovery on the Identifier.
- /// </summary>
- /// <param name="requestHandler">The web request handler to use for discovery.</param>
- /// <returns>
- /// An initialized structure containing the discovered provider endpoint information.
- /// </returns>
- internal override IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler) {
- return this.DownloadXrds(requestHandler).CreateServiceEndpoints(this);
- }
-
- /// <summary>
- /// Performs discovery on THIS identifier, but generates <see cref="ServiceEndpoint"/>
- /// instances that treat another given identifier as the user-supplied identifier.
- /// </summary>
- /// <param name="requestHandler">The request handler to use in discovery.</param>
- /// <param name="userSuppliedIdentifier">The user supplied identifier, which may differ from this XRI instance due to multiple discovery steps.</param>
- /// <returns>A list of service endpoints offered for this identifier.</returns>
- internal IEnumerable<ServiceEndpoint> Discover(IDirectWebRequestHandler requestHandler, XriIdentifier userSuppliedIdentifier) {
- Contract.Requires<ArgumentNullException>(requestHandler != null);
- Contract.Requires<ArgumentNullException>(userSuppliedIdentifier != null);
- return this.DownloadXrds(requestHandler).CreateServiceEndpoints(userSuppliedIdentifier);
- }
-
- /// <summary>
/// Returns an <see cref="Identifier"/> that has no URI fragment.
/// Quietly returns the original <see cref="Identifier"/> if it is not
/// a <see cref="UriIdentifier"/> or no fragment exists.
@@ -255,22 +193,6 @@ namespace DotNetOpenAuth.OpenId {
return xri;
}
- /// <summary>
- /// Downloads the XRDS document for this XRI.
- /// </summary>
- /// <param name="requestHandler">The request handler.</param>
- /// <returns>The XRDS document.</returns>
- private XrdsDocument DownloadXrds(IDirectWebRequestHandler requestHandler) {
- Contract.Requires<ArgumentNullException>(requestHandler != null);
- Contract.Ensures(Contract.Result<XrdsDocument>() != null);
- XrdsDocument doc;
- using (var xrdsResponse = Yadis.Request(requestHandler, this.XrdsUrl, this.IsDiscoverySecureEndToEnd)) {
- doc = new XrdsDocument(XmlReader.Create(xrdsResponse.ResponseStream));
- }
- ErrorUtilities.VerifyProtocol(doc.IsXrdResolutionSuccessful, OpenIdStrings.XriResolutionFailed);
- return doc;
- }
-
#if CONTRACTS_FULL
/// <summary>
/// Verifies conditions that should be true for any valid state of this object.
@@ -279,7 +201,6 @@ namespace DotNetOpenAuth.OpenId {
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")]
[ContractInvariantMethod]
private void ObjectInvariant() {
- Contract.Invariant(this.xriResolverProxy != null);
Contract.Invariant(this.canonicalXri != null);
}
#endif
diff --git a/src/DotNetOpenAuth/Reporting.cs b/src/DotNetOpenAuth/Reporting.cs
index 2235986..612845f 100644
--- a/src/DotNetOpenAuth/Reporting.cs
+++ b/src/DotNetOpenAuth/Reporting.cs
@@ -30,7 +30,27 @@ namespace DotNetOpenAuth {
/// The statistical reporting mechanism used so this library's project authors
/// know what versions and features are in use.
/// </summary>
- internal static class Reporting {
+ public static class Reporting {
+ /// <summary>
+ /// A value indicating whether reporting is desirable or not. Must be logical-AND'd with !<see cref="broken"/>.
+ /// </summary>
+ private static bool enabled;
+
+ /// <summary>
+ /// A value indicating whether reporting experienced an error and cannot be enabled.
+ /// </summary>
+ private static bool broken;
+
+ /// <summary>
+ /// A value indicating whether the reporting class has been initialized or not.
+ /// </summary>
+ private static bool initialized;
+
+ /// <summary>
+ /// The object to lock during initialization.
+ /// </summary>
+ private static object initializationSync = new object();
+
/// <summary>
/// The isolated storage to use for collecting data in between published reports.
/// </summary>
@@ -93,37 +113,31 @@ namespace DotNetOpenAuth {
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reporting MUST NOT cause unhandled exceptions.")]
static Reporting() {
Enabled = DotNetOpenAuthSection.Configuration.Reporting.Enabled;
- if (Enabled) {
- try {
- file = GetIsolatedStorage();
- reportOriginIdentity = GetOrCreateOriginIdentity();
-
- webRequestHandler = new StandardWebRequestHandler();
- observations.Add(observedRequests = new PersistentHashSet(file, "requests.txt", 3));
- observations.Add(observedCultures = new PersistentHashSet(file, "cultures.txt", 20));
- observations.Add(observedFeatures = new PersistentHashSet(file, "features.txt", int.MaxValue));
-
- // Record site-wide features in use.
- if (HttpContext.Current != null && HttpContext.Current.ApplicationInstance != null) {
- // MVC or web forms?
- // front-end or back end web farm?
- // url rewriting?
- ////RecordFeatureUse(IsMVC ? "ASP.NET MVC" : "ASP.NET Web Forms");
- }
- } catch (Exception e) {
- // This is supposed to be as low-risk as possible, so if it fails, just disable reporting
- // and avoid rethrowing.
- Enabled = false;
- Logger.Library.Error("Error while trying to initialize reporting.", e);
- }
- }
}
/// <summary>
/// Gets or sets a value indicating whether this reporting is enabled.
/// </summary>
/// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
- internal static bool Enabled { get; set; }
+ /// <remarks>
+ /// Setting this property to <c>true</c> <i>may</i> have no effect
+ /// if reporting has already experienced a failure of some kind.
+ /// </remarks>
+ public static bool Enabled {
+ get {
+ return enabled && !broken;
+ }
+
+ set {
+ if (value) {
+ Initialize();
+ }
+
+ // Only set the static field here, so that other threads
+ // don't try to use reporting while we're initializing it.
+ enabled = value;
+ }
+ }
/// <summary>
/// Gets the configuration to use for reporting.
@@ -137,6 +151,7 @@ namespace DotNetOpenAuth {
/// </summary>
/// <param name="eventName">Name of the event.</param>
/// <param name="category">The category within the event. Null and empty strings are allowed, but considered the same.</param>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "PersistentCounter instances are stored in a table for later use.")]
internal static void RecordEventOccurrence(string eventName, string category) {
Contract.Requires(!String.IsNullOrEmpty(eventName));
@@ -302,49 +317,89 @@ namespace DotNetOpenAuth {
}
/// <summary>
+ /// Initializes Reporting if it has not been initialized yet.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method must never throw.")]
+ private static void Initialize() {
+ lock (initializationSync) {
+ if (!broken && !initialized) {
+ try {
+ file = GetIsolatedStorage();
+ reportOriginIdentity = GetOrCreateOriginIdentity();
+
+ webRequestHandler = new StandardWebRequestHandler();
+ observations.Add(observedRequests = new PersistentHashSet(file, "requests.txt", 3));
+ observations.Add(observedCultures = new PersistentHashSet(file, "cultures.txt", 20));
+ observations.Add(observedFeatures = new PersistentHashSet(file, "features.txt", int.MaxValue));
+
+ // Record site-wide features in use.
+ if (HttpContext.Current != null && HttpContext.Current.ApplicationInstance != null) {
+ // MVC or web forms?
+ // front-end or back end web farm?
+ // url rewriting?
+ ////RecordFeatureUse(IsMVC ? "ASP.NET MVC" : "ASP.NET Web Forms");
+ }
+
+ initialized = true;
+ } catch (Exception e) {
+ // This is supposed to be as low-risk as possible, so if it fails, just disable reporting
+ // and avoid rethrowing.
+ broken = true;
+ Logger.Library.Error("Error while trying to initialize reporting.", e);
+ }
+ }
+ }
+ }
+
+ /// <summary>
/// Assembles a report for submission.
/// </summary>
/// <returns>A stream that contains the report.</returns>
private static Stream GetReport() {
var stream = new MemoryStream();
- var writer = new StreamWriter(stream, Encoding.UTF8);
- writer.WriteLine(reportOriginIdentity.ToString("B"));
- writer.WriteLine(Util.LibraryVersion);
- writer.WriteLine(".NET Framework {0}", Environment.Version);
-
- foreach (var observation in observations) {
- observation.Flush();
- writer.WriteLine("====================================");
- writer.WriteLine(observation.FileName);
- try {
- using (var fileStream = new IsolatedStorageFileStream(observation.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, file)) {
- writer.Flush();
- fileStream.CopyTo(writer.BaseStream);
+ try {
+ var writer = new StreamWriter(stream, Encoding.UTF8);
+ writer.WriteLine(reportOriginIdentity.ToString("B"));
+ writer.WriteLine(Util.LibraryVersion);
+ writer.WriteLine(".NET Framework {0}", Environment.Version);
+
+ foreach (var observation in observations) {
+ observation.Flush();
+ writer.WriteLine("====================================");
+ writer.WriteLine(observation.FileName);
+ try {
+ using (var fileStream = new IsolatedStorageFileStream(observation.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, file)) {
+ writer.Flush();
+ fileStream.CopyTo(writer.BaseStream);
+ }
+ } catch (FileNotFoundException) {
+ writer.WriteLine("(missing)");
}
- } catch (FileNotFoundException) {
- writer.WriteLine("(missing)");
}
- }
- // Not all event counters may have even loaded in this app instance.
- // We flush the ones in memory, and then read all of them off disk.
- foreach (var counter in events.Values) {
- counter.Flush();
- }
+ // Not all event counters may have even loaded in this app instance.
+ // We flush the ones in memory, and then read all of them off disk.
+ foreach (var counter in events.Values) {
+ counter.Flush();
+ }
- foreach (string eventFile in file.GetFileNames("event-*.txt")) {
- writer.WriteLine("====================================");
- writer.WriteLine(eventFile);
- using (var fileStream = new IsolatedStorageFileStream(eventFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, file)) {
- writer.Flush();
- fileStream.CopyTo(writer.BaseStream);
+ foreach (string eventFile in file.GetFileNames("event-*.txt")) {
+ writer.WriteLine("====================================");
+ writer.WriteLine(eventFile);
+ using (var fileStream = new IsolatedStorageFileStream(eventFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, file)) {
+ writer.Flush();
+ fileStream.CopyTo(writer.BaseStream);
+ }
}
- }
- // Make sure the stream is positioned at the beginning.
- writer.Flush();
- stream.Position = 0;
- return stream;
+ // Make sure the stream is positioned at the beginning.
+ writer.Flush();
+ stream.Position = 0;
+ return stream;
+ } catch {
+ stream.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -459,7 +514,7 @@ namespace DotNetOpenAuth {
} catch (Exception ex) {
// Something bad and unexpected happened. Just deactivate to avoid more trouble.
Logger.Library.Error("Error while trying to submit statistical report.", ex);
- Enabled = false;
+ broken = true;
}
});
}
diff --git a/src/DotNetOpenAuth/Strings.Designer.cs b/src/DotNetOpenAuth/Strings.Designer.cs
index 38c89f7..70b9fb2 100644
--- a/src/DotNetOpenAuth/Strings.Designer.cs
+++ b/src/DotNetOpenAuth/Strings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.4927
+// Runtime Version:4.0.30104.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Strings {
@@ -70,20 +70,20 @@ namespace DotNetOpenAuth {
}
/// <summary>
- /// Looks up a localized string similar to No current HttpContext was detected, so an {0} instance must be explicitly provided or specified in the .config file. Call the constructor overload that takes an {0}..
+ /// Looks up a localized string similar to The configuration XAML reference to {0} requires a current HttpContext to resolve..
/// </summary>
- internal static string StoreRequiredWhenNoHttpContextAvailable {
+ internal static string ConfigurationXamlReferenceRequiresHttpContext {
get {
- return ResourceManager.GetString("StoreRequiredWhenNoHttpContextAvailable", resourceCulture);
+ return ResourceManager.GetString("ConfigurationXamlReferenceRequiresHttpContext", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to The configuration XAML reference to {0} requires a current HttpContext to resolve..
+ /// Looks up a localized string similar to No current HttpContext was detected, so an {0} instance must be explicitly provided or specified in the .config file. Call the constructor overload that takes an {0}..
/// </summary>
- internal static string ConfigurationXamlReferenceRequiresHttpContext {
+ internal static string StoreRequiredWhenNoHttpContextAvailable {
get {
- return ResourceManager.GetString("ConfigurationXamlReferenceRequiresHttpContext", resourceCulture);
+ return ResourceManager.GetString("StoreRequiredWhenNoHttpContextAvailable", resourceCulture);
}
}
}
diff --git a/src/DotNetOpenAuth/Util.cs b/src/DotNetOpenAuth/Util.cs
index 9f8b30c..8a18ef8 100644
--- a/src/DotNetOpenAuth/Util.cs
+++ b/src/DotNetOpenAuth/Util.cs
@@ -126,7 +126,7 @@ namespace DotNetOpenAuth {
sb.Append("\t");
sb.Append(objString);
- if (!objString.EndsWith(Environment.NewLine)) {
+ if (!objString.EndsWith(Environment.NewLine, StringComparison.Ordinal)) {
sb.AppendLine();
}
sb.AppendLine("}, {");
diff --git a/src/DotNetOpenAuth/Xrds/XrdElement.cs b/src/DotNetOpenAuth/Xrds/XrdElement.cs
index a8cc145..2cdc720 100644
--- a/src/DotNetOpenAuth/Xrds/XrdElement.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdElement.cs
@@ -133,7 +133,7 @@ namespace DotNetOpenAuth.Xrds {
/// </summary>
/// <param name="p">A function that selects what element of the OpenID Protocol we're interested in finding.</param>
/// <returns>A sequence of service elements that match the search criteria, sorted in XRDS @priority attribute order.</returns>
- private IEnumerable<ServiceElement> SearchForServiceTypeUris(Func<Protocol, string> p) {
+ internal IEnumerable<ServiceElement> SearchForServiceTypeUris(Func<Protocol, string> p) {
var xpath = new StringBuilder();
xpath.Append("xrd:Service[");
foreach (var protocol in Protocol.AllVersions) {
diff --git a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
index dd0e19f..e2c2d72 100644
--- a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
@@ -18,6 +18,16 @@ namespace DotNetOpenAuth.Xrds {
/// </summary>
internal class XrdsDocument : XrdsNode {
/// <summary>
+ /// The namespace used by XML digital signatures.
+ /// </summary>
+ private const string XmlDSigNamespace = "http://www.w3.org/2000/09/xmldsig#";
+
+ /// <summary>
+ /// The namespace used by Google Apps for Domains for OpenID URI templates.
+ /// </summary>
+ private const string GoogleOpenIdNamespace = "http://namespace.google.com/openid/xmlns";
+
+ /// <summary>
/// Initializes a new instance of the <see cref="XrdsDocument"/> class.
/// </summary>
/// <param name="xrdsNavigator">The root node of the XRDS document.</param>
@@ -26,6 +36,8 @@ namespace DotNetOpenAuth.Xrds {
XmlNamespaceResolver.AddNamespace("xrd", XrdsNode.XrdNamespace);
XmlNamespaceResolver.AddNamespace("xrds", XrdsNode.XrdsNamespace);
XmlNamespaceResolver.AddNamespace("openid10", Protocol.V10.XmlNamespace);
+ XmlNamespaceResolver.AddNamespace("ds", XmlDSigNamespace);
+ XmlNamespaceResolver.AddNamespace("google", GoogleOpenIdNamespace);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Xrds/XrdsNode.cs b/src/DotNetOpenAuth/Xrds/XrdsNode.cs
index f8fa0af..39bd9b9 100644
--- a/src/DotNetOpenAuth/Xrds/XrdsNode.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdsNode.cs
@@ -54,16 +54,16 @@ namespace DotNetOpenAuth.Xrds {
/// <summary>
/// Gets the node.
/// </summary>
- protected XPathNavigator Node { get; private set; }
+ internal XPathNavigator Node { get; private set; }
/// <summary>
/// Gets the parent node, or null if this is the root node.
/// </summary>
- protected XrdsNode ParentNode { get; private set; }
+ protected internal XrdsNode ParentNode { get; private set; }
/// <summary>
/// Gets the XML namespace resolver to use in XPath expressions.
/// </summary>
- protected XmlNamespaceManager XmlNamespaceResolver { get; private set; }
+ protected internal XmlNamespaceManager XmlNamespaceResolver { get; private set; }
}
}
diff --git a/src/DotNetOpenAuth/Xrds/XrdsStrings.Designer.cs b/src/DotNetOpenAuth/Xrds/XrdsStrings.Designer.cs
index 465c990..2279b5f 100644
--- a/src/DotNetOpenAuth/Xrds/XrdsStrings.Designer.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdsStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:2.0.50727.3053
+// Runtime Version:4.0.30104.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -19,7 +19,7 @@ namespace DotNetOpenAuth.Xrds {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class XrdsStrings {
diff --git a/src/DotNetOpenAuth/XrdsPublisher.cs b/src/DotNetOpenAuth/XrdsPublisher.cs
index e7c04d8..83d82ff 100644
--- a/src/DotNetOpenAuth/XrdsPublisher.cs
+++ b/src/DotNetOpenAuth/XrdsPublisher.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth {
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Drawing.Design;
using System.Text;
using System.Web;
@@ -209,6 +210,7 @@ namespace DotNetOpenAuth {
/// <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.")]
protected override void Render(HtmlTextWriter writer) {
+ Contract.Assume(writer != null, "Missing contract.");
if (this.Enabled && this.Visible && !string.IsNullOrEmpty(this.XrdsUrl)) {
Uri xrdsAddress = new Uri(MessagingUtilities.GetRequestUrlFromContext(), Page.Response.ApplyAppPathModifier(this.XrdsUrl));
if ((this.XrdsAdvertisement & XrdsUrlLocations.HttpHeader) != 0) {
diff --git a/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs b/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
index 01dae40..06c6fc7 100644
--- a/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
+++ b/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
@@ -17,6 +17,12 @@ namespace DotNetOpenAuth.Yadis {
/// </summary>
internal class DiscoveryResult {
/// <summary>
+ /// The original web response, backed up here if the final web response is the preferred response to use
+ /// in case it turns out to not work out.
+ /// </summary>
+ private CachedDirectWebResponse htmlFallback;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="DiscoveryResult"/> class.
/// </summary>
/// <param name="requestUri">The user-supplied identifier.</param>
@@ -25,10 +31,8 @@ namespace DotNetOpenAuth.Yadis {
public DiscoveryResult(Uri requestUri, CachedDirectWebResponse initialResponse, CachedDirectWebResponse finalResponse) {
this.RequestUri = requestUri;
this.NormalizedUri = initialResponse.FinalUri;
- if (finalResponse == null) {
- this.ContentType = initialResponse.ContentType;
- this.ResponseText = initialResponse.GetResponseString();
- this.IsXrds = this.ContentType != null && this.ContentType.MediaType == ContentTypes.Xrds;
+ if (finalResponse == null || finalResponse.Status != System.Net.HttpStatusCode.OK) {
+ this.ApplyHtmlResponse(initialResponse);
} else {
this.ContentType = finalResponse.ContentType;
this.ResponseText = finalResponse.GetResponseString();
@@ -36,6 +40,9 @@ namespace DotNetOpenAuth.Yadis {
if (initialResponse != finalResponse) {
this.YadisLocation = finalResponse.RequestUri;
}
+
+ // Back up the initial HTML response in case the XRDS is not useful.
+ this.htmlFallback = initialResponse;
}
}
@@ -77,13 +84,23 @@ namespace DotNetOpenAuth.Yadis {
public bool IsXrds { get; private set; }
/// <summary>
- /// Gets a value indicating whether discovery resulted in an
- /// XRDS document at a referred location.
+ /// Reverts to the HTML response after the XRDS response didn't work out.
+ /// </summary>
+ internal void TryRevertToHtmlResponse() {
+ if (this.htmlFallback != null) {
+ this.ApplyHtmlResponse(this.htmlFallback);
+ this.htmlFallback = null;
+ }
+ }
+
+ /// <summary>
+ /// Applies the HTML response to the object.
/// </summary>
- /// <value><c>true</c> if the response to the userSuppliedIdentifier
- /// pointed to a different URL for the XRDS document.</value>
- public bool UsedYadisLocation {
- get { return this.YadisLocation != null; }
+ /// <param name="initialResponse">The initial response.</param>
+ private void ApplyHtmlResponse(CachedDirectWebResponse initialResponse) {
+ this.ContentType = initialResponse.ContentType;
+ this.ResponseText = initialResponse.GetResponseString();
+ this.IsXrds = this.ContentType != null && this.ContentType.MediaType == ContentTypes.Xrds;
}
}
}
diff --git a/src/DotNetOpenAuth/Yadis/Yadis.cs b/src/DotNetOpenAuth/Yadis/Yadis.cs
index f1c8be3..8b8c20f 100644
--- a/src/DotNetOpenAuth/Yadis/Yadis.cs
+++ b/src/DotNetOpenAuth/Yadis/Yadis.cs
@@ -39,7 +39,7 @@ namespace DotNetOpenAuth.Yadis {
/// The maximum number of bytes to read from an HTTP response
/// in searching for a link to a YADIS document.
/// </summary>
- private const int MaximumResultToScan = 1024 * 1024;
+ internal const int MaximumResultToScan = 1024 * 1024;
/// <summary>
/// Performs YADIS discovery on some identifier.
@@ -96,7 +96,6 @@ namespace DotNetOpenAuth.Yadis {
response2 = Request(requestHandler, url, requireSsl, ContentTypes.Xrds).GetSnapshot(MaximumResultToScan);
if (response2.Status != HttpStatusCode.OK) {
Logger.Yadis.ErrorFormat("HTTP error {0} {1} while performing discovery on {2}.", (int)response2.Status, response2.Status, uri);
- return null;
}
} else {
Logger.Yadis.WarnFormat("XRDS document at insecure location '{0}'. Aborting YADIS discovery.", url);
diff --git a/src/LocalTestRun.testrunconfig b/src/LocalTestRun.testrunconfig
deleted file mode 100644
index f037171..0000000
--- a/src/LocalTestRun.testrunconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<TestRunConfiguration name="Local Test Run" id="abbd81c0-7d7b-4c98-878c-05dbead62c27" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
- <Description>This is a default test run configuration for a local test run.</Description>
- <CodeCoverage enabled="true">
- <Regular>
- <CodeCoverageItem binaryFile="C:\git\dotnetoauth\bin\Debug\DotNetOpenAuth.dll" pdbFile="C:\git\dotnetoauth\bin\Debug\DotNetOpenAuth.pdb" instrumentInPlace="true" />
- </Regular>
- </CodeCoverage>
- <TestTypeSpecific>
- <WebTestRunConfiguration testTypeId="4e7599fa-5ecb-43e9-a887-cd63cf72d207">
- <Browser name="Internet Explorer 7.0">
- <Headers>
- <Header name="User-Agent" value="Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)" />
- <Header name="Accept" value="*/*" />
- <Header name="Accept-Language" value="{{$IEAcceptLanguage}}" />
- <Header name="Accept-Encoding" value="GZIP" />
- </Headers>
- </Browser>
- <Network Name="LAN" BandwidthInKbps="0" />
- </WebTestRunConfiguration>
- </TestTypeSpecific>
-</TestRunConfiguration> \ No newline at end of file
diff --git a/src/version.txt b/src/version.txt
index 4772543..f989260 100644
--- a/src/version.txt
+++ b/src/version.txt
@@ -1 +1 @@
-3.3.2
+3.4.4