summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-09-01 17:34:59 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-09-01 17:34:59 -0700
commit6e8a6eb02294c28b13bacaa339e58a67fd766f99 (patch)
treea1bd58a2a51505ba71b697fb61378e7142df8ef3
parente36299f39476c56977c39700067ed8f6ae0a4e49 (diff)
parent36b1ba3c75d060fa71f6f15582b90e7f70292ddc (diff)
downloadDotNetOpenAuth-6e8a6eb02294c28b13bacaa339e58a67fd766f99.zip
DotNetOpenAuth-6e8a6eb02294c28b13bacaa339e58a67fd766f99.tar.gz
DotNetOpenAuth-6e8a6eb02294c28b13bacaa339e58a67fd766f99.tar.bz2
Merge branch 'master' into contracts
Conflicts: src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs src/DotNetOpenAuth.vsmdi src/DotNetOpenAuth/DotNetOpenAuth.csproj src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs src/DotNetOpenAuth/OAuth/Protocol.cs src/DotNetOpenAuth/OAuth/ServiceProvider.cs src/DotNetOpenAuth/OpenId/Association.cs src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs src/DotNetOpenAuth/OpenId/Provider/IDirectedIdentityIdentifierProvider.cs src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs src/DotNetOpenAuth/OpenId/Realm.cs src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs src/DotNetOpenAuth/OpenId/UriIdentifier.cs src/DotNetOpenAuth/OpenId/XriIdentifier.cs src/DotNetOpenAuth/Util.cs
-rw-r--r--LICENSE.txt2
-rw-r--r--build.proj22
-rw-r--r--doc/README.Bin.html30
-rw-r--r--doc/api/Web.config116
-rw-r--r--doc/api/default.aspx35
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.dllbin12288 -> 21504 bytes
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.pdbbin34304 -> 60928 bytes
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.targets4
-rw-r--r--samples/OAuthConsumer/App_Code/InMemoryTokenManager.cs8
-rw-r--r--samples/OAuthConsumerWpf/App.config34
-rw-r--r--samples/OAuthConsumerWpf/Authorize.xaml.cs15
-rw-r--r--samples/OAuthConsumerWpf/MainWindow.xaml116
-rw-r--r--samples/OAuthConsumerWpf/MainWindow.xaml.cs91
-rw-r--r--samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj36
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.disco4
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.wsdl310
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.xsd9
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi1.xsd40
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi2.xsd42
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.cs67
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.svcmap33
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration.svcinfo10
-rw-r--r--samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration91.svcinfo210
-rw-r--r--samples/OAuthServiceProvider/App_Code/DataApi.cs13
-rw-r--r--samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs4
-rw-r--r--samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs9
-rw-r--r--samples/OAuthServiceProvider/App_Code/OAuthConsumer.cs2
-rw-r--r--samples/OAuthServiceProvider/App_Code/OAuthToken.cs2
-rw-r--r--samples/OAuthServiceProvider/App_Code/Utilities.cs26
-rw-r--r--samples/OAuthServiceProvider/Default.aspx3
-rw-r--r--samples/OAuthServiceProvider/Members/Authorize.aspx.cs4
-rw-r--r--samples/OpenIdOfflineProvider/MainWindow.xaml.cs1
-rw-r--r--samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj5
-rw-r--r--samples/OpenIdProviderMvc/Controllers/UserController.cs2
-rw-r--r--samples/OpenIdProviderMvc/Web.config4
-rw-r--r--samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs31
-rw-r--r--samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs31
-rw-r--r--samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs42
-rw-r--r--samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs117
-rw-r--r--samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs46
-rw-r--r--samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj11
-rw-r--r--samples/OpenIdProviderWebForms/Web.config6
-rw-r--r--samples/OpenIdProviderWebForms/access_token.ashx1
-rw-r--r--samples/OpenIdProviderWebForms/access_token.ashx.cs23
-rw-r--r--samples/OpenIdProviderWebForms/decide.aspx4
-rw-r--r--samples/OpenIdProviderWebForms/decide.aspx.cs24
-rw-r--r--samples/OpenIdProviderWebForms/decide.aspx.designer.cs18
-rw-r--r--samples/OpenIdRelyingPartyClassicAsp/login.asp22
-rw-r--r--samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs3
-rw-r--r--samples/OpenIdRelyingPartyMvc/Web.config4
-rw-r--r--samples/OpenIdRelyingPartyWebForms/Global.asax.cs14
-rw-r--r--samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj8
-rw-r--r--samples/OpenIdRelyingPartyWebForms/Web.config8
-rw-r--r--samples/OpenIdRelyingPartyWebForms/ajaxlogin.aspx4
-rw-r--r--samples/OpenIdRelyingPartyWebForms/login.aspx6
-rw-r--r--samples/OpenIdRelyingPartyWebForms/login.aspx.cs4
-rw-r--r--samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs9
-rw-r--r--samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx34
-rw-r--r--samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs62
-rw-r--r--samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs88
-rw-r--r--samples/OpenIdRelyingPartyWebForms/logout.aspx1
-rw-r--r--samples/OpenIdRelyingPartyWebForms/xrds.aspx4
-rw-r--r--src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs95
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs66
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj19
-rw-r--r--src/DotNetOpenAuth.BuildTasks/FilterItems.cs24
-rw-r--r--src/DotNetOpenAuth.BuildTasks/SnToolTask.cs11
-rw-r--r--src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs99
-rw-r--r--src/DotNetOpenAuth.BuildTasks/TaskStrings.resx132
-rw-r--r--src/DotNetOpenAuth.BuildTasks/Trim.cs56
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj2
-rw-r--r--src/DotNetOpenAuth.Test/Hosting/HostingTests.cs18
-rw-r--r--src/DotNetOpenAuth.Test/LocalizationTests.cs28
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs44
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs4
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs2
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockRealm.cs42
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs13
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs23
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs41
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs14
-rw-r--r--src/DotNetOpenAuth.sln3
-rw-r--r--src/DotNetOpenAuth.vsmdi242
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd269
-rw-r--r--src/DotNetOpenAuth/Configuration/OAuthConsumerSecuritySettingsElement.cs2
-rw-r--r--src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs18
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj24
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs1
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs42
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs11
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardStrings.resx3
-rw-r--r--src/DotNetOpenAuth/InfoCard/InfoCardStrings.sr.resx135
-rw-r--r--src/DotNetOpenAuth/Loggers/Log4NetLogger.cs6
-rw-r--r--src/DotNetOpenAuth/Messaging/Bindings/NonceMemoryStore.cs4
-rw-r--r--src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs41
-rw-r--r--src/DotNetOpenAuth/Messaging/HostErrorException.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs15
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs17
-rw-r--r--src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs3
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.sr.resx294
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs68
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs3
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs14
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs13
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthHttpMethodBindingElement.cs12
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthIdentity.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthPrincipal.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs7
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs18
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/MessageBase.cs1
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/UnauthorizedTokenResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationRequest.cs1
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationResponse.cs1
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.sr.resx162
-rw-r--r--src/DotNetOpenAuth/OAuth/Protocol.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ServiceProvider.cs66
-rw-r--r--src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs4
-rw-r--r--src/DotNetOpenAuth/OAuth/WebConsumer.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/Association.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.sr.resx123
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs31
-rw-r--r--src/DotNetOpenAuth/OpenId/DiffieHellmanUtilities.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/DateTimeEncoder.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIConstants.cs28
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs25
-rw-r--r--src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Identifier.cs25
-rw-r--r--src/DotNetOpenAuth/OpenId/IdentifierContract.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs26
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs29
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx11
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.sr.resx340
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Realm.cs29
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs27
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/Controls.cd112
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs887
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.js531
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs308
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cd1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs10
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs303
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js538
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs388
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js5
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs883
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs43
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs (renamed from src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationResponseSnapshot.cs)8
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs115
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/WellKnownProviders.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/UriIdentifier.cs24
-rw-r--r--src/DotNetOpenAuth/OpenId/XriIdentifier.cs5
-rw-r--r--src/DotNetOpenAuth/Strings.sr.resx126
-rw-r--r--src/DotNetOpenAuth/Util.cs2
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsStrings.sr.resx132
-rw-r--r--src/version.txt2
-rw-r--r--tools/DotNetOpenAuth.Versioning.targets3
-rw-r--r--tools/Publish.targets122
-rw-r--r--tools/Sandcastle/Presentation/vs2005/Content/feedBack_content.xml2
-rw-r--r--tools/Sandcastle/Presentation/vs2005/Content/shared_content.xml2
186 files changed, 6812 insertions, 2718 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
index a3f32e1..906ff2c 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -4,7 +4,7 @@ Every file is bound by the following copyright and license unless explicitly
indicated otherwise in and/or for any individual file.
-Copyright (c) 2008, Andrew Arnott
+Copyright (c) 2008-2009, Andrew Arnott
All rights reserved.
Microsoft Public License (Ms-PL)
diff --git a/build.proj b/build.proj
index 2850a5e..c500d6b 100644
--- a/build.proj
+++ b/build.proj
@@ -9,6 +9,7 @@
<Import Project="$(ProjectRoot)\tools\$(ProductName).Versioning.targets"/>
<Import Project="$(ProjectRoot)\tools\Documentation.targets"/>
+ <Import Project="$(ProjectRoot)\tools\Publish.targets"/>
<UsingTask AssemblyFile="$(ProjectRoot)\lib\MSBuild.Community.Tasks.dll" TaskName="Zip"/>
<UsingTask AssemblyFile="$(ProjectRoot)\lib\MSBuild.Community.Tasks.dll" TaskName="ILMerge"/>
@@ -19,10 +20,12 @@
$(ProjectRoot)\lib\Microsoft.Contracts.dll; "/>
<DelaySignedAssemblies Include="$(ILMergeOutputAssembly);
$(OutputPath)\$(ProductName).dll;
- $(OutputPath)\$(ProductName).Test.dll" />
+ $(OutputPath)\$(ProductName).Contracts.dll;
+ $(OutputPath)\$(ProductName).Test.dll;
+ $(ProjectRoot)\samples\OpenIdOfflineProvider\bin\$(Configuration)\OpenIdOfflineProvider.exe" />
</ItemGroup>
- <Target Name="Clean" DependsOnTargets="CleanDocumentation">
+ <Target Name="Clean" DependsOnTargets="CleanDocumentation;UnpublishSamples;UnpublishDocumentation">
<MSBuild Projects="$(SolutionPath)" Targets="Clean" />
<ItemGroup>
<DirtyDirectories Include="
@@ -45,9 +48,7 @@
</Target>
<Target Name="SkipVerification" Condition="'$(IsElevated)' == 'true'">
- <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName)" PublicKeyToken="$(PublicKeyToken)" />
- <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName)_Accessor" PublicKeyToken="$(PublicKeyToken)" />
- <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName).Test" PublicKeyToken="$(PublicKeyToken)" />
+ <SignatureVerification SkipVerification="true" AssemblyName="*" PublicKeyToken="$(PublicKeyToken)" />
</Target>
<Target Name="BuildProduct" DependsOnTargets="SkipVerification">
@@ -88,7 +89,8 @@
<Message Text="Signing delay-signed assemblies." />
<ReSignDelaySignedAssemblies
KeyContainer="$(KeyPairContainer)"
- Assemblies="@(DelaySignedAssemblies)" />
+ Assemblies="@(DelaySignedAssemblies)"
+ Condition="Exists(%(Identity))" />
</Target>
<Target Name="ToolsLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;BuildUnifiedProduct">
@@ -176,9 +178,11 @@
Exclude="$(ProjectRoot)\Doc\README.*.html;" />
<DropBinSourceFiles Include="
$(ILMergeOutputAssemblyDirectory)\$(ProductName).???;
+ $(OutputPath)\**\$(ProductName).resources.dll;
$(OutputPath)\$(ProductName).xml;
$(OutputPath)\$(ProductName).Contracts.???;
$(ProjectRoot)\Doc\README.Bin.html;
+ $(ProjectRoot)\src\$(ProductName)\Configuration\$(ProductName).xsd;
" />
<DropLibSourceFiles Include="
$(ProjectRoot)\Lib\log4net.*;
@@ -197,6 +201,8 @@
$(ProjectRoot)\**\Settings.StyleCop;
$(ProjectRoot)\Samples\**\DotNetOpenAuth.???;
$(ProjectRoot)\Samples\**\log4net.???;
+ $(ProjectRoot)\Samples\**\PresentationCore.dll;
+ $(ProjectRoot)\Samples\**\System.Printing.dll;
$(ProjectRoot)\Samples\**\*.refresh_;
" />
<!-- Some .refresh files are only applicable to drop builds, so we rename them from *.refresh_ -->
@@ -251,7 +257,9 @@
<Zip Files="@(AllDropTargets)" ZipFileName="$(DropZip)" WorkingDirectory="$(DropsRoot)" />
</Target>
- <Target Name="Nightly" DependsOnTargets="Drop;Tools">
+ <!-- Although Nightly includes publishing samples and docs, those targets are conditioned for
+ running only when the SampleWebRoot and DocWebRoot properties are set, respectively. -->
+ <Target Name="Nightly" DependsOnTargets="Drop;Tools;PublishSamples;PublishDocumentation">
</Target>
</Project>
diff --git a/doc/README.Bin.html b/doc/README.Bin.html
index 4d6df90..de05333 100644
--- a/doc/README.Bin.html
+++ b/doc/README.Bin.html
@@ -9,10 +9,20 @@
{
vertical-align: top;
}
+ .style1
+ {
+ font-family: "Courier New", Courier, monospace;
+ }
+ .style2
+ {
+ font-family: "Courier New", Courier, monospace;
+ font-style: italic;
+ }
</style>
</head>
<body>
- <h1>Binary dependencies of sites using this library</h1>
+ <h1>Files in this directory</h1>
+ <h2>Binary dependencies of sites using this library</h2>
<table>
<tr>
<th>
@@ -43,7 +53,7 @@
<th>
log4net.dll
</th>
- <td>If present, will allow for recording log messages this library emits.</td>
+ <td>If present and v1.2.10, will allow for recording log messages this library emits.</td>
</tr>
<tr>
<th>
@@ -53,5 +63,21 @@
developing DotNetOpenAuth itself.</td>
</tr>
</table>
+ <h2>Other files</h2>
+ <table>
+ <tr>
+ <th>
+ DotNetOpenAuth.xsd
+ </th>
+ <td>Provides Intellisense for the web.config or app.config files of projects using this library.&nbsp;
+ To activate Intellisense, modify your <span class="style1">
+ %PROGRAMFILES%\Microsoft Visual Studio 9.0\Xml\Schemas\catalog.xml</span> file
+ to include this entry:<br />
+ <span class="style1">&lt;Association extension=&quot;config&quot; schema=&quot;</span><span
+ class="style2">permanent-directory</span><span class="style1">\DotNetOpenAuth.xsd&quot;
+ condition=&quot;%TargetFrameworkVersion% != 2.0 and %TargetFrameworkVersion% != 3.0&quot;
+ /&gt; </span>&nbsp;</td>
+ </tr>
+ </table>
</body>
</html>
diff --git a/doc/api/Web.config b/doc/api/Web.config
new file mode 100644
index 0000000..1307a69
--- /dev/null
+++ b/doc/api/Web.config
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<!--
+ Note: As an alternative to hand editing this file you can use the
+ web admin tool to configure settings for your application. Use
+ the Website->Asp.Net Configuration option in Visual Studio.
+ A full list of settings and comments can be found in
+ machine.config.comments usually located in
+ \Windows\Microsoft.Net\Framework\v2.x\Config
+-->
+<configuration>
+ <configSections>
+ <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
+ <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
+ <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
+ <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
+ <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
+ <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
+ <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
+ <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
+ </sectionGroup>
+ </sectionGroup>
+ </sectionGroup>
+ </configSections>
+ <appSettings/>
+ <connectionStrings/>
+ <system.web>
+ <!--
+ Set compilation debug="true" to insert debugging
+ symbols into the compiled page. Because this
+ affects performance, set this value to true only
+ during development.
+ -->
+ <compilation debug="false">
+ <assemblies>
+ <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
+ <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
+ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
+ </assemblies>
+ </compilation>
+ <!--
+ The <authentication> section enables configuration
+ of the security authentication mode used by
+ ASP.NET to identify an incoming user.
+ -->
+ <authentication mode="Windows"/>
+ <!--
+ The <customErrors> section enables configuration
+ of what to do if/when an unhandled error occurs
+ during the execution of a request. Specifically,
+ it enables developers to configure html error pages
+ to be displayed in place of a error stack trace.
+
+ <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
+ <error statusCode="403" redirect="NoAccess.htm" />
+ <error statusCode="404" redirect="FileNotFound.htm" />
+ </customErrors>
+ -->
+ <pages>
+ <controls>
+ <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ </controls>
+ </pages>
+ <httpHandlers>
+ <remove verb="*" path="*.asmx"/>
+ <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add verb="GET,HEAD" path="ScriptResource.axd" validate="false" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ </httpHandlers>
+ <httpModules>
+ <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ </httpModules>
+ </system.web>
+ <system.codedom>
+ <compilers>
+ <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
+ <providerOption name="CompilerVersion" value="v3.5"/>
+ <providerOption name="WarnAsError" value="false"/>
+ </compiler>
+ <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" warningLevel="4">
+ <providerOption name="CompilerVersion" value="v3.5"/>
+ <providerOption name="OptionInfer" value="true"/>
+ <providerOption name="WarnAsError" value="false"/>
+ </compiler>
+ </compilers>
+ </system.codedom>
+ <system.webServer>
+ <validation validateIntegratedModeConfiguration="false"/>
+ <modules>
+ <remove name="ScriptModule"/>
+ <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ </modules>
+ <handlers>
+ <remove name="WebServiceHandlerFactory-Integrated"/>
+ <remove name="ScriptHandlerFactory"/>
+ <remove name="ScriptHandlerFactoryAppServices"/>
+ <remove name="ScriptResource"/>
+ <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ <add name="ScriptResource" verb="GET,HEAD" path="ScriptResource.axd" preCondition="integratedMode" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
+ </handlers>
+ </system.webServer>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
+ <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
+ <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration>
diff --git a/doc/api/default.aspx b/doc/api/default.aspx
new file mode 100644
index 0000000..19484cd
--- /dev/null
+++ b/doc/api/default.aspx
@@ -0,0 +1,35 @@
+<%@ Page Language="C#" %>
+
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Linq" %>
+
+<script runat="server">
+ protected virtual void Page_Load(object sender, EventArgs e) {
+ string apiPath = Path.GetDirectoryName(Request.PhysicalPath);
+ string htmlPath = Path.Combine(apiPath, "html");
+ var namespaceFiles = Directory.GetFiles(htmlPath, "N_*.htm*").Select(ns => Path.GetFileName(ns));
+ NamespaceRepeater.DataSource = namespaceFiles.Select(ns => new {
+ Href = "html/" + ns,
+ Title = Path.GetFileNameWithoutExtension(ns).Substring(2).Replace("_", "."),
+ });
+ NamespaceRepeater.DataBind();
+ }
+</script>
+
+<html>
+<head>
+ <title>DotNetOpenAuth API documentation</title>
+</head>
+<body>
+ <h1>DotNetOpenAuth API documentation</h1>
+ <h2>Documentation by namespace</h2>
+ <ul>
+ <asp:Repeater runat="server" ID="NamespaceRepeater">
+ <ItemTemplate>
+ <li><a href="<%# Eval("Href") %>">
+ <%# Eval("Title") %></a></li>
+ </ItemTemplate>
+ </asp:Repeater>
+ </ul>
+</body>
+</html>
diff --git a/lib/DotNetOpenAuth.BuildTasks.dll b/lib/DotNetOpenAuth.BuildTasks.dll
index 4f3cd90..d11865f 100644
--- a/lib/DotNetOpenAuth.BuildTasks.dll
+++ b/lib/DotNetOpenAuth.BuildTasks.dll
Binary files differ
diff --git a/lib/DotNetOpenAuth.BuildTasks.pdb b/lib/DotNetOpenAuth.BuildTasks.pdb
index 219857c..dda205e 100644
--- a/lib/DotNetOpenAuth.BuildTasks.pdb
+++ b/lib/DotNetOpenAuth.BuildTasks.pdb
Binary files differ
diff --git a/lib/DotNetOpenAuth.BuildTasks.targets b/lib/DotNetOpenAuth.BuildTasks.targets
index 9b9758a..024b43a 100644
--- a/lib/DotNetOpenAuth.BuildTasks.targets
+++ b/lib/DotNetOpenAuth.BuildTasks.targets
@@ -11,5 +11,9 @@
<UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="ReSignDelaySignedAssemblies" />
<UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="SignatureVerification" />
<UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="CheckAdminRights" />
+ <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="CreateWebApplication" />
+ <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="DeleteWebApplication" />
+ <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="Trim" />
+ <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="FilterItems" />
</Project>
diff --git a/samples/OAuthConsumer/App_Code/InMemoryTokenManager.cs b/samples/OAuthConsumer/App_Code/InMemoryTokenManager.cs
index fede300..2ecd045 100644
--- a/samples/OAuthConsumer/App_Code/InMemoryTokenManager.cs
+++ b/samples/OAuthConsumer/App_Code/InMemoryTokenManager.cs
@@ -28,14 +28,6 @@ public class InMemoryTokenManager : IConsumerTokenManager {
#region ITokenManager Members
- public string GetConsumerSecret(string consumerKey) {
- if (consumerKey == this.ConsumerKey) {
- return this.ConsumerSecret;
- } else {
- throw new ArgumentException("Unrecognized consumer key.", "consumerKey");
- }
- }
-
public string GetTokenSecret(string token) {
return this.tokensAndSecrets[token];
}
diff --git a/samples/OAuthConsumerWpf/App.config b/samples/OAuthConsumerWpf/App.config
index aef423e..e53b4a3 100644
--- a/samples/OAuthConsumerWpf/App.config
+++ b/samples/OAuthConsumerWpf/App.config
@@ -57,4 +57,38 @@
<level value="ALL" />
</logger>
</log4net>
+ <system.serviceModel>
+ <bindings>
+ <wsHttpBinding>
+ <binding name="WSHttpBinding_IDataApi" closeTimeout="00:01:00"
+ openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
+ bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
+ maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
+ messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
+ allowCookies="false">
+ <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
+ maxBytesPerRead="4096" maxNameTableCharCount="16384" />
+ <reliableSession ordered="true" inactivityTimeout="00:10:00"
+ enabled="false" />
+ <security mode="Message">
+ <transport clientCredentialType="Windows" proxyCredentialType="None"
+ realm="">
+ <extendedProtectionPolicy policyEnforcement="Never" />
+ </transport>
+ <message clientCredentialType="Windows" negotiateServiceCredential="true"
+ algorithmSuite="Default" establishSecurityContext="true" />
+ </security>
+ </binding>
+ </wsHttpBinding>
+ </bindings>
+ <client>
+ <endpoint address="http://localhost:65169/OAuthServiceProvider/DataApi.svc"
+ binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDataApi"
+ contract="WcfSampleService.IDataApi" name="WSHttpBinding_IDataApi">
+ <identity>
+ <dns value="localhost" />
+ </identity>
+ </endpoint>
+ </client>
+ </system.serviceModel>
</configuration> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Authorize.xaml.cs b/samples/OAuthConsumerWpf/Authorize.xaml.cs
index c28e6cc..2ee4d70 100644
--- a/samples/OAuthConsumerWpf/Authorize.xaml.cs
+++ b/samples/OAuthConsumerWpf/Authorize.xaml.cs
@@ -20,20 +20,17 @@
/// Interaction logic for Authorize.xaml
/// </summary>
public partial class Authorize : Window {
- private DesktopConsumer google;
+ private DesktopConsumer consumer;
private string requestToken;
- internal Authorize(DesktopConsumer consumer) {
+ internal Authorize(DesktopConsumer consumer, FetchUri fetchUriCallback) {
InitializeComponent();
- this.google = consumer;
+ this.consumer = consumer;
Cursor original = this.Cursor;
this.Cursor = Cursors.Wait;
ThreadPool.QueueUserWorkItem(delegate(object state) {
- Uri browserAuthorizationLocation = GoogleConsumer.RequestAuthorization(
- this.google,
- GoogleConsumer.Applications.Contacts | GoogleConsumer.Applications.Blogger,
- out this.requestToken);
+ Uri browserAuthorizationLocation = fetchUriCallback(this.consumer, out this.requestToken);
System.Diagnostics.Process.Start(browserAuthorizationLocation.AbsoluteUri);
this.Dispatcher.BeginInvoke(new Action(() => {
this.Cursor = original;
@@ -42,10 +39,12 @@
});
}
+ internal delegate Uri FetchUri(DesktopConsumer consumer, out string requestToken);
+
internal string AccessToken { get; set; }
private void finishButton_Click(object sender, RoutedEventArgs e) {
- var grantedAccess = this.google.ProcessUserAuthorization(this.requestToken, verifierBox.Text);
+ var grantedAccess = this.consumer.ProcessUserAuthorization(this.requestToken, verifierBox.Text);
this.AccessToken = grantedAccess.AccessToken;
DialogResult = true;
Close();
diff --git a/samples/OAuthConsumerWpf/MainWindow.xaml b/samples/OAuthConsumerWpf/MainWindow.xaml
index 6ada88a..e948bd2 100644
--- a/samples/OAuthConsumerWpf/MainWindow.xaml
+++ b/samples/OAuthConsumerWpf/MainWindow.xaml
@@ -2,49 +2,75 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DotNetOpenAuth Consumer (sample)" Height="400" Width="442">
- <Grid Margin="5">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition />
- </Grid.ColumnDefinitions>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition />
- </Grid.RowDefinitions>
- <Button Grid.Column="1" Grid.Row="3" Name="beginAuthorizationButton" Click="beginAuthorizationButton_Click">Authorize</Button>
- <TabControl Grid.ColumnSpan="2" Grid.Row="4" Name="tabControl1" Margin="0,10,0,0">
- <TabItem Header="Gmail Contacts" Name="gmailContactsTab">
- <Grid Name="contactsGrid">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition Width="Auto" />
- </Grid.ColumnDefinitions>
- </Grid>
- </TabItem>
- <TabItem Header="Blogger" Name="bloggerTab">
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition Width="*" />
- </Grid.ColumnDefinitions>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
- </Grid.RowDefinitions>
- <Label>Blog URL</Label>
- <TextBox Grid.Column="1" x:Name="blogUrlBox"/>
- <Label Grid.Row="1">Title</Label>
- <TextBox Grid.Row="1" Grid.Column="1" x:Name="postTitleBox">OAuth Rocks!</TextBox>
- <Label Grid.Row="2">Body</Label>
- <TextBox Grid.Row="2" Grid.Column="1" x:Name="postBodyBox" AcceptsReturn="True" AcceptsTab="True" AutoWordSelection="True" TextWrapping="WrapWithOverflow">&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;Oauth is cool&lt;/p&gt;</TextBox>
- <Button x:Name="postButton" Grid.Row="3" Grid.Column="1" Click="postButton_Click" IsEnabled="False">Post</Button>
- </Grid>
- </TabItem>
- </TabControl>
- </Grid>
+ <TabControl Name="outerTabControl" Margin="0,10,0,0">
+ <TabItem Header="Google" Name="googleTab">
+ <Grid Margin="5">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition />
+ </Grid.RowDefinitions>
+ <Button Grid.Column="1" Grid.Row="3" Name="beginAuthorizationButton" Click="beginAuthorizationButton_Click">Authorize</Button>
+ <TabControl Grid.ColumnSpan="2" Grid.Row="4" Name="tabControl1" Margin="0,10,0,0">
+ <TabItem Header="Gmail Contacts" Name="gmailContactsTab">
+ <Grid Name="contactsGrid">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ </Grid>
+ </TabItem>
+ <TabItem Header="Blogger" Name="bloggerTab">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <Label>Blog URL</Label>
+ <TextBox Grid.Column="1" x:Name="blogUrlBox"/>
+ <Label Grid.Row="1">Title</Label>
+ <TextBox Grid.Row="1" Grid.Column="1" x:Name="postTitleBox">OAuth Rocks!</TextBox>
+ <Label Grid.Row="2">Body</Label>
+ <TextBox Grid.Row="2" Grid.Column="1" x:Name="postBodyBox" AcceptsReturn="True" AcceptsTab="True" AutoWordSelection="True" TextWrapping="WrapWithOverflow">&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;Oauth is cool&lt;/p&gt;</TextBox>
+ <Button x:Name="postButton" Grid.Row="3" Grid.Column="1" Click="postButton_Click" IsEnabled="False">Post</Button>
+ </Grid>
+ </TabItem>
+ </TabControl>
+ </Grid>
+ </TabItem>
+ <TabItem Header="WCF sample">
+ <Grid Margin="5">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition />
+ </Grid.RowDefinitions>
+ <Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Name="beginWcfAuthorizationButton" Click="beginWcfAuthorizationButton_Click">Authorize</Button>
+ <Label Content="Name" Grid.Row="1" />
+ <Label Grid.Row="1" Grid.Column="1" Name="wcfName" />
+ <Label Content="Age" Grid.Row="2" />
+ <Label Grid.Row="2" Grid.Column="1" Name="wcfAge" />
+ <Label Content="Favorite sites" Grid.Row="3" />
+ <Label Grid.Row="3" Grid.Column="1" Name="wcfFavoriteSites" />
+ </Grid>
+ </TabItem>
+ </TabControl>
</Window>
diff --git a/samples/OAuthConsumerWpf/MainWindow.xaml.cs b/samples/OAuthConsumerWpf/MainWindow.xaml.cs
index e408d19..ebbeffc 100644
--- a/samples/OAuthConsumerWpf/MainWindow.xaml.cs
+++ b/samples/OAuthConsumerWpf/MainWindow.xaml.cs
@@ -3,7 +3,10 @@
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
+ using System.Net;
using System.Security.Cryptography.X509Certificates;
+ using System.ServiceModel;
+ using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
using System.Windows;
@@ -23,45 +26,78 @@
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
- private InMemoryTokenManager tokenManager = new InMemoryTokenManager();
+ private InMemoryTokenManager googleTokenManager = new InMemoryTokenManager();
private DesktopConsumer google;
- private string accessToken;
+ private string googleAccessToken;
+ private InMemoryTokenManager wcfTokenManager = new InMemoryTokenManager();
+ private DesktopConsumer wcf;
+ private string wcfAccessToken;
public MainWindow() {
- InitializeComponent();
+ this.InitializeComponent();
- this.tokenManager.ConsumerKey = ConfigurationManager.AppSettings["googleConsumerKey"];
- this.tokenManager.ConsumerSecret = ConfigurationManager.AppSettings["googleConsumerSecret"];
+ this.InitializeGoogleConsumer();
+ this.InitializeWcfConsumer();
+ }
+
+ private void InitializeGoogleConsumer() {
+ this.googleTokenManager.ConsumerKey = ConfigurationManager.AppSettings["googleConsumerKey"];
+ this.googleTokenManager.ConsumerSecret = ConfigurationManager.AppSettings["googleConsumerSecret"];
string pfxFile = ConfigurationManager.AppSettings["googleConsumerCertificateFile"];
if (string.IsNullOrEmpty(pfxFile)) {
- this.google = new DesktopConsumer(GoogleConsumer.ServiceDescription, this.tokenManager);
+ this.google = new DesktopConsumer(GoogleConsumer.ServiceDescription, this.googleTokenManager);
} else {
string pfxPassword = ConfigurationManager.AppSettings["googleConsumerCertificatePassword"];
var signingCertificate = new X509Certificate2(pfxFile, pfxPassword);
var service = GoogleConsumer.CreateRsaSha1ServiceDescription(signingCertificate);
- this.google = new DesktopConsumer(service, this.tokenManager);
+ this.google = new DesktopConsumer(service, this.googleTokenManager);
}
}
+ private void InitializeWcfConsumer() {
+ this.wcfTokenManager.ConsumerKey = "sampleconsumer";
+ this.wcfTokenManager.ConsumerSecret = "samplesecret";
+ MessageReceivingEndpoint oauthEndpoint = new MessageReceivingEndpoint(
+ new Uri("http://localhost:65169/OAuthServiceProvider/OAuth.ashx"),
+ HttpDeliveryMethods.PostRequest);
+ this.wcf = new DesktopConsumer(
+ new ServiceProviderDescription {
+ RequestTokenEndpoint = oauthEndpoint,
+ UserAuthorizationEndpoint = oauthEndpoint,
+ AccessTokenEndpoint = oauthEndpoint,
+ TamperProtectionElements = new DotNetOpenAuth.Messaging.ITamperProtectionChannelBindingElement[] {
+ new HmacSha1SigningBindingElement(),
+ },
+ },
+ this.wcfTokenManager);
+ }
+
private void beginAuthorizationButton_Click(object sender, RoutedEventArgs e) {
- if (string.IsNullOrEmpty(this.tokenManager.ConsumerKey)) {
+ if (string.IsNullOrEmpty(this.googleTokenManager.ConsumerKey)) {
MessageBox.Show(this, "You must modify the App.config or OAuthConsumerWpf.exe.config file for this application to include your Google OAuth consumer key first.", "Configuration required", MessageBoxButton.OK, MessageBoxImage.Stop);
return;
}
- Authorize auth = new Authorize(this.google);
+ Authorize auth = new Authorize(
+ this.google,
+ (DesktopConsumer consumer, out string requestToken) =>
+ GoogleConsumer.RequestAuthorization(
+ consumer,
+ GoogleConsumer.Applications.Contacts | GoogleConsumer.Applications.Blogger,
+ out requestToken));
bool? result = auth.ShowDialog();
if (result.HasValue && result.Value) {
- this.accessToken = auth.AccessToken;
+ this.googleAccessToken = auth.AccessToken;
postButton.IsEnabled = true;
- XDocument contactsDocument = GoogleConsumer.GetContacts(this.google, this.accessToken);
+ XDocument contactsDocument = GoogleConsumer.GetContacts(this.google, this.googleAccessToken);
var contacts = from entry in contactsDocument.Root.Elements(XName.Get("entry", "http://www.w3.org/2005/Atom"))
select new { Name = entry.Element(XName.Get("title", "http://www.w3.org/2005/Atom")).Value, Email = entry.Element(XName.Get("email", "http://schemas.google.com/g/2005")).Attribute("address").Value };
contactsGrid.Children.Clear();
@@ -80,7 +116,38 @@
private void postButton_Click(object sender, RoutedEventArgs e) {
XElement postBodyXml = XElement.Parse(postBodyBox.Text);
- GoogleConsumer.PostBlogEntry(this.google, this.accessToken, blogUrlBox.Text, postTitleBox.Text, postBodyXml);
+ GoogleConsumer.PostBlogEntry(this.google, this.googleAccessToken, blogUrlBox.Text, postTitleBox.Text, postBodyXml);
+ }
+
+ private void beginWcfAuthorizationButton_Click(object sender, RoutedEventArgs e) {
+ var requestArgs = new Dictionary<string, string>();
+ requestArgs["scope"] = "http://tempuri.org/IDataApi/GetName|http://tempuri.org/IDataApi/GetAge|http://tempuri.org/IDataApi/GetFavoriteSites";
+ Authorize auth = new Authorize(
+ this.wcf,
+ (DesktopConsumer consumer, out string requestToken) => consumer.RequestUserAuthorization(requestArgs, null, out requestToken));
+ bool? result = auth.ShowDialog();
+ if (result.HasValue && result.Value) {
+ this.wcfAccessToken = auth.AccessToken;
+ wcfName.Content = CallService(client => client.GetName());
+ wcfAge.Content = CallService(client => client.GetAge());
+ wcfFavoriteSites.Content = CallService(client => string.Join(", ", client.GetFavoriteSites()));
+ }
+ }
+
+ private T CallService<T>(Func<DataApiClient, T> predicate) {
+ DataApiClient client = new DataApiClient();
+ var serviceEndpoint = new MessageReceivingEndpoint(client.Endpoint.Address.Uri, HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.PostRequest);
+ if (this.wcfAccessToken == null) {
+ throw new InvalidOperationException("No access token!");
+ }
+ WebRequest httpRequest = this.wcf.PrepareAuthorizedRequest(serviceEndpoint, this.wcfAccessToken);
+
+ HttpRequestMessageProperty httpDetails = new HttpRequestMessageProperty();
+ httpDetails.Headers[HttpRequestHeader.Authorization] = httpRequest.Headers[HttpRequestHeader.Authorization];
+ using (OperationContextScope scope = new OperationContextScope(client.InnerChannel)) {
+ OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpDetails;
+ return predicate(client);
+ }
}
}
}
diff --git a/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj b/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
index 6e8e4ea..c91f0b4 100644
--- a/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
+++ b/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
@@ -56,6 +56,12 @@
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.Runtime.Serialization">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.ServiceModel">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -118,6 +124,11 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
+ <Compile Include="Service References\WcfSampleService\Reference.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Reference.svcmap</DependentUpon>
+ </Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
@@ -127,6 +138,9 @@
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
+ <None Include="Service References\WcfSampleService\DataApi.wsdl" />
+ <None Include="Service References\WcfSampleService\DataApi.xsd" />
+ <None Include="Service References\WcfSampleService\DataApi1.xsd" />
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
@@ -139,6 +153,28 @@
<Name>DotNetOpenAuth.ApplicationBlock</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <WCFMetadata Include="Service References\" />
+ </ItemGroup>
+ <ItemGroup>
+ <WCFMetadataStorage Include="Service References\WcfSampleService\" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Service References\WcfSampleService\DataApi.disco" />
+ <None Include="Service References\WcfSampleService\DataApi2.xsd" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Service References\WcfSampleService\configuration91.svcinfo" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Service References\WcfSampleService\configuration.svcinfo" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Service References\WcfSampleService\Reference.svcmap">
+ <Generator>WCF Proxy Generator</Generator>
+ <LastGenOutput>Reference.cs</LastGenOutput>
+ </None>
+ </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/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.disco b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.disco
new file mode 100644
index 0000000..a3cecd3
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.disco
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
+ <contractRef ref="http://localhost:65169/OAuthServiceProvider/DataApi.svc?wsdl" docRef="http://localhost:65169/OAuthServiceProvider/DataApi.svc" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
+</discovery> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.wsdl b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.wsdl
new file mode 100644
index 0000000..46a07e1
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.wsdl
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8"?>
+<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:tns="http://tempuri.org/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" name="DataApi" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <wsp:Policy>
+ <sp:ProtectionToken>
+ <wsp:Policy>
+ <sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
+ <wsp:Policy>
+ <sp:RequireDerivedKeys />
+ <sp:BootstrapPolicy>
+ <wsp:Policy>
+ <sp:SignedParts>
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts>
+ <sp:Body />
+ </sp:EncryptedParts>
+ <sp:SymmetricBinding>
+ <wsp:Policy>
+ <sp:ProtectionToken>
+ <wsp:Policy>
+ <sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
+ <wsp:Policy>
+ <sp:RequireDerivedKeys />
+ </wsp:Policy>
+ </sp:SpnegoContextToken>
+ </wsp:Policy>
+ </sp:ProtectionToken>
+ <sp:AlgorithmSuite>
+ <wsp:Policy>
+ <sp:Basic256 />
+ </wsp:Policy>
+ </sp:AlgorithmSuite>
+ <sp:Layout>
+ <wsp:Policy>
+ <sp:Strict />
+ </wsp:Policy>
+ </sp:Layout>
+ <sp:IncludeTimestamp />
+ <sp:EncryptSignature />
+ <sp:OnlySignEntireHeadersAndBody />
+ </wsp:Policy>
+ </sp:SymmetricBinding>
+ <sp:Wss11>
+ <wsp:Policy>
+ <sp:MustSupportRefKeyIdentifier />
+ <sp:MustSupportRefIssuerSerial />
+ <sp:MustSupportRefThumbprint />
+ <sp:MustSupportRefEncryptedKey />
+ </wsp:Policy>
+ </sp:Wss11>
+ <sp:Trust10>
+ <wsp:Policy>
+ <sp:MustSupportIssuedTokens />
+ <sp:RequireClientEntropy />
+ <sp:RequireServerEntropy />
+ </wsp:Policy>
+ </sp:Trust10>
+ </wsp:Policy>
+ </sp:BootstrapPolicy>
+ </wsp:Policy>
+ </sp:SecureConversationToken>
+ </wsp:Policy>
+ </sp:ProtectionToken>
+ <sp:AlgorithmSuite>
+ <wsp:Policy>
+ <sp:Basic256 />
+ </wsp:Policy>
+ </sp:AlgorithmSuite>
+ <sp:Layout>
+ <wsp:Policy>
+ <sp:Strict />
+ </wsp:Policy>
+ </sp:Layout>
+ <sp:IncludeTimestamp />
+ <sp:EncryptSignature />
+ <sp:OnlySignEntireHeadersAndBody />
+ </wsp:Policy>
+ </sp:SymmetricBinding>
+ <sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <wsp:Policy>
+ <sp:MustSupportRefKeyIdentifier />
+ <sp:MustSupportRefIssuerSerial />
+ <sp:MustSupportRefThumbprint />
+ <sp:MustSupportRefEncryptedKey />
+ </wsp:Policy>
+ </sp:Wss11>
+ <sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <wsp:Policy>
+ <sp:MustSupportIssuedTokens />
+ <sp:RequireClientEntropy />
+ <sp:RequireServerEntropy />
+ </wsp:Policy>
+ </sp:Trust10>
+ <wsaw:UsingAddressing />
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetAge_Input_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetAge_output_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetName_Input_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetName_output_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetFavoriteSites_Input_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsp:Policy wsu:Id="WSHttpBinding_IDataApi_GetFavoriteSites_output_policy">
+ <wsp:ExactlyOne>
+ <wsp:All>
+ <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
+ <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
+ </sp:SignedParts>
+ <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+ <sp:Body />
+ </sp:EncryptedParts>
+ </wsp:All>
+ </wsp:ExactlyOne>
+ </wsp:Policy>
+ <wsdl:types>
+ <xsd:schema targetNamespace="http://tempuri.org/Imports">
+ <xsd:import schemaLocation="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd0" namespace="http://tempuri.org/" />
+ <xsd:import schemaLocation="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
+ <xsd:import schemaLocation="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd2" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
+ </xsd:schema>
+ </wsdl:types>
+ <wsdl:message name="IDataApi_GetAge_InputMessage">
+ <wsdl:part name="parameters" element="tns:GetAge" />
+ </wsdl:message>
+ <wsdl:message name="IDataApi_GetAge_OutputMessage">
+ <wsdl:part name="parameters" element="tns:GetAgeResponse" />
+ </wsdl:message>
+ <wsdl:message name="IDataApi_GetName_InputMessage">
+ <wsdl:part name="parameters" element="tns:GetName" />
+ </wsdl:message>
+ <wsdl:message name="IDataApi_GetName_OutputMessage">
+ <wsdl:part name="parameters" element="tns:GetNameResponse" />
+ </wsdl:message>
+ <wsdl:message name="IDataApi_GetFavoriteSites_InputMessage">
+ <wsdl:part name="parameters" element="tns:GetFavoriteSites" />
+ </wsdl:message>
+ <wsdl:message name="IDataApi_GetFavoriteSites_OutputMessage">
+ <wsdl:part name="parameters" element="tns:GetFavoriteSitesResponse" />
+ </wsdl:message>
+ <wsdl:portType name="IDataApi">
+ <wsdl:operation name="GetAge">
+ <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetAge" message="tns:IDataApi_GetAge_InputMessage" />
+ <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetAgeResponse" message="tns:IDataApi_GetAge_OutputMessage" />
+ </wsdl:operation>
+ <wsdl:operation name="GetName">
+ <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetName" message="tns:IDataApi_GetName_InputMessage" />
+ <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetNameResponse" message="tns:IDataApi_GetName_OutputMessage" />
+ </wsdl:operation>
+ <wsdl:operation name="GetFavoriteSites">
+ <wsdl:input wsaw:Action="http://tempuri.org/IDataApi/GetFavoriteSites" message="tns:IDataApi_GetFavoriteSites_InputMessage" />
+ <wsdl:output wsaw:Action="http://tempuri.org/IDataApi/GetFavoriteSitesResponse" message="tns:IDataApi_GetFavoriteSites_OutputMessage" />
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="WSHttpBinding_IDataApi" type="tns:IDataApi">
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_policy" />
+ <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="GetAge">
+ <soap12:operation soapAction="http://tempuri.org/IDataApi/GetAge" style="document" />
+ <wsdl:input>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetAge_Input_policy" />
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetAge_output_policy" />
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="GetName">
+ <soap12:operation soapAction="http://tempuri.org/IDataApi/GetName" style="document" />
+ <wsdl:input>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetName_Input_policy" />
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetName_output_policy" />
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ <wsdl:operation name="GetFavoriteSites">
+ <soap12:operation soapAction="http://tempuri.org/IDataApi/GetFavoriteSites" style="document" />
+ <wsdl:input>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetFavoriteSites_Input_policy" />
+ <soap12:body use="literal" />
+ </wsdl:input>
+ <wsdl:output>
+ <wsp:PolicyReference URI="#WSHttpBinding_IDataApi_GetFavoriteSites_output_policy" />
+ <soap12:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="DataApi">
+ <wsdl:port name="WSHttpBinding_IDataApi" binding="tns:WSHttpBinding_IDataApi">
+ <soap12:address location="http://localhost:65169/OAuthServiceProvider/DataApi.svc" />
+ <wsa10:EndpointReference>
+ <wsa10:Address>http://localhost:65169/OAuthServiceProvider/DataApi.svc</wsa10:Address>
+ <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
+ <Dns>localhost</Dns>
+ </Identity>
+ </wsa10:EndpointReference>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.xsd b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.xsd
new file mode 100644
index 0000000..04a74a4
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi.xsd
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/Arrays" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType name="ArrayOfstring">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ <xs:element name="ArrayOfstring" nillable="true" type="tns:ArrayOfstring" />
+</xs:schema> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi1.xsd b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi1.xsd
new file mode 100644
index 0000000..bcb9ef8
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi1.xsd
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:tns="http://tempuri.org/" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import schemaLocation="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd2" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
+ <xs:element name="GetAge">
+ <xs:complexType>
+ <xs:sequence />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetAgeResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GetAgeResult" nillable="true" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetName">
+ <xs:complexType>
+ <xs:sequence />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetNameResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="GetNameResult" nillable="true" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetFavoriteSites">
+ <xs:complexType>
+ <xs:sequence />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="GetFavoriteSitesResponse">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element xmlns:q1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" minOccurs="0" name="GetFavoriteSitesResult" nillable="true" type="q1:ArrayOfstring" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi2.xsd b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi2.xsd
new file mode 100644
index 0000000..d58e7f3
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/DataApi2.xsd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="anyType" nillable="true" type="xs:anyType" />
+ <xs:element name="anyURI" nillable="true" type="xs:anyURI" />
+ <xs:element name="base64Binary" nillable="true" type="xs:base64Binary" />
+ <xs:element name="boolean" nillable="true" type="xs:boolean" />
+ <xs:element name="byte" nillable="true" type="xs:byte" />
+ <xs:element name="dateTime" nillable="true" type="xs:dateTime" />
+ <xs:element name="decimal" nillable="true" type="xs:decimal" />
+ <xs:element name="double" nillable="true" type="xs:double" />
+ <xs:element name="float" nillable="true" type="xs:float" />
+ <xs:element name="int" nillable="true" type="xs:int" />
+ <xs:element name="long" nillable="true" type="xs:long" />
+ <xs:element name="QName" nillable="true" type="xs:QName" />
+ <xs:element name="short" nillable="true" type="xs:short" />
+ <xs:element name="string" nillable="true" type="xs:string" />
+ <xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte" />
+ <xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt" />
+ <xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong" />
+ <xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort" />
+ <xs:element name="char" nillable="true" type="tns:char" />
+ <xs:simpleType name="char">
+ <xs:restriction base="xs:int" />
+ </xs:simpleType>
+ <xs:element name="duration" nillable="true" type="tns:duration" />
+ <xs:simpleType name="duration">
+ <xs:restriction base="xs:duration">
+ <xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?" />
+ <xs:minInclusive value="-P10675199DT2H48M5.4775808S" />
+ <xs:maxInclusive value="P10675199DT2H48M5.4775807S" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="guid" nillable="true" type="tns:guid" />
+ <xs:simpleType name="guid">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:attribute name="FactoryType" type="xs:QName" />
+ <xs:attribute name="Id" type="xs:ID" />
+ <xs:attribute name="Ref" type="xs:IDREF" />
+</xs:schema> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.cs b/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.cs
new file mode 100644
index 0000000..216c8b3
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.cs
@@ -0,0 +1,67 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4918
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService {
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
+ [System.ServiceModel.ServiceContractAttribute(ConfigurationName="WcfSampleService.IDataApi")]
+ public interface IDataApi {
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetAge", ReplyAction="http://tempuri.org/IDataApi/GetAgeResponse")]
+ System.Nullable<int> GetAge();
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetName", ReplyAction="http://tempuri.org/IDataApi/GetNameResponse")]
+ string GetName();
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IDataApi/GetFavoriteSites", ReplyAction="http://tempuri.org/IDataApi/GetFavoriteSitesResponse")]
+ string[] GetFavoriteSites();
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
+ public interface IDataApiChannel : DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService.IDataApi, System.ServiceModel.IClientChannel {
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
+ public partial class DataApiClient : System.ServiceModel.ClientBase<DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService.IDataApi>, DotNetOpenAuth.Samples.OAuthConsumerWpf.WcfSampleService.IDataApi {
+
+ public DataApiClient() {
+ }
+
+ public DataApiClient(string endpointConfigurationName) :
+ base(endpointConfigurationName) {
+ }
+
+ public DataApiClient(string endpointConfigurationName, string remoteAddress) :
+ base(endpointConfigurationName, remoteAddress) {
+ }
+
+ public DataApiClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(endpointConfigurationName, remoteAddress) {
+ }
+
+ public DataApiClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(binding, remoteAddress) {
+ }
+
+ public System.Nullable<int> GetAge() {
+ return base.Channel.GetAge();
+ }
+
+ public string GetName() {
+ return base.Channel.GetName();
+ }
+
+ public string[] GetFavoriteSites() {
+ return base.Channel.GetFavoriteSites();
+ }
+ }
+}
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.svcmap b/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.svcmap
new file mode 100644
index 0000000..60bdc90
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/Reference.svcmap
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ReferenceGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="2ed8bfde-ddd6-4e80-8c91-c4c0ee21026d" xmlns="urn:schemas-microsoft-com:xml-wcfservicemap">
+ <ClientOptions>
+ <GenerateAsynchronousMethods>false</GenerateAsynchronousMethods>
+ <EnableDataBinding>true</EnableDataBinding>
+ <ExcludedTypes />
+ <ImportXmlTypes>false</ImportXmlTypes>
+ <GenerateInternalTypes>false</GenerateInternalTypes>
+ <GenerateMessageContracts>false</GenerateMessageContracts>
+ <NamespaceMappings />
+ <CollectionMappings />
+ <GenerateSerializableTypes>true</GenerateSerializableTypes>
+ <Serializer>Auto</Serializer>
+ <ReferenceAllAssemblies>true</ReferenceAllAssemblies>
+ <ReferencedAssemblies />
+ <ReferencedDataContractTypes />
+ <ServiceContractMappings />
+ </ClientOptions>
+ <MetadataSources>
+ <MetadataSource Address="http://localhost:65169/OAuthServiceProvider/DataApi.svc" Protocol="http" SourceId="1" />
+ </MetadataSources>
+ <Metadata>
+ <MetadataFile FileName="DataApi.wsdl" MetadataType="Wsdl" ID="3e4bf2a2-224e-4651-bbfb-67b29c58b1e8" SourceId="1" SourceUrl="http://localhost:65169/OAuthServiceProvider/DataApi.svc?wsdl" />
+ <MetadataFile FileName="DataApi.xsd" MetadataType="Schema" ID="431abff0-dec3-4e99-9173-9f8b69a27f94" SourceId="1" SourceUrl="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd2" />
+ <MetadataFile FileName="DataApi1.xsd" MetadataType="Schema" ID="150d6701-aa42-49bc-8042-108207e19493" SourceId="1" SourceUrl="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd0" />
+ <MetadataFile FileName="DataApi.disco" MetadataType="Disco" ID="d9c6ecfd-3dc0-4b71-80ba-b2b25c42238a" SourceId="1" SourceUrl="http://localhost:65169/OAuthServiceProvider/DataApi.svc?disco" />
+ <MetadataFile FileName="DataApi2.xsd" MetadataType="Schema" ID="3f8e1950-7d27-4def-acf9-8e1a0e4e03df" SourceId="1" SourceUrl="http://localhost:65169/OAuthServiceProvider/DataApi.svc?xsd=xsd1" />
+ </Metadata>
+ <Extensions>
+ <ExtensionFile FileName="configuration91.svcinfo" Name="configuration91.svcinfo" />
+ <ExtensionFile FileName="configuration.svcinfo" Name="configuration.svcinfo" />
+ </Extensions>
+</ReferenceGroup> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration.svcinfo b/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration.svcinfo
new file mode 100644
index 0000000..83fa826
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration.svcinfo
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configurationSnapshot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:xml-wcfconfigurationsnapshot">
+ <behaviors />
+ <bindings>
+ <binding digest="System.ServiceModel.Configuration.WSHttpBindingElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089:&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data hostNameComparisonMode=&quot;StrongWildcard&quot; messageEncoding=&quot;Text&quot; name=&quot;WSHttpBinding_IDataApi&quot; textEncoding=&quot;utf-8&quot; transactionFlow=&quot;false&quot;&gt;&lt;readerQuotas maxArrayLength=&quot;16384&quot; maxBytesPerRead=&quot;4096&quot; maxDepth=&quot;32&quot; maxNameTableCharCount=&quot;16384&quot; maxStringContentLength=&quot;8192&quot; /&gt;&lt;reliableSession enabled=&quot;false&quot; inactivityTimeout=&quot;00:10:00&quot; ordered=&quot;true&quot; /&gt;&lt;security mode=&quot;Message&quot;&gt;&lt;message algorithmSuite=&quot;Default&quot; clientCredentialType=&quot;Windows&quot; establishSecurityContext=&quot;true&quot; negotiateServiceCredential=&quot;true&quot; /&gt;&lt;transport clientCredentialType=&quot;Windows&quot; proxyCredentialType=&quot;None&quot; realm=&quot;&quot; /&gt;&lt;/security&gt;&lt;/Data&gt;" bindingType="wsHttpBinding" name="WSHttpBinding_IDataApi" />
+ </bindings>
+ <endpoints>
+ <endpoint normalizedDigest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:65169/OAuthServiceProvider/DataApi.svc&quot; binding=&quot;wsHttpBinding&quot; bindingConfiguration=&quot;WSHttpBinding_IDataApi&quot; contract=&quot;WcfSampleService.IDataApi&quot; name=&quot;WSHttpBinding_IDataApi&quot;&gt;&lt;identity&gt;&lt;dns value=&quot;localhost&quot; /&gt;&lt;/identity&gt;&lt;/Data&gt;" digest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:65169/OAuthServiceProvider/DataApi.svc&quot; binding=&quot;wsHttpBinding&quot; bindingConfiguration=&quot;WSHttpBinding_IDataApi&quot; contract=&quot;WcfSampleService.IDataApi&quot; name=&quot;WSHttpBinding_IDataApi&quot;&gt;&lt;identity&gt;&lt;dns value=&quot;localhost&quot; /&gt;&lt;/identity&gt;&lt;/Data&gt;" contractName="WcfSampleService.IDataApi" name="WSHttpBinding_IDataApi" />
+ </endpoints>
+</configurationSnapshot> \ No newline at end of file
diff --git a/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration91.svcinfo b/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration91.svcinfo
new file mode 100644
index 0000000..de1eabf
--- /dev/null
+++ b/samples/OAuthConsumerWpf/Service References/WcfSampleService/configuration91.svcinfo
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<SavedWcfConfigurationInformation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="9.1" CheckSum="euCgt24VN7V3aZNjvZhw/CrojFo=">
+ <bindingConfigurations>
+ <bindingConfiguration bindingType="wsHttpBinding" name="WSHttpBinding_IDataApi">
+ <properties>
+ <property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>WSHttpBinding_IDataApi</serializedValue>
+ </property>
+ <property path="/closeTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>00:01:00</serializedValue>
+ </property>
+ <property path="/openTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>00:01:00</serializedValue>
+ </property>
+ <property path="/receiveTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>00:10:00</serializedValue>
+ </property>
+ <property path="/sendTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>00:01:00</serializedValue>
+ </property>
+ <property path="/bypassProxyOnLocal" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>False</serializedValue>
+ </property>
+ <property path="/transactionFlow" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>False</serializedValue>
+ </property>
+ <property path="/hostNameComparisonMode" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HostNameComparisonMode, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>StrongWildcard</serializedValue>
+ </property>
+ <property path="/maxBufferPoolSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>524288</serializedValue>
+ </property>
+ <property path="/maxReceivedMessageSize" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>65536</serializedValue>
+ </property>
+ <property path="/messageEncoding" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.WSMessageEncoding, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Text</serializedValue>
+ </property>
+ <property path="/proxyAddress" isComplexType="false" isExplicitlyDefined="false" clrType="System.Uri, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/readerQuotas" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.XmlDictionaryReaderQuotasElement</serializedValue>
+ </property>
+ <property path="/readerQuotas/maxDepth" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>32</serializedValue>
+ </property>
+ <property path="/readerQuotas/maxStringContentLength" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>8192</serializedValue>
+ </property>
+ <property path="/readerQuotas/maxArrayLength" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>16384</serializedValue>
+ </property>
+ <property path="/readerQuotas/maxBytesPerRead" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>4096</serializedValue>
+ </property>
+ <property path="/readerQuotas/maxNameTableCharCount" isComplexType="false" isExplicitlyDefined="true" clrType="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>16384</serializedValue>
+ </property>
+ <property path="/reliableSession" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.StandardBindingOptionalReliableSessionElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.StandardBindingOptionalReliableSessionElement</serializedValue>
+ </property>
+ <property path="/reliableSession/ordered" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>True</serializedValue>
+ </property>
+ <property path="/reliableSession/inactivityTimeout" isComplexType="false" isExplicitlyDefined="true" clrType="System.TimeSpan, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>00:10:00</serializedValue>
+ </property>
+ <property path="/reliableSession/enabled" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>False</serializedValue>
+ </property>
+ <property path="/textEncoding" isComplexType="false" isExplicitlyDefined="true" clrType="System.Text.Encoding, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.Text.UTF8Encoding</serializedValue>
+ </property>
+ <property path="/useDefaultWebProxy" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>True</serializedValue>
+ </property>
+ <property path="/allowCookies" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>False</serializedValue>
+ </property>
+ <property path="/security" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.WSHttpSecurityElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.WSHttpSecurityElement</serializedValue>
+ </property>
+ <property path="/security/mode" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.SecurityMode, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Message</serializedValue>
+ </property>
+ <property path="/security/transport" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.WSHttpTransportSecurityElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.WSHttpTransportSecurityElement</serializedValue>
+ </property>
+ <property path="/security/transport/clientCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HttpClientCredentialType, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Windows</serializedValue>
+ </property>
+ <property path="/security/transport/proxyCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.HttpProxyCredentialType, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>None</serializedValue>
+ </property>
+ <property path="/security/transport/realm" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/security/transport/extendedProtectionPolicy" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.Security.Authentication.ExtendedProtection.Configuration.ExtendedProtectionPolicyElement</serializedValue>
+ </property>
+ <property path="/security/transport/extendedProtectionPolicy/policyEnforcement" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.PolicyEnforcement, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Never</serializedValue>
+ </property>
+ <property path="/security/transport/extendedProtectionPolicy/protectionScenario" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.ProtectionScenario, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>TransportSelected</serializedValue>
+ </property>
+ <property path="/security/transport/extendedProtectionPolicy/customServiceNames" isComplexType="true" isExplicitlyDefined="false" clrType="System.Security.Authentication.ExtendedProtection.Configuration.ServiceNameElementCollection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>(Collection)</serializedValue>
+ </property>
+ <property path="/security/message" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.NonDualMessageSecurityOverHttpElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.NonDualMessageSecurityOverHttpElement</serializedValue>
+ </property>
+ <property path="/security/message/clientCredentialType" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.MessageCredentialType, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Windows</serializedValue>
+ </property>
+ <property path="/security/message/negotiateServiceCredential" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>True</serializedValue>
+ </property>
+ <property path="/security/message/algorithmSuite" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.Security.SecurityAlgorithmSuite, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>Basic256</serializedValue>
+ </property>
+ <property path="/security/message/establishSecurityContext" isComplexType="false" isExplicitlyDefined="true" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>True</serializedValue>
+ </property>
+ </properties>
+ </bindingConfiguration>
+ </bindingConfigurations>
+ <endpoints>
+ <endpoint name="WSHttpBinding_IDataApi" contract="WcfSampleService.IDataApi" bindingType="wsHttpBinding" address="http://localhost:65169/OAuthServiceProvider/DataApi.svc" bindingConfiguration="WSHttpBinding_IDataApi">
+ <properties>
+ <property path="/address" isComplexType="false" isExplicitlyDefined="true" clrType="System.Uri, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>http://localhost:65169/OAuthServiceProvider/DataApi.svc</serializedValue>
+ </property>
+ <property path="/behaviorConfiguration" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/binding" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>wsHttpBinding</serializedValue>
+ </property>
+ <property path="/bindingConfiguration" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>WSHttpBinding_IDataApi</serializedValue>
+ </property>
+ <property path="/contract" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>WcfSampleService.IDataApi</serializedValue>
+ </property>
+ <property path="/headers" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.AddressHeaderCollectionElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.AddressHeaderCollectionElement</serializedValue>
+ </property>
+ <property path="/headers/headers" isComplexType="false" isExplicitlyDefined="true" clrType="System.ServiceModel.Channels.AddressHeaderCollection, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>&lt;Header /&gt;</serializedValue>
+ </property>
+ <property path="/identity" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.IdentityElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.IdentityElement</serializedValue>
+ </property>
+ <property path="/identity/userPrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.UserPrincipalNameElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.UserPrincipalNameElement</serializedValue>
+ </property>
+ <property path="/identity/userPrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/identity/servicePrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.ServicePrincipalNameElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.ServicePrincipalNameElement</serializedValue>
+ </property>
+ <property path="/identity/servicePrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/identity/dns" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.DnsElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.DnsElement</serializedValue>
+ </property>
+ <property path="/identity/dns/value" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>localhost</serializedValue>
+ </property>
+ <property path="/identity/rsa" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.RsaElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.RsaElement</serializedValue>
+ </property>
+ <property path="/identity/rsa/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/identity/certificate" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.CertificateElement</serializedValue>
+ </property>
+ <property path="/identity/certificate/encodedValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/identity/certificateReference" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.CertificateReferenceElement, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>System.ServiceModel.Configuration.CertificateReferenceElement</serializedValue>
+ </property>
+ <property path="/identity/certificateReference/storeName" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreName, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>My</serializedValue>
+ </property>
+ <property path="/identity/certificateReference/storeLocation" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.StoreLocation, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>LocalMachine</serializedValue>
+ </property>
+ <property path="/identity/certificateReference/x509FindType" isComplexType="false" isExplicitlyDefined="false" clrType="System.Security.Cryptography.X509Certificates.X509FindType, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>FindBySubjectDistinguishedName</serializedValue>
+ </property>
+ <property path="/identity/certificateReference/findValue" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue />
+ </property>
+ <property path="/identity/certificateReference/isChainIncluded" isComplexType="false" isExplicitlyDefined="false" clrType="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>False</serializedValue>
+ </property>
+ <property path="/name" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+ <serializedValue>WSHttpBinding_IDataApi</serializedValue>
+ </property>
+ </properties>
+ </endpoint>
+ </endpoints>
+</SavedWcfConfigurationInformation> \ No newline at end of file
diff --git a/samples/OAuthServiceProvider/App_Code/DataApi.cs b/samples/OAuthServiceProvider/App_Code/DataApi.cs
index 00876f6..d5adb10 100644
--- a/samples/OAuthServiceProvider/App_Code/DataApi.cs
+++ b/samples/OAuthServiceProvider/App_Code/DataApi.cs
@@ -7,20 +7,25 @@ using System.ServiceModel;
/// <remarks>
/// Note how there is no code here that is bound to OAuth or any other
/// credential/authorization scheme. That's all part of the channel/binding elsewhere.
-/// And the reference to Global.LoggedInUser is the user being impersonated by the WCF client.
+/// And the reference to OperationContext.Current.ServiceSecurityContext.PrimaryIdentity
+/// is the user being impersonated by the WCF client.
/// In the OAuth case, it is the user who authorized the OAuth access token that was used
/// to gain access to the service.
/// </remarks>
public class DataApi : IDataApi {
+ private User User {
+ get { return OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.GetUser(); }
+ }
+
public int? GetAge() {
- return Global.LoggedInUser.Age;
+ return User.Age;
}
public string GetName() {
- return Global.LoggedInUser.FullName;
+ return User.FullName;
}
public string[] GetFavoriteSites() {
- return Global.LoggedInUser.FavoriteSites.Select(site => site.SiteUrl).ToArray();
+ return User.FavoriteSites.Select(site => site.SiteUrl).ToArray();
}
}
diff --git a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
index 710508d..8c93d2f 100644
--- a/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
+++ b/samples/OAuthServiceProvider/App_Code/DatabaseTokenManager.cs
@@ -40,6 +40,10 @@ public class DatabaseTokenManager : IServiceProviderTokenManager {
}
}
+ public void UpdateToken(IServiceProviderRequestToken token) {
+ // Nothing to do here, since we're using Linq To SQL.
+ }
+
#endregion
#region ITokenManager Members
diff --git a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs
index 1ec2cb5..8589932 100644
--- a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs
+++ b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IdentityModel.Policy;
using System.Linq;
+using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
@@ -27,10 +28,12 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager {
if (auth != null) {
var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken);
- var policy = new OAuthPrincipalAuthorizationPolicy(sp.CreatePrincipal(auth));
+ var principal = sp.CreatePrincipal(auth);
+ var policy = new OAuthPrincipalAuthorizationPolicy(principal);
var policies = new List<IAuthorizationPolicy> {
policy,
};
+
var securityContext = new ServiceSecurityContext(policies.AsReadOnly());
if (operationContext.IncomingMessageProperties.Security != null) {
operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext;
@@ -40,6 +43,10 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager {
};
}
+ securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> {
+ principal.Identity,
+ };
+
// Only allow this method call if the access token scope permits it.
string[] scopes = accessToken.Scope.Split('|');
if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) {
diff --git a/samples/OAuthServiceProvider/App_Code/OAuthConsumer.cs b/samples/OAuthServiceProvider/App_Code/OAuthConsumer.cs
index 1255717..db8f469 100644
--- a/samples/OAuthServiceProvider/App_Code/OAuthConsumer.cs
+++ b/samples/OAuthServiceProvider/App_Code/OAuthConsumer.cs
@@ -26,7 +26,7 @@ public partial class OAuthConsumer : IConsumerDescription {
}
Uri IConsumerDescription.Callback {
- get { return this.Callback != null ? new Uri(this.Callback) : null; }
+ get { return string.IsNullOrEmpty(this.Callback) ? null : new Uri(this.Callback); }
}
DotNetOpenAuth.OAuth.VerificationCodeFormat IConsumerDescription.VerificationCodeFormat {
diff --git a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
index fc1d6c5..ea18b2b 100644
--- a/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
+++ b/samples/OAuthServiceProvider/App_Code/OAuthToken.cs
@@ -26,7 +26,7 @@ public partial class OAuthToken : IServiceProviderRequestToken, IServiceProvider
}
Uri IServiceProviderRequestToken.Callback {
- get { return new Uri(this.RequestTokenCallback); }
+ get { return string.IsNullOrEmpty(this.RequestTokenCallback) ? null : new Uri(this.RequestTokenCallback); }
set { this.RequestTokenCallback = value.AbsoluteUri; }
}
diff --git a/samples/OAuthServiceProvider/App_Code/Utilities.cs b/samples/OAuthServiceProvider/App_Code/Utilities.cs
new file mode 100644
index 0000000..2c25fe8
--- /dev/null
+++ b/samples/OAuthServiceProvider/App_Code/Utilities.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Principal;
+using System.Web;
+
+/// <summary>
+/// Extension methods and other helpful utility methods.
+/// </summary>
+public static class Utilities {
+ /// <summary>
+ /// Gets the database entity representing the user identified by a given <see cref="IIdentity"/> instance.
+ /// </summary>
+ /// <param name="identity">The identity of the user.</param>
+ /// <returns>
+ /// The database object for that user; or <c>null</c> if the user could not
+ /// be found or if <paramref name="identity"/> is <c>null</c> or represents an anonymous identity.
+ /// </returns>
+ public static User GetUser(this IIdentity identity) {
+ if (identity == null || !identity.IsAuthenticated) {
+ return null;
+ }
+
+ return Global.DataContext.Users.SingleOrDefault(user => user.OpenIDClaimedIdentifier == identity.Name);
+ }
+}
diff --git a/samples/OAuthServiceProvider/Default.aspx b/samples/OAuthServiceProvider/Default.aspx
index 67efe3a..683a939 100644
--- a/samples/OAuthServiceProvider/Default.aspx
+++ b/samples/OAuthServiceProvider/Default.aspx
@@ -47,4 +47,7 @@
<asp:Button ID="createDatabaseButton" runat="server" Text="(Re)create Database" OnClick="createDatabaseButton_Click" />
<asp:Label runat="server" ID="databaseStatus" EnableViewState="false" Text="Database recreated!"
Visible="false" />
+ <p>Note that to be useful, you really need to either modify the database to add an
+ account with data that will be accessed by this sample, or modify this very page
+ to inject that data into the database. </p>
</asp:Content>
diff --git a/samples/OAuthServiceProvider/Members/Authorize.aspx.cs b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs
index f936c60..1e981a3 100644
--- a/samples/OAuthServiceProvider/Members/Authorize.aspx.cs
+++ b/samples/OAuthServiceProvider/Members/Authorize.aspx.cs
@@ -63,7 +63,9 @@ public partial class Authorize : System.Web.UI.Page {
string verifier = ServiceProvider.CreateVerificationCode(VerificationCodeFormat.AlphaNumericNoLookAlikes, 10);
verificationCodeLabel.Text = verifier;
ITokenContainingMessage requestTokenMessage = pending;
- Global.TokenManager.GetRequestToken(requestTokenMessage.Token).VerificationCode = verifier;
+ var requestToken = Global.TokenManager.GetRequestToken(requestTokenMessage.Token);
+ requestToken.VerificationCode = verifier;
+ Global.TokenManager.UpdateToken(requestToken);
}
}
}
diff --git a/samples/OpenIdOfflineProvider/MainWindow.xaml.cs b/samples/OpenIdOfflineProvider/MainWindow.xaml.cs
index a0ee56e..f4f88ca 100644
--- a/samples/OpenIdOfflineProvider/MainWindow.xaml.cs
+++ b/samples/OpenIdOfflineProvider/MainWindow.xaml.cs
@@ -101,6 +101,7 @@ namespace DotNetOpenAuth.OpenIdOfflineProvider {
IRequest request = this.hostedProvider.Provider.GetRequest(requestInfo);
if (request == null) {
App.Logger.Error("A request came in that did not carry an OpenID message.");
+ response.ContentType = "text/html";
response.StatusCode = (int)HttpStatusCode.BadRequest;
using (StreamWriter sw = new StreamWriter(response.OutputStream)) {
sw.WriteLine("<html><body>This is an OpenID Provider endpoint.</body></html>");
diff --git a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
index 1bb2367..2f303bb 100644
--- a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
+++ b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
@@ -57,10 +57,11 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
- <PropertyGroup Condition=" '$(Sign)' == 'true' ">
+ <PropertyGroup>
<SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\..\src\official-build-key.pfx</AssemblyOriginatorKeyFile>
<DefineConstants>$(DefineConstants);StrongNameSigned</DefineConstants>
+ <DelaySign>true</DelaySign>
+ <AssemblyOriginatorKeyFile>..\..\src\official-build-key.pub</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
diff --git a/samples/OpenIdProviderMvc/Controllers/UserController.cs b/samples/OpenIdProviderMvc/Controllers/UserController.cs
index 3cb87ae..4fc2f9f 100644
--- a/samples/OpenIdProviderMvc/Controllers/UserController.cs
+++ b/samples/OpenIdProviderMvc/Controllers/UserController.cs
@@ -21,7 +21,7 @@ namespace OpenIdProviderMvc.Controllers {
return redirect;
}
- if (Request.AcceptTypes.Contains("application/xrds+xml")) {
+ if (Request.AcceptTypes != null && Request.AcceptTypes.Contains("application/xrds+xml")) {
return View("Xrds");
}
diff --git a/samples/OpenIdProviderMvc/Web.config b/samples/OpenIdProviderMvc/Web.config
index fb89415..6f0fdd1 100644
--- a/samples/OpenIdProviderMvc/Web.config
+++ b/samples/OpenIdProviderMvc/Web.config
@@ -194,4 +194,8 @@
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</handlers>
</system.webServer>
+
+ <runtime>
+ <legacyHMACWarning enabled="0" />
+ </runtime>
</configuration>
diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs b/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs
new file mode 100644
index 0000000..de4505d
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------
+// <copyright file="InMemoryConsumerDescription.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace OpenIdProviderWebForms.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public class InMemoryConsumerDescription : IConsumerDescription {
+ #region IConsumerDescription Members
+
+ public string Key { get; set; }
+
+ public string Secret { get; set; }
+
+ public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get; set; }
+
+ public Uri Callback { get; set; }
+
+ public DotNetOpenAuth.OAuth.VerificationCodeFormat VerificationCodeFormat { get; set; }
+
+ public int VerificationCodeLength { get; set; }
+
+ #endregion
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs
new file mode 100644
index 0000000..7e26b45
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------
+// <copyright file="InMemoryServiceProviderAccessToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace OpenIdProviderWebForms.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public class InMemoryServiceProviderAccessToken : IServiceProviderAccessToken {
+ #region IServiceProviderAccessToken Members
+
+ public string Token { get; set; }
+
+ public DateTime? ExpirationDate { get; set; }
+
+ public string Username { get; set; }
+
+ public string[] Roles { get; set; }
+
+ #endregion
+
+ public string Secret { get; set; }
+
+ public string Scope { get; set; }
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs
new file mode 100644
index 0000000..9c02427
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------
+// <copyright file="InMemoryServiceProviderRequestToken.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace OpenIdProviderWebForms.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ public class InMemoryServiceProviderRequestToken : IServiceProviderRequestToken {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InMemoryServiceProviderRequestToken"/> class.
+ /// </summary>
+ public InMemoryServiceProviderRequestToken() {
+ this.CreatedOn = DateTime.Now;
+ }
+
+ #region IServiceProviderRequestToken Members
+
+ public string Token { get; set; }
+
+ public string ConsumerKey { get; set; }
+
+ public DateTime CreatedOn { get; set; }
+
+ public Uri Callback { get; set; }
+
+ public string VerificationCode { get; set; }
+
+ public Version ConsumerVersion { get; set; }
+
+ #endregion
+
+ public string Secret { get; set; }
+
+ public string Scope { get; set; }
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs b/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs
new file mode 100644
index 0000000..b04f736
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs
@@ -0,0 +1,117 @@
+//-----------------------------------------------------------------------
+// <copyright file="InMemoryTokenManager.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace OpenIdProviderWebForms.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth.Messages;
+ using DotNetOpenAuth.OpenId.Extensions.OAuth;
+
+ /// <summary>
+ /// A simple in-memory token manager. JUST FOR PURPOSES OF KEEPING THE SAMPLE SIMPLE.
+ /// </summary>
+ /// <remarks>
+ /// This is merely a sample app. A real web app SHOULD NEVER store a memory-only
+ /// token manager in application. It should be an IServiceProviderTokenManager
+ /// implementation that is bound to a database.
+ /// </remarks>
+ public class InMemoryTokenManager : IServiceProviderTokenManager, IOpenIdOAuthTokenManager, ICombinedOpenIdProviderTokenManager {
+ private Dictionary<string, InMemoryServiceProviderRequestToken> requestTokens = new Dictionary<string, InMemoryServiceProviderRequestToken>();
+ private Dictionary<string, InMemoryServiceProviderAccessToken> accessTokens = new Dictionary<string, InMemoryServiceProviderAccessToken>();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InMemoryTokenManager"/> class.
+ /// </summary>
+ internal InMemoryTokenManager() {
+ }
+
+ #region IServiceProviderTokenManager Members
+
+ public IConsumerDescription GetConsumer(string consumerKey) {
+ return new InMemoryConsumerDescription {
+ Key = consumerKey,
+ Secret = "some crazy secret",
+ };
+ }
+
+ public IServiceProviderRequestToken GetRequestToken(string token) {
+ return this.requestTokens[token];
+ }
+
+ public IServiceProviderAccessToken GetAccessToken(string token) {
+ throw new NotImplementedException();
+ }
+
+ public void UpdateToken(IServiceProviderRequestToken token) {
+ // Nothing to do here, since there's not database in this sample.
+ }
+
+ #endregion
+
+ #region ITokenManager Members
+
+ public string GetTokenSecret(string token) {
+ if (this.requestTokens.ContainsKey(token)) {
+ return this.requestTokens[token].Secret;
+ } else {
+ return this.accessTokens[token].Secret;
+ }
+ }
+
+ public void StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response) {
+ throw new NotImplementedException();
+ }
+
+ public bool IsRequestTokenAuthorized(string requestToken) {
+ // In OpenID+OAuth scenarios, request tokens are always authorized.
+ return true;
+ }
+
+ public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) {
+ this.requestTokens.Remove(requestToken);
+ this.accessTokens[accessToken] = new InMemoryServiceProviderAccessToken {
+ Token = accessToken,
+ Secret = accessTokenSecret,
+ };
+ }
+
+ public TokenType GetTokenType(string token) {
+ if (this.requestTokens.ContainsKey(token)) {
+ return TokenType.RequestToken;
+ } else if (this.accessTokens.ContainsKey(token)) {
+ return TokenType.AccessToken;
+ } else {
+ return TokenType.InvalidToken;
+ }
+ }
+
+ #endregion
+
+ #region IOpenIdOAuthTokenManager Members
+
+ public void StoreOpenIdAuthorizedRequestToken(string consumerKey, AuthorizationApprovedResponse authorization) {
+ this.requestTokens[authorization.RequestToken] = new InMemoryServiceProviderRequestToken {
+ Token = authorization.RequestToken,
+ Scope = authorization.Scope,
+ ConsumerVersion = authorization.Version,
+ };
+ }
+
+ #endregion
+
+ #region ICombinedOpenIdProviderTokenManager Members
+
+ public string GetConsumerKey(DotNetOpenAuth.OpenId.Realm realm) {
+ // We just use the realm as the consumer key, like Google does.
+ return realm;
+ }
+
+ #endregion
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs b/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs
new file mode 100644
index 0000000..cc4beff
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs
@@ -0,0 +1,46 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthHybrid.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace OpenIdProviderWebForms.Code {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ internal class OAuthHybrid {
+ /// <summary>
+ /// Initializes static members of the <see cref="OAuthHybrid"/> class.
+ /// </summary>
+ static OAuthHybrid() {
+ ServiceProvider = new ServiceProvider(GetServiceDescription(), TokenManager);
+ }
+
+ internal static IServiceProviderTokenManager TokenManager {
+ get {
+ // This is merely a sample app. A real web app SHOULD NEVER store a memory-only
+ // token manager in application. It should be an IServiceProviderTokenManager
+ // implementation that is bound to a database.
+ var tokenManager = (IServiceProviderTokenManager)HttpContext.Current.Application["TokenManager"];
+ if (tokenManager == null) {
+ HttpContext.Current.Application["TokenManager"] = tokenManager = new InMemoryTokenManager();
+ }
+
+ return tokenManager;
+ }
+ }
+
+ internal static ServiceProvider ServiceProvider { get; private set; }
+
+ internal static ServiceProviderDescription GetServiceDescription() {
+ return new ServiceProviderDescription {
+ TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
+ };
+ }
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
index ceea842..ffb0f2f 100644
--- a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
+++ b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
@@ -83,12 +83,20 @@
<Content Include="user_xrds.aspx" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="access_token.ashx.cs">
+ <DependentUpon>access_token.ashx</DependentUpon>
+ </Compile>
+ <Compile Include="Code\InMemoryConsumerDescription.cs" />
+ <Compile Include="Code\InMemoryServiceProviderAccessToken.cs" />
<Compile Include="Code\CustomStore.cs" />
<Compile Include="Code\CustomStoreDataSet.Designer.cs">
<DependentUpon>CustomStoreDataSet.xsd</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
+ <Compile Include="Code\InMemoryServiceProviderRequestToken.cs" />
+ <Compile Include="Code\InMemoryTokenManager.cs" />
+ <Compile Include="Code\OAuthHybrid.cs" />
<Compile Include="Code\ReadOnlyXmlMembershipProvider.cs" />
<Compile Include="Code\TracePageAppender.cs" />
<Compile Include="Code\Util.cs" />
@@ -157,6 +165,7 @@
<Content Include="TracePage.aspx" />
</ItemGroup>
<ItemGroup>
+ <Content Include="access_token.ashx" />
<None Include="Code\CustomStoreDataSet.xsc">
<DependentUpon>CustomStoreDataSet.xsd</DependentUpon>
</None>
@@ -190,7 +199,7 @@
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
- <AutoAssignPort>True</AutoAssignPort>
+ <AutoAssignPort>False</AutoAssignPort>
<DevelopmentServerPort>4860</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>
diff --git a/samples/OpenIdProviderWebForms/Web.config b/samples/OpenIdProviderWebForms/Web.config
index c3c7ef9..159dcd1 100644
--- a/samples/OpenIdProviderWebForms/Web.config
+++ b/samples/OpenIdProviderWebForms/Web.config
@@ -98,9 +98,10 @@
<!-- Trust level discussion:
Full: everything works
High: TRACE compilation symbol must NOT be defined
- Medium/Low: doesn't work on default machine.config, because WebPermission.Connect is denied.
+ Medium: doesn't work unless originUrl=".*" or WebPermission.Connect is extended.
+ Low: doesn't work because WebPermission.Connect is denied.
-->
- <trust level="High" originUrl=""/>
+ <trust level="Medium" originUrl=".*"/>
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
@@ -183,6 +184,7 @@
</handlers>
</system.webServer>
<runtime>
+ <legacyHMACWarning enabled="0" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
diff --git a/samples/OpenIdProviderWebForms/access_token.ashx b/samples/OpenIdProviderWebForms/access_token.ashx
new file mode 100644
index 0000000..dcb088e
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/access_token.ashx
@@ -0,0 +1 @@
+<%@ WebHandler Language="C#" CodeBehind="access_token.ashx.cs" Class="OpenIdProviderWebForms.access_token" %>
diff --git a/samples/OpenIdProviderWebForms/access_token.ashx.cs b/samples/OpenIdProviderWebForms/access_token.ashx.cs
new file mode 100644
index 0000000..b895da9
--- /dev/null
+++ b/samples/OpenIdProviderWebForms/access_token.ashx.cs
@@ -0,0 +1,23 @@
+namespace OpenIdProviderWebForms {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Web;
+ using System.Web.Services;
+ using DotNetOpenAuth.OAuth;
+ using OpenIdProviderWebForms.Code;
+
+ [WebService(Namespace = "http://tempuri.org/")]
+ [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
+ public class access_token : IHttpHandler {
+ public bool IsReusable {
+ get { return true; }
+ }
+
+ public void ProcessRequest(HttpContext context) {
+ var request = OAuthHybrid.ServiceProvider.ReadAccessTokenRequest();
+ var response = OAuthHybrid.ServiceProvider.PrepareAccessTokenMessage(request);
+ OAuthHybrid.ServiceProvider.Channel.Send(response);
+ }
+ }
+}
diff --git a/samples/OpenIdProviderWebForms/decide.aspx b/samples/OpenIdProviderWebForms/decide.aspx
index 4a6e2d8..d63364e 100644
--- a/samples/OpenIdProviderWebForms/decide.aspx
+++ b/samples/OpenIdProviderWebForms/decide.aspx
@@ -17,6 +17,10 @@
<td><asp:Label runat="server" ID='realmLabel' /> </td>
</tr>
</table>
+ <asp:Panel runat="server" ID="OAuthPanel" Visible="false">
+ <p>In addition the relying party has asked for permission to access your private data. </p>
+ <asp:CheckBox runat="server" Text="Allow the relying party to access my private data" ID="oauthPermission" />
+ </asp:Panel>
<p>Allow this to proceed? </p>
<uc1:ProfileFields ID="profileFields" runat="server" Visible="false" />
<asp:Button ID="yes_button" OnClick="Yes_Click" Text=" yes " runat="Server" />
diff --git a/samples/OpenIdProviderWebForms/decide.aspx.cs b/samples/OpenIdProviderWebForms/decide.aspx.cs
index 3a14cf7..6146bd2 100644
--- a/samples/OpenIdProviderWebForms/decide.aspx.cs
+++ b/samples/OpenIdProviderWebForms/decide.aspx.cs
@@ -6,6 +6,7 @@ namespace OpenIdProviderWebForms {
using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy;
using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.Provider;
+ using OpenIdProviderWebForms.Code;
/// <summary>
/// Page for giving the user the option to continue or cancel out of authentication with a consumer.
@@ -21,6 +22,11 @@ namespace OpenIdProviderWebForms {
this.realmLabel.Text = ProviderEndpoint.PendingRequest.Realm.ToString();
+ var oauthRequest = OAuthHybrid.ServiceProvider.ReadAuthorizationRequest(ProviderEndpoint.PendingRequest);
+ if (oauthRequest != null) {
+ this.OAuthPanel.Visible = true;
+ }
+
if (ProviderEndpoint.PendingAuthenticationRequest != null) {
if (ProviderEndpoint.PendingAuthenticationRequest.IsDirectedIdentity) {
ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier = Code.Util.BuildIdentityUrl();
@@ -51,6 +57,24 @@ namespace OpenIdProviderWebForms {
}
protected void Yes_Click(object sender, EventArgs e) {
+ if (!Page.IsValid) {
+ return;
+ }
+
+ if (this.OAuthPanel.Visible) {
+ string consumerKey = null;
+ string grantedScope = null;
+ if (this.oauthPermission.Checked) {
+ // This SIMPLE sample merely uses the realm as the consumerKey,
+ // but in a real app this will probably involve a database lookup to translate
+ // the realm to a known consumerKey.
+ consumerKey = ProviderEndpoint.PendingRequest.Realm;
+ grantedScope = string.Empty; // we don't scope individual access rights on this sample
+ }
+
+ OAuthHybrid.ServiceProvider.AttachAuthorizationResponse(ProviderEndpoint.PendingRequest, consumerKey, grantedScope);
+ }
+
var sregRequest = ProviderEndpoint.PendingRequest.GetExtension<ClaimsRequest>();
ClaimsResponse sregResponse = null;
if (sregRequest != null) {
diff --git a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs
index 05386cd..3aa6271 100644
--- a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs
+++ b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs
@@ -50,6 +50,24 @@ namespace OpenIdProviderWebForms {
protected global::System.Web.UI.WebControls.Label realmLabel;
/// <summary>
+ /// OAuthPanel control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.Panel OAuthPanel;
+
+ /// <summary>
+ /// oauthPermission control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.CheckBox oauthPermission;
+
+ /// <summary>
/// profileFields control.
/// </summary>
/// <remarks>
diff --git a/samples/OpenIdRelyingPartyClassicAsp/login.asp b/samples/OpenIdRelyingPartyClassicAsp/login.asp
index 878ab39..d222e57 100644
--- a/samples/OpenIdRelyingPartyClassicAsp/login.asp
+++ b/samples/OpenIdRelyingPartyClassicAsp/login.asp
@@ -17,23 +17,37 @@
thisPageUrl = "http://" + Request.ServerVariables("HTTP_HOST") + Request.ServerVariables("URL")
requestUrl = "http://" + Request.ServerVariables("HTTP_HOST") + Request.ServerVariables("HTTP_URL")
Set dnoi = server.CreateObject("DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty")
+ On Error Resume Next
Set authentication = dnoi.ProcessAuthentication(requestUrl, Request.Form)
+ If Err.number <> 0 Then
+ Response.Write "<p>" + Server.HTMLEncode(Err.Description) + "</p>"
+ End If
+ On Error Goto 0
if Not authentication Is Nothing then
If authentication.Successful Then
Session("ClaimedIdentifier") = authentication.ClaimedIdentifier
- Session("Email") = authentication.ClaimsResponse.Email
- Session("Nickname") = authentication.ClaimsResponse.Nickname
- Session("FullName") = authentication.ClaimsResponse.FullName
+ If Not authentication.ClaimsResponse Is Nothing Then
+ Session("Email") = authentication.ClaimsResponse.Email
+ Session("Nickname") = authentication.ClaimsResponse.Nickname
+ Session("FullName") = authentication.ClaimsResponse.FullName
+ End If
Response.Redirect "MembersOnly.asp"
else
Response.Write "Authentication failed: " + authentication.ExceptionMessage
end if
elseif Request.Form("openid_identifier") <> "" then
dim redirectUrl
+ On Error Resume Next
' redirectUrl = dnoi.CreateRequest(Request.Form("openid_identifier"), realm, thisPageUrl)
redirectUrl = dnoi.CreateRequestWithSimpleRegistration(Request.Form("openid_identifier"), realm, thisPageUrl, "nickname,email", "fullname")
- Response.Redirect redirectUrl
+ If Err.number <> 0 Then
+ Response.Write "<p>" + Server.HTMLEncode(Err.Description) + "</p>"
+ Else
+ Response.Redirect redirectUrl
+ End If
+ On Error Goto 0
End If
+
%>
<form action="login.asp" method="post">
OpenID Login:
diff --git a/samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs b/samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs
index 784533b..fd22389 100644
--- a/samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs
+++ b/samples/OpenIdRelyingPartyMvc/Controllers/UserController.cs
@@ -10,6 +10,8 @@
using DotNetOpenAuth.OpenId.RelyingParty;
public class UserController : Controller {
+ private static OpenIdRelyingParty openid = new OpenIdRelyingParty();
+
public ActionResult Index() {
if (!User.Identity.IsAuthenticated) {
Response.Redirect("/User/Login?ReturnUrl=Index");
@@ -34,7 +36,6 @@
[ValidateInput(false)]
public ActionResult Authenticate(string returnUrl) {
- var openid = new OpenIdRelyingParty();
var response = openid.GetResponse();
if (response == null) {
// Stage 2: user submitting Identifier
diff --git a/samples/OpenIdRelyingPartyMvc/Web.config b/samples/OpenIdRelyingPartyMvc/Web.config
index c4a4b71..c3bfa41 100644
--- a/samples/OpenIdRelyingPartyMvc/Web.config
+++ b/samples/OpenIdRelyingPartyMvc/Web.config
@@ -172,4 +172,8 @@
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
</system.webServer>
+
+ <runtime>
+ <legacyHMACWarning enabled="0" />
+ </runtime>
</configuration>
diff --git a/samples/OpenIdRelyingPartyWebForms/Global.asax.cs b/samples/OpenIdRelyingPartyWebForms/Global.asax.cs
index ac74853..6583289 100644
--- a/samples/OpenIdRelyingPartyWebForms/Global.asax.cs
+++ b/samples/OpenIdRelyingPartyWebForms/Global.asax.cs
@@ -42,6 +42,20 @@
}
}
+ internal static InMemoryTokenManager OwnSampleOPHybridTokenManager {
+ get {
+ var tokenManager = (InMemoryTokenManager)HttpContext.Current.Application["OwnSampleOPHybridTokenManager"];
+ if (tokenManager == null) {
+ string consumerKey = new Uri(HttpContext.Current.Request.Url, HttpContext.Current.Request.ApplicationPath).AbsoluteUri;
+ string consumerSecret = "some crazy secret";
+ tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret);
+ HttpContext.Current.Application["OwnSampleOPHybridTokenManager"] = tokenManager;
+ }
+
+ return tokenManager;
+ }
+ }
+
public static string ToString(NameValueCollection collection) {
using (StringWriter sw = new StringWriter()) {
foreach (string key in collection.Keys) {
diff --git a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
index d3bf92c..6f5df5c 100644
--- a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
+++ b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
@@ -101,6 +101,13 @@
<Compile Include="Code\InMemoryTokenManager.cs" />
<Compile Include="Code\State.cs" />
<Compile Include="Code\TracePageAppender.cs" />
+ <Compile Include="loginPlusOAuthSampleOP.aspx.cs">
+ <DependentUpon>loginPlusOAuthSampleOP.aspx</DependentUpon>
+ <SubType>ASPXCodeBehind</SubType>
+ </Compile>
+ <Compile Include="loginPlusOAuthSampleOP.aspx.designer.cs">
+ <DependentUpon>loginPlusOAuthSampleOP.aspx</DependentUpon>
+ </Compile>
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
@@ -169,6 +176,7 @@
<Content Include="xrds.aspx" />
</ItemGroup>
<ItemGroup>
+ <Content Include="loginPlusOAuthSampleOP.aspx" />
<Content Include="images\attention.png" />
<Content Include="images\dotnetopenid_tiny.gif" />
<Content Include="images\openid_login.gif" />
diff --git a/samples/OpenIdRelyingPartyWebForms/Web.config b/samples/OpenIdRelyingPartyWebForms/Web.config
index 0ae3c6c..445c419 100644
--- a/samples/OpenIdRelyingPartyWebForms/Web.config
+++ b/samples/OpenIdRelyingPartyWebForms/Web.config
@@ -67,9 +67,10 @@
<!-- Trust level discussion:
Full: everything works
High: TRACE compilation symbol must NOT be defined
- Medium/Low: doesn't work on default machine.config, because WebPermission.Connect is denied.
+ Medium: doesn't work unless originUrl=".*" or WebPermission.Connect is extended.
+ Low: doesn't work because WebPermission.Connect is denied.
-->
- <trust level="High" originUrl=""/>
+ <trust level="Medium" originUrl=".*"/>
</system.web>
<!-- log4net is a 3rd party (free) logger library that dotnetopenid will use if present but does not require. -->
@@ -102,4 +103,7 @@
</logger>
</log4net>
+ <runtime>
+ <legacyHMACWarning enabled="0" />
+ </runtime>
</configuration>
diff --git a/samples/OpenIdRelyingPartyWebForms/ajaxlogin.aspx b/samples/OpenIdRelyingPartyWebForms/ajaxlogin.aspx
index df29914..232cf3f 100644
--- a/samples/OpenIdRelyingPartyWebForms/ajaxlogin.aspx
+++ b/samples/OpenIdRelyingPartyWebForms/ajaxlogin.aspx
@@ -3,6 +3,10 @@
<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty" TagPrefix="openid" %>
<asp:Content runat="server" ContentPlaceHolderID="head">
+<script>
+// window.openid_visible_iframe = true; // causes the hidden iframe to show up
+// window.openid_trace = true; // causes lots of messages
+</script>
<style type="text/css">
.textbox
{
diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx b/samples/OpenIdRelyingPartyWebForms/login.aspx
index 281725c..bca0676 100644
--- a/samples/OpenIdRelyingPartyWebForms/login.aspx
+++ b/samples/OpenIdRelyingPartyWebForms/login.aspx
@@ -7,8 +7,7 @@
<rp:OpenIdLogin ID="OpenIdLogin1" runat="server" CssClass="openid_login" RequestCountry="Request"
RequestEmail="Require" RequestGender="Require" RequestPostalCode="Require" RequestTimeZone="Require"
RememberMeVisible="True" PolicyUrl="~/PrivacyPolicy.aspx" TabIndex="1"
- OnLoggedIn="OpenIdLogin1_LoggedIn" OnLoggingIn="OpenIdLogin1_LoggingIn"
- OnSetupRequired="OpenIdLogin1_SetupRequired" />
+ OnLoggedIn="OpenIdLogin1_LoggedIn" OnLoggingIn="OpenIdLogin1_LoggingIn" />
<fieldset title="Knobs">
<asp:CheckBox ID="requireSslCheckBox" runat="server"
Text="RequireSsl (high security) mode"
@@ -22,9 +21,6 @@
</asp:CheckBoxList>
<p>Try the PPID identifier functionality against the OpenIDProviderMvc sample.</p>
</fieldset>
- <br />
- <asp:Label ID="setupRequiredLabel" runat="server" EnableViewState="False" Text="You must log into your Provider first to use Immediate mode."
- Visible="False" />
<p>
<rp:OpenIdButton runat="server" ImageUrl="~/images/yahoo.png" Text="Login with Yahoo!" ID="yahooLoginButton"
Identifier="https://me.yahoo.com/" />
diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx.cs b/samples/OpenIdRelyingPartyWebForms/login.aspx.cs
index 1de942a..6721e9b 100644
--- a/samples/OpenIdRelyingPartyWebForms/login.aspx.cs
+++ b/samples/OpenIdRelyingPartyWebForms/login.aspx.cs
@@ -35,10 +35,6 @@ namespace OpenIdRelyingPartyWebForms {
State.PapePolicies = e.Response.GetExtension<PolicyResponse>();
}
- protected void OpenIdLogin1_SetupRequired(object sender, OpenIdEventArgs e) {
- this.setupRequiredLabel.Visible = true;
- }
-
private void prepareRequest(IAuthenticationRequest request) {
// Collect the PAPE policies requested by the user.
List<string> policies = new List<string>();
diff --git a/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs
index 944f5ff..4a2521c 100644
--- a/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs
+++ b/samples/OpenIdRelyingPartyWebForms/login.aspx.designer.cs
@@ -41,15 +41,6 @@ namespace OpenIdRelyingPartyWebForms {
protected global::System.Web.UI.WebControls.CheckBoxList papePolicies;
/// <summary>
- /// setupRequiredLabel control.
- /// </summary>
- /// <remarks>
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- /// </remarks>
- protected global::System.Web.UI.WebControls.Label setupRequiredLabel;
-
- /// <summary>
/// yahooLoginButton control.
/// </summary>
/// <remarks>
diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx
new file mode 100644
index 0000000..863f335
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx
@@ -0,0 +1,34 @@
+<%@ Page Language="C#" AutoEventWireup="True" CodeBehind="loginPlusOAuthSampleOP.aspx.cs"
+ Inherits="OpenIdRelyingPartyWebForms.loginPlusOAuthSampleOP" ValidateRequest="false"
+ MasterPageFile="~/Site.Master" %>
+
+<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty"
+ TagPrefix="rp" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <h2>Login Page </h2>
+ <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex='0'>
+ <asp:View ID="View1" runat="server">
+ <asp:Label runat="server" Text="OpenIdProviderWebForms sample's OP Identifier or Claimed Identifier: " />
+ <rp:OpenIdTextBox runat="server" ID="identifierBox" Text="http://localhost:4860/"
+ OnLoggingIn="identifierBox_LoggingIn" OnLoggedIn="identifierBox_LoggedIn" OnCanceled="identifierBox_Failed"
+ OnFailed="identifierBox_Failed" />
+ <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="required"
+ ControlToValidate="identifierBox" />
+ <br />
+ <asp:Button ID="beginButton" runat="server" Text="Login + OAuth request" OnClick="beginButton_Click" />
+ </asp:View>
+ <asp:View ID="AuthorizationGiven" runat="server">
+ Authentication succeeded, and OAuth access was granted.
+ <p>The actual login step is aborted since this sample focuses on the process only
+ up to this point.</p>
+ </asp:View>
+ <asp:View ID="AuthorizationDenied" runat="server">
+ Authentication succeeded, but OAuth access was denied.
+ <p>The actual login step is aborted since this sample focuses on the process only
+ up to this point.</p>
+ </asp:View>
+ <asp:View ID="AuthenticationFailed" runat="server">
+ Authentication failed or was canceled.
+ </asp:View>
+ </asp:MultiView>
+</asp:Content>
diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs
new file mode 100644
index 0000000..c7d3168
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs
@@ -0,0 +1,62 @@
+namespace OpenIdRelyingPartyWebForms {
+ using System;
+ using System.Web.Security;
+ using DotNetOpenAuth.ApplicationBlock;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+ using DotNetOpenAuth.OAuth.Messages;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ public partial class loginPlusOAuthSampleOP : System.Web.UI.Page {
+ protected void Page_Load(object sender, EventArgs e) {
+ }
+
+ protected void beginButton_Click(object sender, EventArgs e) {
+ if (!Page.IsValid) {
+ return;
+ }
+
+ this.identifierBox.LogOn();
+ }
+
+ protected void identifierBox_LoggingIn(object sender, OpenIdEventArgs e) {
+ ServiceProviderDescription serviceDescription = new ServiceProviderDescription {
+ TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
+ };
+
+ WebConsumer consumer = new WebConsumer(serviceDescription, Global.OwnSampleOPHybridTokenManager);
+ consumer.AttachAuthorizationRequest(e.Request, "http://tempuri.org/IDataApi/GetName");
+ }
+
+ protected void identifierBox_LoggedIn(object sender, OpenIdEventArgs e) {
+ State.FetchResponse = e.Response.GetExtension<FetchResponse>();
+
+ ServiceProviderDescription serviceDescription = new ServiceProviderDescription {
+ AccessTokenEndpoint = new MessageReceivingEndpoint(new Uri(e.Response.Provider.Uri, "/access_token.ashx"), HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.PostRequest),
+ TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
+ };
+ WebConsumer consumer = new WebConsumer(serviceDescription, Global.OwnSampleOPHybridTokenManager);
+
+ AuthorizedTokenResponse accessToken = consumer.ProcessUserAuthorization(e.Response);
+ if (accessToken != null) {
+ this.MultiView1.SetActiveView(this.AuthorizationGiven);
+
+ // At this point, the access token would be somehow associated with the user
+ // account at the RP.
+ ////Database.Associate(e.Response.ClaimedIdentifier, accessToken.AccessToken);
+ } else {
+ this.MultiView1.SetActiveView(this.AuthorizationDenied);
+ }
+
+ // Avoid the redirect
+ e.Cancel = true;
+ }
+
+ protected void identifierBox_Failed(object sender, OpenIdEventArgs e) {
+ this.MultiView1.SetActiveView(this.AuthenticationFailed);
+ }
+ }
+}
diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs
new file mode 100644
index 0000000..9bf29b9
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs
@@ -0,0 +1,88 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4918
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace OpenIdRelyingPartyWebForms {
+
+
+ public partial class loginPlusOAuthSampleOP {
+
+ /// <summary>
+ /// MultiView1 control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.MultiView MultiView1;
+
+ /// <summary>
+ /// View1 control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.View View1;
+
+ /// <summary>
+ /// identifierBox control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox identifierBox;
+
+ /// <summary>
+ /// RequiredFieldValidator1 control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1;
+
+ /// <summary>
+ /// beginButton control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.Button beginButton;
+
+ /// <summary>
+ /// AuthorizationGiven control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.View AuthorizationGiven;
+
+ /// <summary>
+ /// AuthorizationDenied control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.View AuthorizationDenied;
+
+ /// <summary>
+ /// AuthenticationFailed control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.View AuthenticationFailed;
+ }
+}
diff --git a/samples/OpenIdRelyingPartyWebForms/logout.aspx b/samples/OpenIdRelyingPartyWebForms/logout.aspx
index 71c0433..156f800 100644
--- a/samples/OpenIdRelyingPartyWebForms/logout.aspx
+++ b/samples/OpenIdRelyingPartyWebForms/logout.aspx
@@ -7,6 +7,7 @@
State.FriendlyLoginName = null;
State.ProfileFields = null;
System.Web.Security.FormsAuthentication.SignOut();
+ DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.LogOff();
Response.Redirect("~/");
}
</script>
diff --git a/samples/OpenIdRelyingPartyWebForms/xrds.aspx b/samples/OpenIdRelyingPartyWebForms/xrds.aspx
index 9e201d0..99a535c 100644
--- a/samples/OpenIdRelyingPartyWebForms/xrds.aspx
+++ b/samples/OpenIdRelyingPartyWebForms/xrds.aspx
@@ -17,7 +17,9 @@ is default.aspx.
<URI priority="1"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/login.aspx"))%></URI>
<URI priority="2"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginProgrammatic.aspx"))%></URI>
<URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/ajaxlogin.aspx"))%></URI>
- <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI>
+ <URI priority="4"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI>
+ <URI priority="5"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuth.aspx"))%></URI>
+ <URI priority="6"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuthSampleOP.aspx"))%></URI>
</Service>
</XRD>
</xrds:XRDS>
diff --git a/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs b/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs
new file mode 100644
index 0000000..4980898
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------
+// <copyright file="CreateWebApplication.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Linq;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+ using Microsoft.Web.Administration;
+
+ /// <summary>
+ /// Creates or updates web applications within an existing web site in IIS.
+ /// </summary>
+ public class CreateWebApplication : Task {
+ /// <summary>
+ /// Gets or sets the name of the application pool that should host the web application.
+ /// </summary>
+ /// <value>The name of an existing application pool.</value>
+ public string ApplicationPoolName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the web site under which to create the web application.
+ /// </summary>
+ /// <value>The name of the existing web site.</value>
+ [Required]
+ public string WebSiteName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the virtual paths within the web site that will access these applications.
+ /// </summary>
+ /// <value>The virtual path, which must start with '/'.</value>
+ [Required]
+ public ITaskItem[] VirtualPaths { get; set; }
+
+ /// <summary>
+ /// Gets or sets the full file system paths to the web applications.
+ /// </summary>
+ /// <value>The physical path.</value>
+ [Required]
+ public ITaskItem[] PhysicalPaths { get; set; }
+
+ /// <summary>
+ /// Executes this instance.
+ /// </summary>
+ /// <returns>A value indicating whether the task completed successfully.</returns>
+ public override bool Execute() {
+ var serverManager = new ServerManager();
+
+ if (this.PhysicalPaths.Length != this.VirtualPaths.Length) {
+ Log.LogError(TaskStrings.MismatchingArrayLengths, "PhysicalPath", "VirtualPath");
+ return false;
+ }
+
+ if (this.VirtualPaths.Length == 0) {
+ // Nothing to do.
+ return true;
+ }
+
+ // Find the root web site that this web application will be created under.
+ var site = serverManager.Sites.FirstOrDefault(s => string.Equals(s.Name, this.WebSiteName, StringComparison.OrdinalIgnoreCase));
+ if (site == null) {
+ Log.LogError(TaskStrings.NoMatchingWebSiteFound, this.WebSiteName);
+ return false;
+ }
+
+ Log.LogMessage(MessageImportance.Normal, "Creating web applications under web site: {0}", site.Name);
+
+ for (int i = 0; i < this.PhysicalPaths.Length; i++) {
+ string physicalPath = this.PhysicalPaths[i].ItemSpec;
+ string virtualPath = this.VirtualPaths[i].ItemSpec;
+
+ Log.LogMessage(MessageImportance.Normal, "\t{0} -> {1}", virtualPath, physicalPath);
+
+ var app = site.Applications.FirstOrDefault(a => string.Equals(a.Path, virtualPath, StringComparison.OrdinalIgnoreCase));
+ if (app == null) {
+ app = site.Applications.Add(virtualPath, physicalPath);
+ } else {
+ // Ensure physical path is set correctly.
+ var appRoot = app.VirtualDirectories.First(vd => vd.Path == "/");
+ appRoot.PhysicalPath = physicalPath;
+ }
+
+ if (!string.IsNullOrEmpty(this.ApplicationPoolName)) {
+ app.ApplicationPoolName = this.ApplicationPoolName;
+ }
+ }
+
+ serverManager.CommitChanges();
+ return true;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs b/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs
new file mode 100644
index 0000000..930a8c4
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs
@@ -0,0 +1,66 @@
+//-----------------------------------------------------------------------
+// <copyright file="DeleteWebApplication.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Linq;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+ using Microsoft.Web.Administration;
+
+ /// <summary>
+ /// Deletes a web application from IIS.
+ /// </summary>
+ public class DeleteWebApplication : Task {
+ /// <summary>
+ /// Gets or sets the name of the web site under which to create the web application.
+ /// </summary>
+ /// <value>The name of the existing web site.</value>
+ [Required]
+ public string WebSiteName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the virtual paths within the web site that will access these applications.
+ /// </summary>
+ /// <value>The virtual path, which must start with '/'.</value>
+ [Required]
+ public ITaskItem[] VirtualPaths { get; set; }
+
+ /// <summary>
+ /// Executes this instance.
+ /// </summary>
+ /// <returns>A value indicating whether the task completed successfully.</returns>
+ public override bool Execute() {
+ var serverManager = new ServerManager();
+
+ // Find the root web site that this web application will be created under.
+ var site = serverManager.Sites.FirstOrDefault(s => string.Equals(s.Name, this.WebSiteName, StringComparison.OrdinalIgnoreCase));
+ if (site == null) {
+ Log.LogMessage(MessageImportance.Low, TaskStrings.NoMatchingWebSiteFound, this.WebSiteName);
+ return true;
+ }
+
+ if (this.VirtualPaths.Length == 0) {
+ // Nothing to do.
+ return true;
+ }
+
+ foreach (ITaskItem path in this.VirtualPaths) {
+ var app = site.Applications.FirstOrDefault(a => string.Equals(a.Path, path.ItemSpec, StringComparison.OrdinalIgnoreCase));
+ if (app != null) {
+ site.Applications.Remove(app);
+ Log.LogMessage(MessageImportance.Normal, TaskStrings.DeletedWebApplication, app.Path);
+ } else {
+ Log.LogMessage(MessageImportance.Low, TaskStrings.WebApplicationNotFoundSoNotDeleted, path.ItemSpec);
+ }
+ }
+
+ serverManager.CommitChanges();
+
+ return true;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
index b198a22..4eb920e 100644
--- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
+++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
@@ -36,6 +36,10 @@
<Reference Include="Microsoft.Build.Utilities.v3.5">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
+ <Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>$(SystemRoot)\System32\inetsrv\Microsoft.Web.Administration.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -47,6 +51,9 @@
<Compile Include="ChangeProjectReferenceToAssemblyReference.cs" />
<Compile Include="CompareFiles.cs" />
<Compile Include="ChangeAssemblyReference.cs" />
+ <Compile Include="CreateWebApplication.cs" />
+ <Compile Include="DeleteWebApplication.cs" />
+ <Compile Include="FilterItems.cs" />
<Compile Include="GetBuildVersion.cs" />
<Compile Include="CheckAdminRights.cs" />
<Compile Include="ReSignDelaySignedAssemblies.cs" />
@@ -54,6 +61,18 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SignatureVerification.cs" />
<Compile Include="SnToolTask.cs" />
+ <Compile Include="TaskStrings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>TaskStrings.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Trim.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="TaskStrings.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>TaskStrings.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/src/DotNetOpenAuth.BuildTasks/FilterItems.cs b/src/DotNetOpenAuth.BuildTasks/FilterItems.cs
new file mode 100644
index 0000000..97631c6
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/FilterItems.cs
@@ -0,0 +1,24 @@
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using Microsoft.Build.Utilities;
+ using Microsoft.Build.Framework;
+
+ public class FilterItems : Task {
+ [Required]
+ public ITaskItem[] InputItems { get; set; }
+
+ [Required]
+ public ITaskItem[] StartsWithAny { get; set; }
+
+ [Output]
+ public ITaskItem[] FilteredItems { get; set; }
+
+ public override bool Execute() {
+ FilteredItems = InputItems.Where(item => StartsWithAny.Any(filter => item.ItemSpec.StartsWith(filter.ItemSpec, StringComparison.OrdinalIgnoreCase))).ToArray();
+ return true;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs b/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs
index 9ba94eb..1c32632 100644
--- a/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs
+++ b/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs
@@ -22,7 +22,16 @@ namespace DotNetOpenAuth.BuildTasks {
/// Generates the full path to tool.
/// </summary>
protected override string GenerateFullPathToTool() {
- return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft SDKs\Windows\v6.0A\bin\" + this.ToolName);
+ string[] versions = new[] { "v6.0A", "v6.1" };
+ string fullPath = null;
+ foreach (string version in versions) {
+ fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft SDKs\Windows\" + version + @"\bin\" + this.ToolName);
+ if (File.Exists(fullPath)) {
+ return fullPath;
+ }
+ }
+
+ throw new FileNotFoundException("Unable to find sn.exe tool.", fullPath);
}
}
}
diff --git a/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs b/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs
new file mode 100644
index 0000000..a727695
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs
@@ -0,0 +1,99 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4918
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class TaskStrings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal TaskStrings() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.BuildTasks.TaskStrings", typeof(TaskStrings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Web application &apos;{0}&apos; deleted..
+ /// </summary>
+ internal static string DeletedWebApplication {
+ get {
+ return ResourceManager.GetString("DeletedWebApplication", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The {0} and {1} properties must be set to arrays of equal length..
+ /// </summary>
+ internal static string MismatchingArrayLengths {
+ get {
+ return ResourceManager.GetString("MismatchingArrayLengths", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to No web site with the name &apos;{0}&apos; found..
+ /// </summary>
+ internal static string NoMatchingWebSiteFound {
+ get {
+ return ResourceManager.GetString("NoMatchingWebSiteFound", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Web application &apos;{0}&apos; was not found, so it was not deleted..
+ /// </summary>
+ internal static string WebApplicationNotFoundSoNotDeleted {
+ get {
+ return ResourceManager.GetString("WebApplicationNotFoundSoNotDeleted", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx b/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx
new file mode 100644
index 0000000..2aaa32e
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="DeletedWebApplication" xml:space="preserve">
+ <value>Web application '{0}' deleted.</value>
+ </data>
+ <data name="MismatchingArrayLengths" xml:space="preserve">
+ <value>The {0} and {1} properties must be set to arrays of equal length.</value>
+ </data>
+ <data name="NoMatchingWebSiteFound" xml:space="preserve">
+ <value>No web site with the name '{0}' found.</value>
+ </data>
+ <data name="WebApplicationNotFoundSoNotDeleted" xml:space="preserve">
+ <value>Web application '{0}' was not found, so it was not deleted.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.BuildTasks/Trim.cs b/src/DotNetOpenAuth.BuildTasks/Trim.cs
new file mode 100644
index 0000000..1cc943e
--- /dev/null
+++ b/src/DotNetOpenAuth.BuildTasks/Trim.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="Trim.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.BuildTasks {
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+
+ /// <summary>
+ /// Trims item identities.
+ /// </summary>
+ public class Trim : Task {
+ /// <summary>
+ /// Gets or sets the characters that should be trimmed off if found at the start of items' ItemSpecs.
+ /// </summary>
+ public string StartCharacters { get; set; }
+
+ /// <summary>
+ /// Gets or sets the characters that should be trimmed off if found at the end of items' ItemSpecs.
+ /// </summary>
+ public string EndCharacters { get; set; }
+
+ /// <summary>
+ /// Gets or sets the items with ItemSpec's to be trimmed.
+ /// </summary>
+ [Required]
+ public ITaskItem[] Inputs { get; set; }
+
+ /// <summary>
+ /// Gets or sets the items with trimmed ItemSpec strings.
+ /// </summary>
+ [Output]
+ public ITaskItem[] Outputs { get; set; }
+
+ /// <summary>
+ /// Executes this instance.
+ /// </summary>
+ /// <returns>A value indicating whether the task completed successfully.</returns>
+ public override bool Execute() {
+ this.Outputs = new ITaskItem[this.Inputs.Length];
+ for (int i = 0; i < this.Inputs.Length; i++) {
+ this.Outputs[i] = new TaskItem(this.Inputs[i]);
+ if (!string.IsNullOrEmpty(this.StartCharacters)) {
+ this.Outputs[i].ItemSpec = this.Outputs[i].ItemSpec.TrimStart(this.StartCharacters.ToCharArray());
+ }
+ if (!string.IsNullOrEmpty(this.EndCharacters)) {
+ this.Outputs[i].ItemSpec = this.Outputs[i].ItemSpec.TrimEnd(this.EndCharacters.ToCharArray());
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 680a9ef..7e92cb5 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -163,6 +163,7 @@
<Compile Include="Hosting\HostingTests.cs" />
<Compile Include="Hosting\HttpHost.cs" />
<Compile Include="Hosting\TestingWorkerRequest.cs" />
+ <Compile Include="LocalizationTests.cs" />
<Compile Include="Messaging\CollectionAssert.cs" />
<Compile Include="Messaging\EnumerableCacheTests.cs" />
<Compile Include="Messaging\ErrorUtilitiesTests.cs" />
@@ -185,6 +186,7 @@
<Compile Include="Mocks\MockHttpRequest.cs" />
<Compile Include="Mocks\MockIdentifier.cs" />
<Compile Include="Mocks\MockOpenIdExtension.cs" />
+ <Compile Include="Mocks\MockRealm.cs" />
<Compile Include="Mocks\MockTransformationBindingElement.cs" />
<Compile Include="Mocks\MockReplayProtectionBindingElement.cs" />
<Compile Include="Mocks\TestBaseMessage.cs" />
diff --git a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
index ff72c66..d7de7a1 100644
--- a/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
+++ b/src/DotNetOpenAuth.Test/Hosting/HostingTests.cs
@@ -18,15 +18,19 @@ namespace DotNetOpenAuth.Test.Hosting {
public class HostingTests : TestBase {
[TestMethod]
public void AspHostBasicTest() {
- using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host.BaseUri);
- using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
- Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
- using (StreamReader sr = new StreamReader(response.GetResponseStream())) {
- string content = sr.ReadToEnd();
- StringAssert.Contains(content, "Test home page");
+ try {
+ using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host.BaseUri);
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
+ Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
+ using (StreamReader sr = new StreamReader(response.GetResponseStream())) {
+ string content = sr.ReadToEnd();
+ StringAssert.Contains(content, "Test home page");
+ }
}
}
+ } catch (FileNotFoundException ex) {
+ Assert.Inconclusive("Unable to execute hosted ASP.NET tests because {0} could not be found. {1}", ex.FileName, ex.FusionLog);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/LocalizationTests.cs b/src/DotNetOpenAuth.Test/LocalizationTests.cs
new file mode 100644
index 0000000..50e9a34
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/LocalizationTests.cs
@@ -0,0 +1,28 @@
+//-----------------------------------------------------------------------
+// <copyright file="LocalizationTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test {
+ using System;
+ using System.Globalization;
+ using System.Threading;
+ using DotNetOpenAuth.Messaging;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ /// <summary>
+ /// Tests various localized resources work as expected.
+ /// </summary>
+ [TestClass]
+ public class LocalizationTests {
+ /// <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.")]
+ public void Serbian() {
+ Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("sr");
+ ErrorUtilities.VerifyHttpContext();
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
index 4cdaa39..05ac306 100644
--- a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs
@@ -30,6 +30,50 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreEqual(request.HttpMethod, info.HttpMethod);
}
+ // All these tests are ineffective because ServerVariables[] cannot be set.
+ ////[TestMethod]
+ ////public void CtorRequestWithDifferentPublicHttpHost() {
+ //// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b");
+ //// request.ServerVariables["HTTP_HOST"] = "publichost";
+ //// HttpRequestInfo info = new HttpRequestInfo(request);
+ //// Assert.AreEqual("publichost", info.UrlBeforeRewriting.Host);
+ //// Assert.AreEqual(80, info.UrlBeforeRewriting.Port);
+ //// Assert.AreEqual(request.Url.Query, info.Query);
+ //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
+ ////}
+
+ ////[TestMethod]
+ ////public void CtorRequestWithDifferentPublicHttpsHost() {
+ //// HttpRequest request = new HttpRequest("file", "https://someserver?a=b", "a=b");
+ //// request.ServerVariables["HTTP_HOST"] = "publichost";
+ //// HttpRequestInfo info = new HttpRequestInfo(request);
+ //// Assert.AreEqual("publichost", info.UrlBeforeRewriting.Host);
+ //// Assert.AreEqual(443, info.UrlBeforeRewriting.Port);
+ //// Assert.AreEqual(request.Url.Query, info.Query);
+ //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
+ ////}
+
+ ////[TestMethod]
+ ////public void CtorRequestWithDifferentPublicHostNonstandardPort() {
+ //// HttpRequest request = new HttpRequest("file", "http://someserver?a=b", "a=b");
+ //// request.ServerVariables["HTTP_HOST"] = "publichost:550";
+ //// HttpRequestInfo info = new HttpRequestInfo(request);
+ //// Assert.AreEqual("publichost", info.UrlBeforeRewriting.Host);
+ //// Assert.AreEqual(550, info.UrlBeforeRewriting.Port);
+ //// Assert.AreEqual(request.Url.Query, info.Query);
+ //// Assert.AreEqual(request.QueryString["a"], info.QueryString["a"]);
+ ////}
+
+ ////[TestMethod]
+ ////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";
+ //// HttpRequestInfo info = new HttpRequestInfo(request);
+ //// Assert.AreEqual("[fe80::587e:c6e5:d3aa:657b]", info.UrlBeforeRewriting.Host);
+ //// Assert.AreEqual(8089, info.UrlBeforeRewriting.Port);
+ //// Assert.AreEqual(request.Url.Query, info.Query);
+ ////}
+
/// <summary>
/// Checks that a property dependent on another null property
/// doesn't generate a NullReferenceException.
diff --git a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
index 0215801..19e6a82 100644
--- a/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/Reflection/MessagePartTests.cs
@@ -82,7 +82,7 @@ namespace DotNetOpenAuth.Test.Messaging.Reflection {
Assert.AreEqual("abc", part.GetValue(message));
}
- [TestMethod, ExpectedException(typeof(ArgumentException))]
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
public void ConstantFieldMemberInvalidValues() {
var message = new MessageWithConstantField();
MessagePart part = GetMessagePart(message.GetType(), "ConstantField");
diff --git a/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs b/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
index 48547b7..35672d7 100644
--- a/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/InMemoryTokenManager.cs
@@ -106,6 +106,10 @@ namespace DotNetOpenAuth.Test.Mocks {
return this.tokens[token];
}
+ public void UpdateToken(IServiceProviderRequestToken token) {
+ // Nothing to do here, since we're using Linq To SQL.
+ }
+
#endregion
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
index 2788435..346dde9 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockIdentifier.cs
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth.Test.Mocks {
private Identifier wrappedIdentifier;
public MockIdentifier(Identifier wrappedIdentifier, MockHttpRequest mockHttpRequest, IEnumerable<ServiceEndpoint> endpoints)
- : base(false) {
+ : base(wrappedIdentifier.OriginalString, false) {
Contract.Requires<ArgumentNullException>(wrappedIdentifier != null);
Contract.Requires<ArgumentNullException>(mockHttpRequest != null);
Contract.Requires<ArgumentNullException>(endpoints != null);
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockRealm.cs b/src/DotNetOpenAuth.Test/Mocks/MockRealm.cs
new file mode 100644
index 0000000..4e29bba
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Mocks/MockRealm.cs
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------
+// <copyright file="MockRealm.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Mocks {
+ using System.Collections.Generic;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId;
+
+ internal class MockRealm : Realm {
+ private RelyingPartyEndpointDescription[] relyingPartyDescriptions;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MockRealm"/> class.
+ /// </summary>
+ /// <param name="wrappedRealm">The wrapped realm.</param>
+ /// <param name="relyingPartyDescriptions">The relying party descriptions.</param>
+ internal MockRealm(Realm wrappedRealm, params RelyingPartyEndpointDescription[] relyingPartyDescriptions)
+ : base(wrappedRealm) {
+ ErrorUtilities.VerifyArgumentNotNull(relyingPartyDescriptions, "relyingPartyDescriptions");
+
+ this.relyingPartyDescriptions = relyingPartyDescriptions;
+ }
+
+ /// <summary>
+ /// Searches for an XRDS document at the realm URL, and if found, searches
+ /// for a description of a relying party endpoints (OpenId login pages).
+ /// </summary>
+ /// <param name="requestHandler">The mechanism to use for sending HTTP requests.</param>
+ /// <param name="allowRedirects">Whether redirects may be followed when discovering the Realm.
+ /// This may be true when creating an unsolicited assertion, but must be
+ /// false when performing return URL verification per 2.0 spec section 9.2.1.</param>
+ /// <returns>
+ /// The details of the endpoints if found, otherwise null.
+ /// </returns>
+ internal override IEnumerable<RelyingPartyEndpointDescription> Discover(IDirectWebRequestHandler requestHandler, bool allowRedirects) {
+ return this.relyingPartyDescriptions;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
index 6bd2c00..3ab6559 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/SigningBindingElementTests.cs
@@ -36,7 +36,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
signedMessage.UtcCreationDate = DateTime.Parse("1/1/2009");
signedMessage.AssociationHandle = association.Handle;
Assert.IsNotNull(signer.ProcessOutgoingMessage(message));
- Assert.AreEqual("0wOdvNgzCZ5I5AzbU58Nq2Tg8EJZ7QoNz4gpx2r7jII=", signedMessage.Signature);
+ Assert.AreEqual("o9+uN7qTaUS9v0otbHTuNAtbkpBm14+es9QnNo6IHD4=", signedMessage.Signature);
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
index 59c818c..5034b7e 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
@@ -71,6 +71,14 @@ namespace DotNetOpenAuth.Test.OpenId {
this.MockResponder = MockHttpRequest.CreateUntrustedMockHttpHandler();
this.RequestHandler = this.MockResponder.MockWebRequestHandler;
this.AutoProviderScenario = Scenarios.AutoApproval;
+ Identifier.EqualityOnStrings = true;
+ }
+
+ [TestCleanup]
+ public override void Cleanup() {
+ base.Cleanup();
+
+ Identifier.EqualityOnStrings = false;
}
/// <summary>
@@ -168,6 +176,11 @@ namespace DotNetOpenAuth.Test.OpenId {
}
}
+ protected Realm GetMockRealm(bool useSsl) {
+ var rpDescription = new RelyingPartyEndpointDescription(useSsl ? RPUriSsl : RPUri, new string[] { Protocol.V20.RPReturnToTypeURI });
+ return new MockRealm(useSsl ? RPRealmUriSsl : RPRealmUri, rpDescription);
+ }
+
protected Identifier GetMockIdentifier(ProtocolVersion providerVersion) {
return this.GetMockIdentifier(providerVersion, false);
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
index 7c92389..8528aa7 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.Test.OpenId.Provider {
using System;
+ using System.IO;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
@@ -128,15 +129,19 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
[TestMethod]
public void BadRequestsGenerateValidErrorResponsesHosted() {
- using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
- Uri opEndpoint = new Uri(host.BaseUri, "/OpenIdProviderEndpoint.ashx");
- var rp = new OpenIdRelyingParty(null);
- var nonOpenIdMessage = new Mocks.TestDirectedMessage();
- nonOpenIdMessage.Recipient = opEndpoint;
- nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest;
- MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage);
- var response = rp.Channel.Request<DirectErrorResponse>(nonOpenIdMessage);
- Assert.IsNotNull(response.ErrorMessage);
+ try {
+ using (AspNetHost host = AspNetHost.CreateHost(TestWebDirectory)) {
+ Uri opEndpoint = new Uri(host.BaseUri, "/OpenIdProviderEndpoint.ashx");
+ var rp = new OpenIdRelyingParty(null);
+ var nonOpenIdMessage = new Mocks.TestDirectedMessage();
+ nonOpenIdMessage.Recipient = opEndpoint;
+ nonOpenIdMessage.HttpMethods = HttpDeliveryMethods.PostRequest;
+ MessagingTestBase.GetStandardTestMessage(MessagingTestBase.FieldFill.AllRequired, nonOpenIdMessage);
+ var response = rp.Channel.Request<DirectErrorResponse>(nonOpenIdMessage);
+ Assert.IsNotNull(response.ErrorMessage);
+ }
+ } catch (FileNotFoundException ex) {
+ Assert.Inconclusive("Unable to execute hosted ASP.NET tests because {0} could not be found. {1}", ex.FileName, ex.FusionLog);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
index 68bbff3..f6a57e7 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
@@ -63,6 +63,21 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.AreEqual(1, requests.Count());
}
+ [TestMethod]
+ public void CreateRequestsWithEndpointFilter() {
+ var rp = this.CreateRelyingParty();
+ StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
+ Identifier id = Identifier.Parse(GetMockIdentifier(ProtocolVersion.V20));
+
+ rp.EndpointFilter = opendpoint => true;
+ var requests = rp.CreateRequests(id, RPRealmUri, RPUri);
+ Assert.AreEqual(1, requests.Count());
+
+ rp.EndpointFilter = opendpoint => false;
+ requests = rp.CreateRequests(id, RPRealmUri, RPUri);
+ Assert.AreEqual(0, requests.Count());
+ }
+
[TestMethod, ExpectedException(typeof(ProtocolException))]
public void CreateRequestOnNonOpenID() {
Uri nonOpenId = new Uri("http://www.microsoft.com/");
@@ -79,5 +94,31 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
var requests = rp.CreateRequests(nonOpenId, RPRealmUri, RPUri);
Assert.AreEqual(0, requests.Count());
}
+
+ /// <summary>
+ /// Verifies that incoming positive assertions throw errors if they come from
+ /// OPs that are not approved by <see cref="OpenIdRelyingParty.EndpointFilter"/>.
+ /// </summary>
+ [TestMethod]
+ public void AssertionWithEndpointFilter() {
+ var coordinator = new OpenIdCoordinator(
+ rp => {
+ // register with RP so that id discovery passes
+ rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
+
+ // Rig it to always deny the incoming OP
+ rp.EndpointFilter = op => false;
+
+ // Receive the unsolicited assertion
+ var response = rp.GetResponse();
+ Assert.AreEqual(AuthenticationStatus.Failed, response.Status);
+ },
+ op => {
+ Identifier id = GetMockIdentifier(ProtocolVersion.V20);
+ op.SendUnsolicitedAssertion(OPUri, GetMockRealm(false), id, id);
+ AutoProvider(op);
+ });
+ coordinator.Run();
+ }
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
index 7701090..701bcae 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseTests.cs
@@ -38,7 +38,7 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.AreEqual(AuthenticationStatus.Authenticated, authResponse.Status);
Assert.IsNull(authResponse.Exception);
Assert.AreEqual<string>(assertion.ClaimedIdentifier, authResponse.ClaimedIdentifier);
- Assert.AreEqual<string>(authResponseAccessor.endpoint.FriendlyIdentifierForDisplay, authResponse.FriendlyIdentifierForDisplay);
+ Assert.AreEqual<string>(authResponse.Endpoint.FriendlyIdentifierForDisplay, authResponse.FriendlyIdentifierForDisplay);
Assert.AreSame(extension, authResponse.GetUntrustedExtension(typeof(ClaimsResponse)));
Assert.AreSame(extension, authResponse.GetUntrustedExtension<ClaimsResponse>());
Assert.IsNull(authResponse.GetCallbackArgument("a"));
@@ -59,6 +59,18 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
Assert.AreEqual(AuthenticationStatus.Failed, authResponse.Status);
}
+ /// <summary>
+ /// Verifies that the RP rejects positive assertions with HTTP Claimed
+ /// Cdentifiers when RequireSsl is set to true.
+ /// </summary>
+ [TestMethod, ExpectedException(typeof(ProtocolException))]
+ public void InsecureIdentifiersRejectedWithRequireSsl() {
+ PositiveAssertionResponse assertion = this.GetPositiveAssertion();
+ var rp = CreateRelyingParty();
+ rp.SecuritySettings.RequireSsl = true;
+ var authResponse = new PositiveAuthenticationResponse(assertion, rp);
+ }
+
[TestMethod]
public void GetCallbackArguments() {
PositiveAssertionResponse assertion = this.GetPositiveAssertion();
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 0a156c4..f96bf48 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -105,6 +105,9 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "OpenIdRelyingPartyClassicAs
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
diff --git a/src/DotNetOpenAuth.vsmdi b/src/DotNetOpenAuth.vsmdi
index 38e2e9a..1c00499 100644
--- a/src/DotNetOpenAuth.vsmdi
+++ b/src/DotNetOpenAuth.vsmdi
@@ -11,40 +11,36 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -54,90 +50,94 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -146,39 +146,42 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -188,17 +191,16 @@
<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="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="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="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="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="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="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="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="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" />
@@ -212,6 +214,7 @@
<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" />
@@ -227,15 +230,15 @@
<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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -246,45 +249,42 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="1da7c479-bf01-2d12-8645-b4f7007dcfec" name="LanguagePreferenceEncoding" 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="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="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="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="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" />
@@ -299,36 +299,38 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -337,94 +339,92 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
+ <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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -432,43 +432,47 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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" />
@@ -478,28 +482,28 @@
<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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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">
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
new file mode 100644
index 0000000..ea32f4c
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified">
+ <xs:element name="dotNetOpenAuth">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="messaging">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="untrustedWebRequest">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="whitelistHosts">
+ <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="whitelistHostsRegex">
+ <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="blacklistHosts">
+ <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="blacklistHostsRegex">
+ <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:choice>
+ <xs:attribute name="timeout" type="xs:string" />
+ <xs:attribute name="readWriteTimeout" type="xs:string" />
+ <xs:attribute name="maximumBytesToRead" type="xs:int" />
+ <xs:attribute name="maximumRedirections" type="xs:int" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="lifetime" type="xs:string" />
+ <xs:attribute name="clockSkew" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="openid">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="relyingParty">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="security">
+ <xs:complexType>
+ <xs:attribute name="requireSsl" type="xs:boolean" default="false" />
+ <xs:attribute name="minimumRequiredOpenIdVersion">
+ <xs:simpleType>
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="V10" />
+ <xs:enumeration value="V11" />
+ <xs:enumeration value="V20" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="minimumHashBitLength" type="xs:int" />
+ <xs:attribute name="maximumHashBitLength" type="xs:int" />
+ <xs:attribute name="privateSecretMaximumAge" type="xs:string" />
+ <xs:attribute name="requireDirectedIdentity" type="xs:boolean" />
+ <xs:attribute name="requireAssociation" type="xs:boolean" />
+ <xs:attribute name="rejectUnsolicitedAssertions" type="xs:boolean" />
+ <xs:attribute name="rejectDelegatingIdentifiers" type="xs:boolean" />
+ <xs:attribute name="ignoreUnsignedExtensions" type="xs:boolean" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="behaviors">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="optional" />
+ <xs:attribute name="xaml" type="xs:string" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="type" 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:complexType>
+ <xs:attribute name="type" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="provider">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="security">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="associations">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ <xs:attribute name="lifetime" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="type" 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:choice>
+ <xs:attribute name="requireSsl" type="xs:boolean" default="false" />
+ <xs:attribute name="protectDownlevelReplayAttacks" type="xs:boolean" />
+ <xs:attribute name="minimumHashBitLength" type="xs:int" />
+ <xs:attribute name="maximumHashBitLength" type="xs:int" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="behaviors">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="optional" />
+ <xs:attribute name="xaml" type="xs:string" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="type" 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:complexType>
+ <xs:attribute name="type" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extensionFactories">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="optional" />
+ <xs:attribute name="xaml" type="xs:string" use="optional" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="type" 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="xriResolver">
+ <xs:complexType>
+ <xs:attribute name="enabled" type="xs:boolean" />
+ <xs:attribute name="proxy" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="maxAuthenticationTime" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/src/DotNetOpenAuth/Configuration/OAuthConsumerSecuritySettingsElement.cs b/src/DotNetOpenAuth/Configuration/OAuthConsumerSecuritySettingsElement.cs
index 5e75390..38a183a 100644
--- a/src/DotNetOpenAuth/Configuration/OAuthConsumerSecuritySettingsElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OAuthConsumerSecuritySettingsElement.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.Configuration {
using System;
using System.Collections.Generic;
using System.Configuration;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using DotNetOpenAuth.OAuth;
@@ -26,6 +27,7 @@ namespace DotNetOpenAuth.Configuration {
/// 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>
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "By design")]
internal ConsumerSecuritySettings CreateSecuritySettings() {
return new ConsumerSecuritySettings();
}
diff --git a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
index b19ecc6..3ba0eb1 100644
--- a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
+++ b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
@@ -106,11 +106,27 @@ namespace DotNetOpenAuth.Configuration {
source = HttpContext.Current.Server.MapPath(source);
}
using (Stream xamlFile = File.OpenRead(source)) {
- return (T)XamlReader.Load(xamlFile);
+ return this.CreateInstanceFromXaml(xamlFile);
}
} else {
return defaultValue;
}
}
+
+ /// <summary>
+ /// Creates the instance from xaml.
+ /// </summary>
+ /// <param name="xaml">The stream of xaml to deserialize.</param>
+ /// <returns>The deserialized object.</returns>
+ /// <remarks>
+ /// This exists as its own method to prevent the CLR's JIT compiler from failing
+ /// to compile the CreateInstance method just because the PresentationFramework.dll
+ /// may be missing (which it is on some shared web hosts). This way, if the
+ /// XamlSource attribute is never used, the PresentationFramework.dll never need
+ /// be present.
+ /// </remarks>
+ private T CreateInstanceFromXaml(Stream xaml) {
+ return (T)XamlReader.Load(xaml);
+ }
}
}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index ce660e5..0374eab 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -93,7 +93,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\bin\CodeAnalysis\</OutputPath>
- <DefineConstants>CONTRACTS_FULL;DEBUG;TRACE</DefineConstants>
+ <DefineConstants>$(DefineConstants);CONTRACTS_FULL;DEBUG;TRACE</DefineConstants>
<DocumentationFile>..\..\bin\CodeAnalysis\DotNetOpenAuth.xml</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -151,9 +151,15 @@
<Reference Include="System.IdentityModel.Selectors">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.Runtime.Serialization">
+ <RequiredTargetFramework>3.0</RequiredTargetFramework>
+ </Reference>
<Reference Include="System.ServiceModel">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
+ <Reference Include="System.ServiceModel.Web">
+ <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>
@@ -394,6 +400,7 @@
<Compile Include="OpenId\Extensions\SimpleRegistration\Constants.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\DemandLevel.cs" />
<Compile Include="OpenId\Extensions\SimpleRegistration\Gender.cs" />
+ <Compile Include="OpenId\Extensions\UI\UIConstants.cs" />
<Compile Include="OpenId\Extensions\UI\UIUtilities.cs" />
<Compile Include="OpenId\Extensions\UI\UIModes.cs" />
<Compile Include="OpenId\Extensions\UI\UIRequest.cs" />
@@ -501,11 +508,12 @@
<Compile Include="OpenId\ProviderEndpointDescription.cs" />
<Compile Include="OpenId\Provider\ProviderSecuritySettings.cs" />
<Compile Include="OpenId\RelyingParty\IRelyingPartyApplicationStore.cs" />
- <Compile Include="OpenId\RelyingParty\AuthenticationResponseSnapshot.cs" />
+ <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseSnapshot.cs" />
<Compile Include="OpenId\RelyingParty\PrivateSecretManager.cs" />
<Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettings.cs" />
<Compile Include="OpenId\RelyingParty\ServiceEndpoint.cs" />
<Compile Include="OpenId\OpenIdXrdsHelper.cs" />
+ <Compile Include="OpenId\RelyingParty\SimpleXrdsProviderEndpoint.cs" />
<Compile Include="OpenId\RelyingParty\StandardRelyingPartyApplicationStore.cs" />
<Compile Include="OpenId\RelyingParty\WellKnownProviders.cs" />
<Compile Include="OpenId\SecuritySettings.cs" />
@@ -544,11 +552,14 @@
<Compile Include="Yadis\Yadis.cs" />
</ItemGroup>
<ItemGroup>
+ <None Include="Configuration\DotNetOpenAuth.xsd" />
<None Include="OAuth\ClassDiagram.cd" />
<None Include="OAuth\Messages\OAuth Messages.cd" />
<None Include="Messaging\Bindings\Bindings.cd" />
<None Include="Messaging\Exceptions.cd" />
<None Include="Messaging\Messaging.cd" />
+ <None Include="OpenId\RelyingParty\Controls.cd" />
+ <None Include="OpenId\RelyingParty\OpenIdRelyingParty.cd" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Messaging\MessagingStrings.resx">
@@ -607,12 +618,19 @@
<EmbeddedResource Include="OpenId\RelyingParty\OpenIdRelyingPartyControlBase.js" />
</ItemGroup>
<ItemGroup>
+ <EmbeddedResource Include="InfoCard\InfoCardStrings.sr.resx" />
+ <EmbeddedResource Include="Messaging\MessagingStrings.sr.resx" />
+ <EmbeddedResource Include="OAuth\OAuthStrings.sr.resx" />
<EmbeddedResource Include="OpenId\Behaviors\BehaviorStrings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>BehaviorStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
+ <EmbeddedResource Include="OpenId\Behaviors\BehaviorStrings.sr.resx" />
+ <EmbeddedResource Include="OpenId\OpenIdStrings.sr.resx" />
<EmbeddedResource Include="OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.js" />
+ <EmbeddedResource Include="Strings.sr.resx" />
+ <EmbeddedResource Include="Xrds\XrdsStrings.sr.resx" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index 8be62f8..07fabc3 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -43,3 +43,4 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.OAuth")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.UI")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Reflection")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "oauthverifier", Scope = "resource", Target = "DotNetOpenAuth.OAuth.OAuthStrings.resources")]
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
index 9deca06..f367baa 100644
--- a/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
+++ b/src/DotNetOpenAuth/InfoCard/InfoCardSelector.cs
@@ -16,6 +16,8 @@ namespace DotNetOpenAuth.InfoCard {
using System.Drawing.Design;
using System.Globalization;
using System.Linq;
+ using System.Text.RegularExpressions;
+ using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
@@ -256,8 +258,27 @@ namespace DotNetOpenAuth.InfoCard {
[Description("The URL to this site's privacy policy.")]
[Category(InfoCardCategory), DefaultValue(PrivacyUrlDefault)]
public string PrivacyUrl {
- get { return (string)this.ViewState[PrivacyUrlViewStateKey] ?? PrivacyUrlDefault; }
- set { this.ViewState[PrivacyUrlViewStateKey] = value; }
+ get {
+ return (string)this.ViewState[PrivacyUrlViewStateKey] ?? PrivacyUrlDefault;
+ }
+
+ set {
+ if (this.Page != null && !this.DesignMode) {
+ // Validate new value by trying to construct a Uri based on it.
+ new Uri(new HttpRequestInfo(HttpContext.Current.Request).UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure.
+ } else {
+ // We can't fully test it, but it should start with either ~/ or a protocol.
+ if (Regex.IsMatch(value, @"^https?://")) {
+ new Uri(value); // make sure it's fully-qualified, but ignore wildcards
+ } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
+ // this is valid too
+ } else {
+ throw new UriFormatException();
+ }
+ }
+
+ this.ViewState[PrivacyUrlViewStateKey] = value;
+ }
}
/// <summary>
@@ -480,6 +501,20 @@ namespace DotNetOpenAuth.InfoCard {
}
/// <summary>
+ /// Raises the <see cref="E:System.Web.UI.Control.PreRender"/> event.
+ /// </summary>
+ /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
+ protected override void OnPreRender(EventArgs e) {
+ base.OnPreRender(e);
+
+ if (!this.DesignMode) {
+ // The Cardspace selector will display an ugly error to the user if
+ // the privacy URL is present but the privacy version is not.
+ ErrorUtilities.VerifyOperation(string.IsNullOrEmpty(this.PrivacyUrl) || !string.IsNullOrEmpty(this.PrivacyVersion), InfoCardStrings.PrivacyVersionRequiredWithPrivacyUrl);
+ }
+ }
+
+ /// <summary>
/// Creates a control that renders to &lt;Param Name="{0}" Value="{1}" /&gt;
/// </summary>
/// <param name="name">The parameter name.</param>
@@ -609,7 +644,8 @@ namespace DotNetOpenAuth.InfoCard {
}
if (!string.IsNullOrEmpty(this.PrivacyUrl)) {
- cardSpaceControl.Controls.Add(CreateParam("privacyUrl", this.PrivacyUrl));
+ string privacyUrl = this.DesignMode ? this.PrivacyUrl : new Uri(Page.Request.Url, Page.ResolveUrl(this.PrivacyUrl)).AbsoluteUri;
+ cardSpaceControl.Controls.Add(CreateParam("privacyUrl", privacyUrl));
}
if (!string.IsNullOrEmpty(this.PrivacyVersion)) {
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.Designer.cs
index 4b1dc60..00eb1af 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.3521
+// Runtime Version:2.0.50727.4918
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -97,6 +97,15 @@ namespace DotNetOpenAuth.InfoCard {
}
/// <summary>
+ /// Looks up a localized string similar to The PrivacyVersion property must be set whenever the PrivacyUrl property is set..
+ /// </summary>
+ internal static string PrivacyVersionRequiredWithPrivacyUrl {
+ get {
+ return ResourceManager.GetString("PrivacyVersionRequiredWithPrivacyUrl", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Click here to select your Information Card..
/// </summary>
internal static string SelectorClickPrompt {
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.resx b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.resx
index e82e8cd..956b321 100644
--- a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.resx
+++ b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.resx
@@ -129,6 +129,9 @@
<data name="PpidClaimRequired" xml:space="preserve">
<value>This operation requires the PPID claim to be included in the InfoCard token.</value>
</data>
+ <data name="PrivacyVersionRequiredWithPrivacyUrl" xml:space="preserve">
+ <value>The PrivacyVersion property must be set whenever the PrivacyUrl property is set.</value>
+ </data>
<data name="SelectorClickPrompt" xml:space="preserve">
<value>Click here to select your Information Card.</value>
</data>
diff --git a/src/DotNetOpenAuth/InfoCard/InfoCardStrings.sr.resx b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.sr.resx
new file mode 100644
index 0000000..9df0429
--- /dev/null
+++ b/src/DotNetOpenAuth/InfoCard/InfoCardStrings.sr.resx
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="AudienceMismatch" xml:space="preserve">
+ <value>Token je neispravan: restrikcije u prijemu se ne slažu sa Relying Party.</value>
+ </data>
+ <data name="EmptyClaimListNotAllowed" xml:space="preserve">
+ <value>Tražena lista zahteva za uključivanje u InfoCard ne sme biti prazna.</value>
+ </data>
+ <data name="EncryptionAlgorithmNotFound" xml:space="preserve">
+ <value>encryptionAlgorithm nije pronađen.</value>
+ </data>
+ <data name="PpidClaimRequired" xml:space="preserve">
+ <value>Ova operacija zahteva da PPID zahtev bude uključen u InfoCard token.</value>
+ </data>
+ <data name="SelectorClickPrompt" xml:space="preserve">
+ <value>Kliknite ovde da odaberete vaš Information Card.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Loggers/Log4NetLogger.cs b/src/DotNetOpenAuth/Loggers/Log4NetLogger.cs
index 30d93ae..dd71a05 100644
--- a/src/DotNetOpenAuth/Loggers/Log4NetLogger.cs
+++ b/src/DotNetOpenAuth/Loggers/Log4NetLogger.cs
@@ -197,7 +197,11 @@ namespace DotNetOpenAuth.Loggers {
/// </summary>
/// <returns>The created <see cref="ILog"/> instance.</returns>
internal static ILog Initialize(string name) {
- return IsLog4NetPresent ? CreateLogger(name) : null;
+ try {
+ return IsLog4NetPresent ? CreateLogger(name) : null;
+ } catch (FileLoadException) { // wrong log4net.dll version
+ return null;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/Bindings/NonceMemoryStore.cs b/src/DotNetOpenAuth/Messaging/Bindings/NonceMemoryStore.cs
index 1d4d28e..3d624a6 100644
--- a/src/DotNetOpenAuth/Messaging/Bindings/NonceMemoryStore.cs
+++ b/src/DotNetOpenAuth/Messaging/Bindings/NonceMemoryStore.cs
@@ -73,7 +73,7 @@ namespace DotNetOpenAuth.Messaging.Bindings {
/// <see cref="StandardExpirationBindingElement.MaximumMessageAge"/> property.
/// </remarks>
public bool StoreNonce(string context, string nonce, DateTime timestamp) {
- if (timestamp.ToUniversalTime() + this.maximumMessageAge < DateTime.UtcNow) {
+ if (timestamp.ToUniversalTimeSafe() + this.maximumMessageAge < DateTime.UtcNow) {
// The expiration binding element should have taken care of this, but perhaps
// it's at the boundary case. We should fail just to be safe.
return false;
@@ -115,7 +115,7 @@ namespace DotNetOpenAuth.Messaging.Bindings {
/// </summary>
public void ClearExpiredNonces() {
lock (this.nonceLock) {
- var oldNonceLists = this.usedNonces.Keys.Where(time => time.ToUniversalTime() + this.maximumMessageAge < DateTime.UtcNow).ToList();
+ var oldNonceLists = this.usedNonces.Keys.Where(time => time.ToUniversalTimeSafe() + this.maximumMessageAge < DateTime.UtcNow).ToList();
foreach (DateTime time in oldNonceLists) {
this.usedNonces.Remove(time);
}
diff --git a/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs b/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs
index 5fcf4bd..7b00e34 100644
--- a/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs
+++ b/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs
@@ -87,7 +87,7 @@ namespace DotNetOpenAuth.Messaging.Bindings {
if (expiringMessage != null) {
// Yes the UtcCreationDate is supposed to always be in UTC already,
// but just in case a given message failed to guarantee that, we do it here.
- DateTime expirationDate = expiringMessage.UtcCreationDate.ToUniversalTime() + MaximumMessageAge;
+ DateTime expirationDate = expiringMessage.UtcCreationDate.ToUniversalTimeSafe() + MaximumMessageAge;
if (expirationDate < DateTime.UtcNow) {
throw new ExpiredMessageException(expirationDate, expiringMessage);
}
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index df56b31..8510aa4 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -67,7 +67,9 @@ namespace DotNetOpenAuth.Messaging {
/// </remarks>
private const string IndirectMessageFormPostFormat = @"
<html>
-<body onload=""var btn = document.getElementById('submit_button'); btn.disabled = true; btn.value = 'Login in progress'; document.getElementById('openid_message').submit()"">
+<head>
+</head>
+<body onload=""document.body.style.display = 'none'; var btn = document.getElementById('submit_button'); btn.disabled = true; btn.value = 'Login in progress'; document.getElementById('openid_message').submit()"">
<form id=""openid_message"" action=""{0}"" method=""post"" accept-charset=""UTF-8"" enctype=""application/x-www-form-urlencoded"" onSubmit=""var btn = document.getElementById('submit_button'); btn.disabled = true; btn.value = 'Login in progress'; return true;"">
{1}
<input id=""submit_button"" type=""submit"" value=""Continue"" />
@@ -677,6 +679,7 @@ namespace DotNetOpenAuth.Messaging {
Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
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) {
@@ -842,6 +845,42 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Prepares to send a request to the Service Provider as the query string in a PUT request.
+ /// </summary>
+ /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
+ /// <returns>The web request ready to send.</returns>
+ /// <remarks>
+ /// This method is simply a standard HTTP PUT request with the message parts serialized to the query string.
+ /// </remarks>
+ protected virtual HttpWebRequest InitializeRequestAsPut(IDirectedProtocolMessage requestMessage) {
+ Contract.Requires(requestMessage != null);
+ Contract.Ensures(Contract.Result<HttpWebRequest>() != null);
+ ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");
+
+ HttpWebRequest request = this.InitializeRequestAsGet(requestMessage);
+ request.Method = "PUT";
+ return request;
+ }
+
+ /// <summary>
+ /// Prepares to send a request to the Service Provider as the query string in a DELETE request.
+ /// </summary>
+ /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
+ /// <returns>The web request ready to send.</returns>
+ /// <remarks>
+ /// This method is simply a standard HTTP DELETE request with the message parts serialized to the query string.
+ /// </remarks>
+ protected virtual HttpWebRequest InitializeRequestAsDelete(IDirectedProtocolMessage requestMessage) {
+ Contract.Requires(requestMessage != null);
+ Contract.Ensures(Contract.Result<HttpWebRequest>() != null);
+ ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage");
+
+ HttpWebRequest request = this.InitializeRequestAsGet(requestMessage);
+ request.Method = "DELETE";
+ return request;
+ }
+
+ /// <summary>
/// Sends the given parameters in the entity stream of an HTTP request.
/// </summary>
/// <param name="httpRequest">The HTTP request.</param>
diff --git a/src/DotNetOpenAuth/Messaging/HostErrorException.cs b/src/DotNetOpenAuth/Messaging/HostErrorException.cs
index 0ab9e51..81691b0 100644
--- a/src/DotNetOpenAuth/Messaging/HostErrorException.cs
+++ b/src/DotNetOpenAuth/Messaging/HostErrorException.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.Messaging {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
@@ -20,6 +21,7 @@ namespace DotNetOpenAuth.Messaging {
/// or its configuration.</para>
/// <para>It is an internal exception to assist in making it uncatchable.</para>
/// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic", Justification = "We don't want this exception to be catchable.")]
[Serializable]
internal class HostErrorException : Exception {
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs b/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
index cbbe28e..17c8f7a 100644
--- a/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
+++ b/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
@@ -34,5 +34,20 @@ namespace DotNetOpenAuth.Messaging {
/// Added to the URLs in the query part (as defined by [RFC3986] (Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .) section 3).
/// </summary>
GetRequest = 0x4,
+
+ /// <summary>
+ /// Added to the URLs in the query part (as defined by [RFC3986] (Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .) section 3).
+ /// </summary>
+ PutRequest = 0x8,
+
+ /// <summary>
+ /// Added to the URLs in the query part (as defined by [RFC3986] (Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .) section 3).
+ /// </summary>
+ DeleteRequest = 0x10,
+
+ /// <summary>
+ /// The flags that control HTTP verbs.
+ /// </summary>
+ HttpVerbMask = PostRequest | GetRequest | PutRequest | DeleteRequest,
}
}
diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
index 34f55e9..c2a39d0 100644
--- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
+++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
@@ -166,11 +166,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="httpMethod">The HTTP method that the incoming request came in on, whether or not <paramref name="message"/> is null.</param>
internal HttpRequestInfo(IDirectedProtocolMessage message, HttpDeliveryMethods httpMethod) {
this.message = message;
- if ((httpMethod & HttpDeliveryMethods.GetRequest) != 0) {
- this.HttpMethod = "GET";
- } else if ((httpMethod & HttpDeliveryMethods.PostRequest) != 0) {
- this.HttpMethod = "POST";
- }
+ this.HttpMethod = MessagingUtilities.GetHttpVerb(httpMethod);
}
/// <summary>
@@ -338,12 +334,11 @@ namespace DotNetOpenAuth.Messaging {
if (request.ServerVariables["HTTP_HOST"] != null) {
ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols.");
UriBuilder publicRequestUri = new UriBuilder(request.Url);
- string[] hostAndPort = request.ServerVariables["HTTP_HOST"].Split(new[] { ':' }, 2);
- publicRequestUri.Host = hostAndPort[0];
- if (hostAndPort.Length > 1) {
- publicRequestUri.Port = Convert.ToInt32(hostAndPort[1], CultureInfo.InvariantCulture);
- } else {
- publicRequestUri.Port = publicRequestUri.Scheme == Uri.UriSchemeHttps ? 443 : 80;
+ Uri hostAndPort = new Uri(request.Url.Scheme + Uri.SchemeDelimiter + request.ServerVariables["HTTP_HOST"]);
+ publicRequestUri.Host = hostAndPort.Host;
+ publicRequestUri.Port = hostAndPort.Port;
+ if (request.ServerVariables["HTTP_X_FORWARDED_PROTO"] != null) {
+ publicRequestUri.Scheme = request.ServerVariables["HTTP_X_FORWARDED_PROTO"];
}
return publicRequestUri.Uri;
} else {
diff --git a/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs b/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
index ddf3664..c7ac581 100644
--- a/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
+++ b/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
@@ -13,6 +13,7 @@ namespace DotNetOpenAuth.Messaging {
/// An immutable description of a URL that receives messages.
/// </summary>
[DebuggerDisplay("{AllowedMethods} {Location}")]
+ [Serializable]
public class MessageReceivingEndpoint {
/// <summary>
/// Initializes a new instance of the <see cref="MessageReceivingEndpoint"/> class.
@@ -30,7 +31,7 @@ namespace DotNetOpenAuth.Messaging {
public MessageReceivingEndpoint(Uri location, HttpDeliveryMethods method) {
Contract.Requires<ArgumentNullException>(location != null);
Contract.Requires<ArgumentOutOfRangeException>(method != HttpDeliveryMethods.None, "method");
- Contract.Requires<ArgumentOutOfRangeException>((method & (HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.GetRequest)) != 0, MessagingStrings.GetOrPostFlagsRequired);
+ Contract.Requires<ArgumentOutOfRangeException>((method & HttpDeliveryMethods.HttpVerbMask) != 0, MessagingStrings.GetOrPostFlagsRequired);
this.Location = location;
this.AllowedMethods = method;
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.sr.resx b/src/DotNetOpenAuth/Messaging/MessagingStrings.sr.resx
new file mode 100644
index 0000000..5b7b716
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.sr.resx
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ArgumentPropertyMissing" xml:space="preserve">
+ <value>Svojstvo {0}.{1} argumenta je neophodno, ali je ono prazno ili nepostojeće.</value>
+ </data>
+ <data name="CurrentHttpContextRequired" xml:space="preserve">
+ <value>HttpContext.Current je nepostojeći. Mora postojati ASP.NET zahtev u procesu da bi ova operacija bila uspešna.</value>
+ </data>
+ <data name="DataContractMissingFromMessageType" xml:space="preserve">
+ <value>DataContractSerializer se ne može inicijalizovati na tipu poruke {0}. Da li nedostaje [DataContract] atribut?</value>
+ </data>
+ <data name="DataContractMissingNamespace" xml:space="preserve">
+ <value>DataContractSerializer se ne može inicijalizovati na tipu poruke {0} jer svojstvo DataContractAttribute.Namespace property nije podešeno.</value>
+ </data>
+ <data name="DerivedTypeNotExpected" xml:space="preserve">
+ <value>Instanca tipa {0} je bila očekivana, a primljena je neočekivana izvedena instanca tipa {1}.</value>
+ </data>
+ <data name="DirectedMessageMissingRecipient" xml:space="preserve">
+ <value>Svojstvo Recipient usmerene poruke ne sme biti nepostojeće.</value>
+ </data>
+ <data name="DirectWebRequestOptionsNotSupported" xml:space="preserve">
+ <value>Dati set opcija ({0}) nije podržan od strane {1}.</value>
+ </data>
+ <data name="ErrorDeserializingMessage" xml:space="preserve">
+ <value>Greška prilikom deserijalizacije poruke {0}.</value>
+ </data>
+ <data name="ErrorInRequestReplyMessage" xml:space="preserve">
+ <value>Greška se desila tokom slanja usmerene poruke ili tokom primanja odgovora.</value>
+ </data>
+ <data name="ExceptionNotConstructedForTransit" xml:space="preserve">
+ <value>Ovaj izuzetak nije napravljen sa početnom porukom koja ga je izazvala.</value>
+ </data>
+ <data name="ExpectedMessageNotReceived" xml:space="preserve">
+ <value>Očekivana je poruka {0} a primljena poruka nije prepoznata.</value>
+ </data>
+ <data name="ExpiredMessage" xml:space="preserve">
+ <value>Poruka ističe u {0} a sada je {1}.</value>
+ </data>
+ <data name="GetOrPostFlagsRequired" xml:space="preserve">
+ <value>Bar jedan od GET ili POST flegova mora biti prisutan.</value>
+ </data>
+ <data name="HttpContextRequired" xml:space="preserve">
+ <value>Ovaj metod zahteva tekući HttpContext. Kao alternativa, koristite preklopljeni metod koji dozvoljava da se prosledi informacija bez HttpContext-a.</value>
+ </data>
+ <data name="IndirectMessagesMustImplementIDirectedProtocolMessage" xml:space="preserve">
+ <value>Poruke koje ukazuju na indirektni transport moraju implementirati {0} interfejs.</value>
+ </data>
+ <data name="InsecureWebRequestWithSslRequired" xml:space="preserve">
+ <value>Nebezbedan web zahtev za '{0}' prekinut zbog bezbednosnih zahteva koji zahtevaju HTTPS.</value>
+ </data>
+ <data name="InsufficientMessageProtection" xml:space="preserve">
+ <value>Poruka {0} je zahtevala zaštite {{{1}}} ali prenosni kanal nije mogao primeniti {{{2}}}.</value>
+ </data>
+ <data name="InvalidCustomBindingElementOrder" xml:space="preserve">
+ <value>Redosled prilagođenih vezujućih elemenata je neispravan.</value>
+ </data>
+ <data name="InvalidMessageParts" xml:space="preserve">
+ <value>Neki deo ili delovi poruke imaju nevalidne vrednosti: {0}</value>
+ </data>
+ <data name="InvalidNonceReceived" xml:space="preserve">
+ <value>Primljena poruka imala je neispravan ili nedostajući jedinstveni identifikator.</value>
+ </data>
+ <data name="KeyAlreadyExists" xml:space="preserve">
+ <value>Element sa istom vrednošću ključa je već dodat.</value>
+ </data>
+ <data name="MessageNotExtensible" xml:space="preserve">
+ <value>Poruka {0} ne podržava ekstenzije.</value>
+ </data>
+ <data name="MessagePartEncoderWrongType" xml:space="preserve">
+ <value>Vrednost za {0}.{1} člana {1} je trebala da bude izvedena od {2} ali je izvedena od {3}.</value>
+ </data>
+ <data name="MessagePartReadFailure" xml:space="preserve">
+ <value>Greška prilikom čitanja poruke '{0}' parametar '{1}' sa vrednošću '{2}'.</value>
+ </data>
+ <data name="MessagePartValueBase64DecodingFault" xml:space="preserve">
+ <value>Parametar poruke '{0}' sa vrednošću '{1}' nije se base64-dekodovao.</value>
+ </data>
+ <data name="MessagePartWriteFailure" xml:space="preserve">
+ <value>Greška prilikom pripremanja poruke '{0}' parametra '{1}' za slanje.</value>
+ </data>
+ <data name="QueuedMessageResponseAlreadyExists" xml:space="preserve">
+ <value>Poruka-odgovor je već u redu za slanje u stream-u za odgovore.</value>
+ </data>
+ <data name="ReplayAttackDetected" xml:space="preserve">
+ <value>Ova poruka je već obrađena. Ovo može ukazivati na replay napad u toku.</value>
+ </data>
+ <data name="ReplayProtectionNotSupported" xml:space="preserve">
+ <value>Ovaj kanal ne podržava replay zaštitu.</value>
+ </data>
+ <data name="RequiredNonEmptyParameterWasEmpty" xml:space="preserve">
+ <value>Sledeći zahtevani parametri koji ne smeju biti prazni su bili prazni u {0} poruke: {1}</value>
+ </data>
+ <data name="RequiredParametersMissing" xml:space="preserve">
+ <value>Sledeći zahtevani parametri nedostaju u {0} poruke: {1}</value>
+ </data>
+ <data name="RequiredProtectionMissing" xml:space="preserve">
+ <value>Povezujući element koji nudi {0} zaštitu zahteva drugu zaštitu koja nije ponuđena.</value>
+ </data>
+ <data name="SequenceContainsNoElements" xml:space="preserve">
+ <value>Lista je prazna.</value>
+ </data>
+ <data name="SequenceContainsNullElement" xml:space="preserve">
+ <value>Lista sadrži prazan (null) element.</value>
+ </data>
+ <data name="SignatureInvalid" xml:space="preserve">
+ <value>Potpis poruke je neispravan.</value>
+ </data>
+ <data name="SigningNotSupported" xml:space="preserve">
+ <value>Ovaj kanal ne podržava potpisivanje poruka. Da bi podržao potpisivanje poruka, izvedeni tip Channel mora preklopiti Sign i IsSignatureValid metode.</value>
+ </data>
+ <data name="StreamUnreadable" xml:space="preserve">
+ <value>Svojstvo stream-a CanRead je vratilo false.</value>
+ </data>
+ <data name="StreamUnwritable" xml:space="preserve">
+ <value>Svojstvo stream-a CanWrite je vratilo false.</value>
+ </data>
+ <data name="TooManyBindingsOfferingSameProtection" xml:space="preserve">
+ <value>Očekivano je da najviše 1 povezujući element primeni zaštitu {0}, ali je više njih primenjeno.</value>
+ </data>
+ <data name="TooManyRedirects" xml:space="preserve">
+ <value>Maksimalno dozvoljeni broj redirekcija je prekoračen u toku zahtevanja '{0}'.</value>
+ </data>
+ <data name="UnexpectedEmptyArray" xml:space="preserve">
+ <value>Niz ne sme biti prazan.</value>
+ </data>
+ <data name="UnexpectedEmptyString" xml:space="preserve">
+ <value>Prazan string nije dozvoljen.</value>
+ </data>
+ <data name="UnexpectedMessagePartValue" xml:space="preserve">
+ <value>Parametar poruke '{0}' ima neočekivanu '{1}'.</value>
+ </data>
+ <data name="UnexpectedMessagePartValueForConstant" xml:space="preserve">
+ <value>Očekivano je da od poruke {0} parametar '{1}' ima vrednost '{2}' ali je imao vrednost '{3}'.</value>
+ </data>
+ <data name="UnexpectedMessageReceived" xml:space="preserve">
+ <value>Očekivana je poruka {0} ali je umesto nje primljena {1}.</value>
+ </data>
+ <data name="UnexpectedMessageReceivedOfMany" xml:space="preserve">
+ <value>Poruka neočekivanog tipa je primljena.</value>
+ </data>
+ <data name="UnexpectedNullKey" xml:space="preserve">
+ <value>null ključ je uključen a nije dozvoljen.</value>
+ </data>
+ <data name="UnexpectedNullOrEmptyKey" xml:space="preserve">
+ <value>null ili prazan ključ je uključen a nije dozvoljen.</value>
+ </data>
+ <data name="UnexpectedNullValue" xml:space="preserve">
+ <value>null vrednost je uključena za ključ '{0}' a nije dozvoljena.</value>
+ </data>
+ <data name="UnexpectedType" xml:space="preserve">
+ <value>Tip {0} ili izvedeni tip je očekivan, a dat je {1}.</value>
+ </data>
+ <data name="UnrecognizedEnumValue" xml:space="preserve">
+ <value>{0} svojstvo ima nepoznatu vrednost {1}.</value>
+ </data>
+ <data name="UnsafeWebRequestDetected" xml:space="preserve">
+ <value>URL '{0}' je rangiran kao nebezbedan i ne može se zahtevati na ovaj način.</value>
+ </data>
+ <data name="UntrustedRedirectsOnPOSTNotSupported" xml:space="preserve">
+ <value>Redirekcije na POST zahteve usmerene ka serverima kojima se ne veruje nisu podržane.</value>
+ </data>
+ <data name="WebRequestFailed" xml:space="preserve">
+ <value>Web zahtev za '{0}' nije uspeo.</value>
+ </data>
+ <data name="ExceptionUndeliverable" xml:space="preserve">
+ <value>Ovaj izuzetak mora se kreirati zajedno sa primaocem koji će primiti poruku o grešci ili sa instancom poruke direktnog zahteva na koju će ovaj izuzetak odgovoriti.</value>
+ </data>
+ <data name="UnsupportedHttpVerbForMessageType" xml:space="preserve">
+ <value>'{0}' poruka ne može biti primljeno sa HTTP glagolom '{1}'.</value>
+ </data>
+ <data name="UnexpectedHttpStatusCode" xml:space="preserve">
+ <value>Očekivano je da direktan odgovor koristi HTTP status kod {0} a korišćen je {1}.</value>
+ </data>
+ <data name="UnsupportedHttpVerb" xml:space="preserve">
+ <value>HTTP glagol '{0}' je neprepoznat i nije podržan.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index df67a21..b0fb463 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -587,7 +587,47 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="request">The request to get recipient information from.</param>
/// <returns>The recipient.</returns>
internal static MessageReceivingEndpoint GetRecipient(this HttpRequestInfo request) {
- return new MessageReceivingEndpoint(request.UrlBeforeRewriting, request.HttpMethod == "GET" ? HttpDeliveryMethods.GetRequest : HttpDeliveryMethods.PostRequest);
+ return new MessageReceivingEndpoint(request.UrlBeforeRewriting, GetHttpDeliveryMethod(request.HttpMethod));
+ }
+
+ /// <summary>
+ /// Gets the <see cref="HttpDeliveryMethods"/> enum value for a given HTTP verb.
+ /// </summary>
+ /// <param name="httpVerb">The HTTP verb.</param>
+ /// <returns>A <see cref="HttpDeliveryMethods"/> enum value that is within the <see cref="HttpDeliveryMethods.HttpVerbMask"/>.</returns>
+ internal static HttpDeliveryMethods GetHttpDeliveryMethod(string httpVerb) {
+ if (httpVerb == "GET") {
+ return HttpDeliveryMethods.GetRequest;
+ } else if (httpVerb == "POST") {
+ return HttpDeliveryMethods.PostRequest;
+ } else if (httpVerb == "PUT") {
+ return HttpDeliveryMethods.PutRequest;
+ } else if (httpVerb == "DELETE") {
+ return HttpDeliveryMethods.DeleteRequest;
+ } else {
+ throw ErrorUtilities.ThrowArgumentNamed("httpVerb", MessagingStrings.UnsupportedHttpVerb, httpVerb);
+ }
+ }
+
+ /// <summary>
+ /// Gets the HTTP verb to use for a given <see cref="HttpDeliveryMethods"/> enum value.
+ /// </summary>
+ /// <param name="httpMethod">The HTTP method.</param>
+ /// <returns>An HTTP verb, such as GET, POST, PUT, or DELETE.</returns>
+ internal static string GetHttpVerb(HttpDeliveryMethods httpMethod) {
+ if ((httpMethod & HttpDeliveryMethods.GetRequest) != 0) {
+ return "GET";
+ } else if ((httpMethod & HttpDeliveryMethods.PostRequest) != 0) {
+ return "POST";
+ } else if ((httpMethod & HttpDeliveryMethods.PutRequest) != 0) {
+ return "PUT";
+ } else if ((httpMethod & HttpDeliveryMethods.DeleteRequest) != 0) {
+ return "DELETE";
+ } else if ((httpMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) {
+ return "GET"; // if AuthorizationHeaderRequest is specified without an explicit HTTP verb, assume GET.
+ } else {
+ throw ErrorUtilities.ThrowArgumentNamed("httpMethod", MessagingStrings.UnsupportedHttpVerb, httpMethod);
+ }
}
/// <summary>
@@ -776,6 +816,32 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Ensures that UTC times are converted to local times. Unspecified kinds are unchanged.
+ /// </summary>
+ /// <param name="value">The date-time to convert.</param>
+ /// <returns>The date-time in local time.</returns>
+ internal static DateTime ToLocalTimeSafe(this DateTime value) {
+ if (value.Kind == DateTimeKind.Unspecified) {
+ return value;
+ }
+
+ return value.ToLocalTime();
+ }
+
+ /// <summary>
+ /// Ensures that local times are converted to UTC times. Unspecified kinds are unchanged.
+ /// </summary>
+ /// <param name="value">The date-time to convert.</param>
+ /// <returns>The date-time in UTC time.</returns>
+ internal static DateTime ToUniversalTimeSafe(this DateTime value) {
+ if (value.Kind == DateTimeKind.Unspecified) {
+ return value;
+ }
+
+ return value.ToUniversalTime();
+ }
+
+ /// <summary>
/// A class to convert a <see cref="Comparison&lt;T&gt;"/> into an <see cref="IComparer&lt;T&gt;"/>.
/// </summary>
/// <typeparam name="T">The type of objects being compared.</typeparam>
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index 84a4327..7fe8222 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -203,7 +203,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
this.field.SetValue(message, this.ToValue(value));
}
}
- } catch (FormatException ex) {
+ } catch (Exception ex) {
throw ErrorUtilities.Wrap(ex, MessagingStrings.MessagePartReadFailure, message.GetType(), this.Name, value);
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs
index ff004cb..dd28e71 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs
@@ -15,7 +15,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// This interface should be implemented by the same class that implements
/// <see cref="ITokenManager"/> in order to enable the OpenID+OAuth extension.
/// </remarks>
- public interface ICombinedOpenIdProviderTokenManager {
+ public interface ICombinedOpenIdProviderTokenManager : IOpenIdOAuthTokenManager, ITokenManager {
/// <summary>
/// Gets the OAuth consumer key for a given OpenID relying party realm.
/// </summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs
index 329ac4d..35ba52d 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderAccessToken.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
@@ -31,6 +32,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <value>
/// The name of the user who authorized the OAuth request token originally.
/// </value>
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Username", Justification = "Breaking change.")]
string Username { get; }
/// <summary>
@@ -40,6 +42,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// The roles that the user belongs to, or a subset of these according to the rights
/// granted when the user authorized the request token.
/// </value>
+ [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "By design.")]
string[] Roles { get; }
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
index 02ebffb..afeaab3 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/IServiceProviderTokenManager.cs
@@ -50,5 +50,19 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// log and throw the appropriate error.
/// </remarks>
IServiceProviderAccessToken GetAccessToken(string token);
+
+ /// <summary>
+ /// Persists any changes made to the token.
+ /// </summary>
+ /// <param name="token">The token whose properties have been changed.</param>
+ /// <remarks>
+ /// This library will invoke this method after making a set
+ /// of changes to the token as part of a web request to give the host
+ /// the opportunity to persist those changes to a database.
+ /// Depending on the object persistence framework the host site uses,
+ /// this method MAY not need to do anything (if changes made to the token
+ /// will automatically be saved without any extra handling).
+ /// </remarks>
+ void UpdateToken(IServiceProviderRequestToken token);
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index a36287f..59d0fea 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -148,7 +148,11 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
// Scrape the query string
foreach (string key in request.QueryStringBeforeRewriting) {
- fields.Add(key, request.QueryStringBeforeRewriting[key]);
+ if (key != null) {
+ fields.Add(key, request.QueryStringBeforeRewriting[key]);
+ } else {
+ Logger.OAuth.WarnFormat("Ignoring query string parameter '{0}' since it isn't a standard name=value parameter.", request.QueryStringBeforeRewriting[key]);
+ }
}
// Deserialize the message using all the data we've collected.
@@ -196,6 +200,10 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
httpRequest = this.InitializeRequestAsPost(request);
} else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) {
httpRequest = InitializeRequestAsGet(request);
+ } else if ((transmissionMethod & HttpDeliveryMethods.PutRequest) != 0) {
+ httpRequest = this.InitializeRequestAsPut(request);
+ } else if ((transmissionMethod & HttpDeliveryMethods.DeleteRequest) != 0) {
+ httpRequest = InitializeRequestAsDelete(request);
} else {
throw new NotSupportedException();
}
@@ -282,7 +290,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if (signedMessage != null) {
return signedMessage.HttpMethod;
} else {
- return (message.HttpMethods & HttpDeliveryMethods.PostRequest) != 0 ? "POST" : "GET";
+ return MessagingUtilities.GetHttpVerb(message.HttpMethods);
}
}
@@ -297,7 +305,6 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <para>This method implements OAuth 1.0 section 5.2, item #1 (described in section 5.4).</para>
/// </remarks>
private HttpWebRequest InitializeRequestAsAuthHeader(IDirectedProtocolMessage requestMessage) {
- var protocol = Protocol.Lookup(requestMessage.Version);
var dictionary = this.MessageDescriptions.GetAccessor(requestMessage);
// copy so as to not modify original
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthHttpMethodBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthHttpMethodBindingElement.cs
index c9df0e8..37fb80b 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthHttpMethodBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthHttpMethodBindingElement.cs
@@ -42,15 +42,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if (oauthMessage != null) {
HttpDeliveryMethods transmissionMethod = oauthMessage.HttpMethods;
- if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) {
- oauthMessage.HttpMethod = "POST";
- } else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) {
- oauthMessage.HttpMethod = "GET";
- } else {
+ try {
+ oauthMessage.HttpMethod = MessagingUtilities.GetHttpVerb(transmissionMethod);
+ return MessageProtections.None;
+ } catch (ArgumentException ex) {
+ Logger.OAuth.Error("Unrecognized HttpDeliveryMethods value.", ex);
return null;
}
-
- return MessageProtections.None;
} else {
return null;
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthIdentity.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthIdentity.cs
index f5b362c..65bde20 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthIdentity.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthIdentity.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using System.Security.Principal;
@@ -14,6 +15,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <summary>
/// Represents an OAuth consumer that is impersonating a known user on the system.
/// </summary>
+ [SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "Not cocreatable.")]
[Serializable]
[ComVisible(true)]
public class OAuthIdentity : IIdentity {
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthPrincipal.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthPrincipal.cs
index 0dc57e6..025ef09 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthPrincipal.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthPrincipal.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.InteropServices;
@@ -15,6 +16,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <summary>
/// Represents an OAuth consumer that is impersonating a known user on the system.
/// </summary>
+ [SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "Not cocreatable.")]
[Serializable]
[ComVisible(true)]
public class OAuthPrincipal : IPrincipal {
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs
index 429615a..5b3c918 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthServiceProviderMessageFactory.cs
@@ -25,7 +25,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// Initializes a new instance of the <see cref="OAuthServiceProviderMessageFactory"/> class.
/// </summary>
/// <param name="tokenManager">The token manager instance to use.</param>
- protected internal OAuthServiceProviderMessageFactory(IServiceProviderTokenManager tokenManager) {
+ public OAuthServiceProviderMessageFactory(IServiceProviderTokenManager tokenManager) {
Contract.Requires<ArgumentNullException>(tokenManager != null);
this.tokenManager = tokenManager;
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs
index 9f99066..22e5f20 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs
@@ -41,7 +41,12 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="message">The message that needs to be signed.</param>
/// <returns>True if this binding element can be used to sign the message. False otherwise.</returns>
protected override bool IsMessageApplicable(ITamperResistantOAuthMessage message) {
- return string.Equals(message.Recipient.Scheme, "https", StringComparison.OrdinalIgnoreCase);
+ if (string.Equals(message.Recipient.Scheme, "https", StringComparison.OrdinalIgnoreCase)) {
+ return true;
+ } else {
+ Logger.Bindings.DebugFormat("The {0} element will not sign this message because the URI scheme is not https.", this.GetType().Name);
+ return false;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
index 249e18f..f9547c6 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
@@ -69,7 +69,9 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
var userAuthResponse = message as UserAuthorizationResponse;
if (userAuthResponse != null && userAuthResponse.Version >= Protocol.V10a.Version) {
- this.tokenManager.GetRequestToken(userAuthResponse.RequestToken).VerificationCode = userAuthResponse.VerificationCode;
+ var requestToken = this.tokenManager.GetRequestToken(userAuthResponse.RequestToken);
+ requestToken.VerificationCode = userAuthResponse.VerificationCode;
+ this.tokenManager.UpdateToken(requestToken);
return MessageProtections.None;
}
@@ -77,10 +79,14 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
var grantRequestTokenResponse = message as UnauthorizedTokenResponse;
if (grantRequestTokenResponse != null) {
this.tokenManager.StoreNewRequestToken(grantRequestTokenResponse.RequestMessage, grantRequestTokenResponse);
- this.tokenManager.GetRequestToken(grantRequestTokenResponse.RequestToken).ConsumerVersion = grantRequestTokenResponse.Version;
+
+ // The host may have already set these properties, but just to make sure...
+ var requestToken = this.tokenManager.GetRequestToken(grantRequestTokenResponse.RequestToken);
+ requestToken.ConsumerVersion = grantRequestTokenResponse.Version;
if (grantRequestTokenResponse.RequestMessage.Callback != null) {
- this.tokenManager.GetRequestToken(grantRequestTokenResponse.RequestToken).Callback = grantRequestTokenResponse.RequestMessage.Callback;
+ requestToken.Callback = grantRequestTokenResponse.RequestMessage.Callback;
}
+ this.tokenManager.UpdateToken(requestToken);
return MessageProtections.None;
}
@@ -141,7 +147,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
try {
IServiceProviderAccessToken token = this.tokenManager.GetAccessToken(message.AccessToken);
- if (token.ExpirationDate.HasValue && DateTime.Now >= token.ExpirationDate.Value.ToLocalTime()) {
+ if (token.ExpirationDate.HasValue && DateTime.Now >= token.ExpirationDate.Value.ToLocalTimeSafe()) {
Logger.OAuth.ErrorFormat(
"OAuth access token {0} rejected because it expired at {1}, and it is now {2}.",
token.Token,
@@ -161,14 +167,14 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <exception cref="ProtocolException">Thrown when the token in the message has expired.</exception>
private void VerifyThrowTokenTimeToLive(ITokenContainingMessage message) {
ErrorUtilities.VerifyInternal(!(message is AccessProtectedResourceRequest), "We shouldn't be verifying TTL on access tokens.");
- if (message == null) {
+ if (message == null || string.IsNullOrEmpty(message.Token)) {
return;
}
try {
IServiceProviderRequestToken token = this.tokenManager.GetRequestToken(message.Token);
TimeSpan ttl = DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.MaximumRequestTokenTimeToLive;
- if (DateTime.Now >= token.CreatedOn.ToLocalTime() + ttl) {
+ if (DateTime.Now >= token.CreatedOn.ToLocalTimeSafe() + ttl) {
Logger.OAuth.ErrorFormat(
"OAuth request token {0} rejected because it was originally issued at {1}, expired at {2}, and it is now {3}.",
token.Token,
diff --git a/src/DotNetOpenAuth/OAuth/Messages/MessageBase.cs b/src/DotNetOpenAuth/OAuth/Messages/MessageBase.cs
index be2c95d..1a0ba23 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/MessageBase.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/MessageBase.cs
@@ -17,6 +17,7 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// <summary>
/// A base class for all OAuth messages.
/// </summary>
+ [Serializable]
public abstract class MessageBase : IDirectedProtocolMessage, IDirectResponseProtocolMessage {
/// <summary>
/// A store for extra name/value data pairs that are attached to this message.
diff --git a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
index 1d8ca21..57ce470 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
@@ -36,7 +36,7 @@ namespace DotNetOpenAuth.OAuth.Messages {
: base(MessageProtections.All, transport, recipient, version) {
ITamperResistantOAuthMessage self = (ITamperResistantOAuthMessage)this;
HttpDeliveryMethods methods = ((IDirectedProtocolMessage)this).HttpMethods;
- self.HttpMethod = (methods & HttpDeliveryMethods.PostRequest) != 0 ? "POST" : "GET";
+ self.HttpMethod = MessagingUtilities.GetHttpVerb(methods);
}
#region ITamperResistantOAuthMessage Members
diff --git a/src/DotNetOpenAuth/OAuth/Messages/UnauthorizedTokenResponse.cs b/src/DotNetOpenAuth/OAuth/Messages/UnauthorizedTokenResponse.cs
index 5d34617..0be9f63 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/UnauthorizedTokenResponse.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/UnauthorizedTokenResponse.cs
@@ -90,6 +90,8 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// <summary>
/// Gets a value indicating whether the Service Provider recognized the callback parameter in the request.
/// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Message serialization invoked.")]
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Message parts must be instance members.")]
[MessagePart("oauth_callback_confirmed", IsRequired = true, MinVersion = Protocol.V10aVersion)]
private bool CallbackConfirmed {
get { return true; }
diff --git a/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationRequest.cs b/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationRequest.cs
index 099729e..a5823bb 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationRequest.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationRequest.cs
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// so the Service Provider can ask the user to authorize the Consumer's access to some
/// protected resource(s).
/// </summary>
+ [Serializable]
public class UserAuthorizationRequest : MessageBase, ITokenContainingMessage {
/// <summary>
/// Initializes a new instance of the <see cref="UserAuthorizationRequest"/> class.
diff --git a/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationResponse.cs b/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationResponse.cs
index 69a327c..73fddc7 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationResponse.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/UserAuthorizationResponse.cs
@@ -14,6 +14,7 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// <remarks>
/// The class is sealed because extra parameters are determined by the callback URI provided by the Consumer.
/// </remarks>
+ [Serializable]
public sealed class UserAuthorizationResponse : MessageBase, ITokenContainingMessage {
/// <summary>
/// Initializes a new instance of the <see cref="UserAuthorizationResponse"/> class.
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.sr.resx b/src/DotNetOpenAuth/OAuth/OAuthStrings.sr.resx
new file mode 100644
index 0000000..ef9ce60
--- /dev/null
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.sr.resx
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="AccessTokenNotAuthorized" xml:space="preserve">
+ <value>Ne može se poslati pristupni token za Consumera za token zahteva '{0}' pre nego što bude autorizovan.</value>
+ </data>
+ <data name="BadAccessTokenInProtectedResourceRequest" xml:space="preserve">
+ <value>Pristupni token '{0}' je neispravan ili je mu je istekao rok važenja.</value>
+ </data>
+ <data name="ConsumerOrTokenSecretNotFound" xml:space="preserve">
+ <value>Greška u traženju šifre za korisnika ili za token.</value>
+ </data>
+ <data name="IncorrectVerifier" xml:space="preserve">
+ <value>oauth_verifier argument je neispravan.</value>
+ </data>
+ <data name="InvalidIncomingMessage" xml:space="preserve">
+ <value>Neispravna OAuth poruka je primljena i odbačena.</value>
+ </data>
+ <data name="MessageNotAllowedExtraParameters" xml:space="preserve">
+ <value>Poruka {0} je sadržala višak podataka koji nije dozvoljen.</value>
+ </data>
+ <data name="MinimumConsumerVersionRequirementNotMet" xml:space="preserve">
+ <value>Ovaj provajder OAuth usluge zahteva od OAuth korisnika da da implementira OAuth {0}, ali izgleda da korisnika podržava jedino {1}.</value>
+ </data>
+ <data name="OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface" xml:space="preserve">
+ <value>Korišćenje OpenID+OAuth ekstenzije zahteva da token menadžer koji se koristi implementira {0} interfejs.</value>
+ </data>
+ <data name="OpenIdOAuthRealmConsumerKeyDoNotMatch" xml:space="preserve">
+ <value>OpenID Relying Party domen nije prepoznat kao da pripada OAuth Consumeru identifikovanom po datom korisničkom tokenu.</value>
+ </data>
+ <data name="RequestUrlMustNotHaveOAuthParameters" xml:space="preserve">
+ <value>URL upit zahteva NE SME sadržati bilo kakve OAuth Protocol Parametre.</value>
+ </data>
+ <data name="SigningElementAlreadyAssociatedWithChannel" xml:space="preserve">
+ <value>Potpisujući element je već asociran sa kanalom.</value>
+ </data>
+ <data name="SigningElementsMustShareSameProtection" xml:space="preserve">
+ <value>Svi elementi za potpisivanje moraju nuditi istu zaštitu poruke.</value>
+ </data>
+ <data name="TokenNotFound" xml:space="preserve">
+ <value>Token u poruci nije prepoznat od strane provajdera usluge.</value>
+ </data>
+ <data name="X509CertificateNotProvidedForSigning" xml:space="preserve">
+ <value>RSA-SHA1 potpisujući povezujući element nije podešen sa sertifikatom za potpisivanje.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OAuth/Protocol.cs b/src/DotNetOpenAuth/OAuth/Protocol.cs
index 3845e4e..a524ba7 100644
--- a/src/DotNetOpenAuth/OAuth/Protocol.cs
+++ b/src/DotNetOpenAuth/OAuth/Protocol.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth {
using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -25,6 +26,7 @@ namespace DotNetOpenAuth.OAuth {
/// <summary>
/// OAuth 1.0a specification
/// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "a", Justification = "By design.")]
V10a,
}
diff --git a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
index 0495ea7..161cf14 100644
--- a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
+++ b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
@@ -60,15 +60,39 @@ namespace DotNetOpenAuth.OAuth {
/// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param>
/// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
/// <param name="messageTypeProvider">An object that can figure out what type of message is being received for deserialization.</param>
- public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider) {
+ public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, OAuthServiceProviderMessageFactory messageTypeProvider)
+ : this(serviceDescription, tokenManager, new NonceMemoryStore(StandardExpirationBindingElement.DefaultMaximumMessageAge), messageTypeProvider) {
Contract.Requires<ArgumentNullException>(serviceDescription != null);
Contract.Requires<ArgumentNullException>(tokenManager != null);
Contract.Requires<ArgumentNullException>(messageTypeProvider != null);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServiceProvider"/> class.
+ /// </summary>
+ /// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param>
+ /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
+ /// <param name="nonceStore">The nonce store.</param>
+ public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore)
+ : this(serviceDescription, tokenManager, nonceStore, new OAuthServiceProviderMessageFactory(tokenManager)) {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServiceProvider"/> class.
+ /// </summary>
+ /// <param name="serviceDescription">The endpoints and behavior on the Service Provider.</param>
+ /// <param name="tokenManager">The host's method of storing and recalling tokens and secrets.</param>
+ /// <param name="nonceStore">The nonce store.</param>
+ /// <param name="messageTypeProvider">An object that can figure out what type of message is being received for deserialization.</param>
+ public ServiceProvider(ServiceProviderDescription serviceDescription, IServiceProviderTokenManager tokenManager, INonceStore nonceStore, OAuthServiceProviderMessageFactory messageTypeProvider) {
+ Contract.Requires<ArgumentNullException>(serviceDescription != null);
+ Contract.Requires<ArgumentNullException>(tokenManager != null);
+ Contract.Requires<ArgumentNullException>(nonceStore != null);
+ Contract.Requires<ArgumentNullException>(messageTypeProvider != null);
var signingElement = serviceDescription.CreateTamperProtectionElement();
- INonceStore store = new NonceMemoryStore(StandardExpirationBindingElement.DefaultMaximumMessageAge);
this.ServiceDescription = serviceDescription;
- this.OAuthChannel = new OAuthChannel(signingElement, store, tokenManager, messageTypeProvider);
+ this.OAuthChannel = new OAuthChannel(signingElement, nonceStore, tokenManager, messageTypeProvider);
this.TokenGenerator = new StandardTokenGenerator();
this.SecuritySettings = DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.CreateSecuritySettings();
}
@@ -234,11 +258,12 @@ namespace DotNetOpenAuth.OAuth {
/// <summary>
/// Gets the OAuth authorization request included with an OpenID authentication
- /// request.
+ /// request, if there is one.
/// </summary>
/// <param name="openIdRequest">The OpenID authentication request.</param>
/// <returns>
- /// The scope of access the relying party is requesting.
+ /// The scope of access the relying party is requesting, or null if no OAuth request
+ /// is present.
/// </returns>
/// <remarks>
/// <para>Call this method rather than simply extracting the OAuth extension
@@ -267,23 +292,42 @@ namespace DotNetOpenAuth.OAuth {
return authzRequest;
}
- /// <summary>
+ /// <summary>
/// Attaches the authorization response to an OpenID authentication response.
/// </summary>
/// <param name="openIdAuthenticationRequest">The OpenID authentication request.</param>
- /// <param name="consumerKey">The consumer key. May and should be <c>null</c> if and only if <paramref name="scope"/> is null.</param>
+ /// <param name="consumerKey">The consumer key. Must be <c>null</c> if and only if <paramref name="scope"/> is null.</param>
/// <param name="scope">The approved access scope. Use <c>null</c> to indicate no access was granted. The empty string will be interpreted as some default level of access is granted.</param>
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "We want to take IAuthenticationRequest because that's the only supported use case.")]
- public void AttachAuthorizationResponse(IAuthenticationRequest openIdAuthenticationRequest, string consumerKey, string scope) {
+ [Obsolete("Call the overload that doesn't take a consumerKey instead.")]
+ public void AttachAuthorizationResponse(IHostProcessedRequest openIdAuthenticationRequest, string consumerKey, string scope) {
Contract.Requires<ArgumentNullException>(openIdAuthenticationRequest != null);
Contract.Requires<ArgumentException>((consumerKey == null) == (scope == null));
- Contract.Requires<InvalidOperationException>(this.TokenManager is IOpenIdOAuthTokenManager);
- var openidTokenManager = this.TokenManager as IOpenIdOAuthTokenManager;
- ErrorUtilities.VerifyOperation(openidTokenManager != null, OAuthStrings.OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface, typeof(IOpenIdOAuthTokenManager).FullName);
+ Contract.Requires<InvalidOperationException>(this.TokenManager is ICombinedOpenIdProviderTokenManager);
+ ErrorUtilities.VerifyArgumentNotNull(openIdAuthenticationRequest, "openIdAuthenticationRequest");
+ var openidTokenManager = (ICombinedOpenIdProviderTokenManager)this.TokenManager;
+ ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), "The consumer key and the realm did not match according to the token manager.");
+
+ this.AttachAuthorizationResponse(openIdAuthenticationRequest, scope);
+ }
+
+ /// <summary>
+ /// Attaches the authorization response to an OpenID authentication response.
+ /// </summary>
+ /// <param name="openIdAuthenticationRequest">The OpenID authentication request.</param>
+ /// <param name="scope">The approved access scope. Use <c>null</c> to indicate no access was granted. The empty string will be interpreted as some default level of access is granted.</param>
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "We want to take IAuthenticationRequest because that's the only supported use case.")]
+ public void AttachAuthorizationResponse(IHostProcessedRequest openIdAuthenticationRequest, string scope) {
+ Contract.Requires(openIdAuthenticationRequest != null);
+ Contract.Requires(this.TokenManager is IOpenIdOAuthTokenManager);
+ ErrorUtilities.VerifyArgumentNotNull(openIdAuthenticationRequest, "openIdAuthenticationRequest");
+ var openidTokenManager = this.TokenManager as ICombinedOpenIdProviderTokenManager;
+ ErrorUtilities.VerifyOperation(openidTokenManager != null, OAuthStrings.OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface, typeof(ICombinedOpenIdProviderTokenManager).FullName);
IOpenIdMessageExtension response;
if (scope != null) {
// Generate an authorized request token to return to the relying party.
+ string consumerKey = openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm);
var approvedResponse = new AuthorizationApprovedResponse {
RequestToken = this.TokenGenerator.GenerateRequestToken(consumerKey),
Scope = scope,
diff --git a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
index d25c988..3afd44e 100644
--- a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
+++ b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
@@ -5,6 +5,8 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OAuth {
+ using System.Diagnostics.CodeAnalysis;
+
/// <summary>
/// The different formats a user authorization verifier code can take
/// in order to be as secure as possible while being compatible with
@@ -33,6 +35,8 @@ namespace DotNetOpenAuth.OAuth {
/// Some letters and numbers will be skipped where they are visually similar
/// enough that they can be difficult to distinguish when displayed with most fonts.
/// </remarks>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Alikes", Justification = "Breaking change of existing API")]
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "AlphaNumeric", Justification = "Breaking change of existing API")]
AlphaNumericNoLookAlikes,
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/WebConsumer.cs b/src/DotNetOpenAuth/OAuth/WebConsumer.cs
index afe972f..de37b80 100644
--- a/src/DotNetOpenAuth/OAuth/WebConsumer.cs
+++ b/src/DotNetOpenAuth/OAuth/WebConsumer.cs
@@ -118,7 +118,8 @@ namespace DotNetOpenAuth.OAuth {
}
// Prepare a message to exchange the request token for an access token.
- var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, this.ServiceProvider.Version) {
+ // We are careful to use a v1.0 message version so that the oauth_verifier is not required.
+ var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, Protocol.V10.Version) {
RequestToken = positiveAuthorization.RequestToken,
ConsumerKey = this.ConsumerKey,
};
diff --git a/src/DotNetOpenAuth/OpenId/Association.cs b/src/DotNetOpenAuth/OpenId/Association.cs
index c65bdd6..d2c84cb 100644
--- a/src/DotNetOpenAuth/OpenId/Association.cs
+++ b/src/DotNetOpenAuth/OpenId/Association.cs
@@ -163,7 +163,7 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<ArgumentNullException>(privateData != null);
Contract.Ensures(Contract.Result<Association>() != null);
- expires = expires.ToUniversalTime();
+ expires = expires.ToUniversalTimeSafe();
TimeSpan remainingLifeLength = expires - DateTime.UtcNow;
byte[] secret = privateData; // the whole of privateData is the secret key for now.
// We figure out what derived type to instantiate based on the length of the secret.
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
index 1c124d8..d7dca9a 100644
--- a/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.Behaviors {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
@@ -21,6 +22,7 @@ namespace DotNetOpenAuth.OpenId.Behaviors {
/// requests look like Simple Registration requests, and to convert the response
/// to the originally requested extension and format.
/// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Abbreviation")]
public class AXFetchAsSregTransform : IRelyingPartyBehavior, IProviderBehavior {
/// <summary>
/// Initializes static members of the <see cref="AXFetchAsSregTransform"/> class.
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.sr.resx b/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.sr.resx
new file mode 100644
index 0000000..2b1b911
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/BehaviorStrings.sr.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="PpidProviderNotGiven" xml:space="preserve">
+ <value>Nijedan PPID provajder nije konfigurisan.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs b/src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs
index 643d6df..baef943 100644
--- a/src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/PpidGeneration.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OpenId.Behaviors {
using System;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -24,10 +25,12 @@ namespace DotNetOpenAuth.OpenId.Behaviors {
/// <c>Application_Start</c> method in the global.asax.cs file.</para>
/// </remarks>
[Serializable]
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ppid", Justification = "Abbreviation")]
public sealed class PpidGeneration : IProviderBehavior {
/// <summary>
/// Gets or sets the provider for generating PPID identifiers.
/// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Ppid", Justification = "Abbreviation")]
public static IDirectedIdentityIdentifierProvider PpidIdentifierProvider { get; set; }
#region IProviderBehavior Members
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
index f64ae38..6a0c0cf 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
@@ -23,11 +23,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// </summary>
internal class ExtensionsBindingElement : IChannelBindingElement {
/// <summary>
- /// The security settings that apply to this binding element.
- /// </summary>
- private readonly SecuritySettings securitySettings;
-
- /// <summary>
/// The security settings that apply to this relying party, if it is a relying party.
/// </summary>
private readonly RelyingPartySecuritySettings relyingPartySecuritySettings;
@@ -42,7 +37,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
Contract.Requires<ArgumentNullException>(securitySettings != null);
this.ExtensionFactory = extensionFactory;
- this.securitySettings = securitySettings;
this.relyingPartySecuritySettings = securitySettings as RelyingPartySecuritySettings;
}
@@ -195,18 +189,25 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
// Initialize this particular extension.
IOpenIdMessageExtension extension = this.ExtensionFactory.Create(typeUri, extensionData, message, isAtProvider);
if (extension != null) {
- MessageDictionary extensionDictionary = this.Channel.MessageDescriptions.GetAccessor(extension);
- foreach (var pair in extensionData) {
- extensionDictionary[pair.Key] = pair.Value;
- }
+ try {
+ MessageDictionary extensionDictionary = this.Channel.MessageDescriptions.GetAccessor(extension);
+ foreach (var pair in extensionData) {
+ extensionDictionary[pair.Key] = pair.Value;
+ }
- // Give extensions that require custom serialization a chance to do their work.
- var customSerializingExtension = extension as IMessageWithEvents;
- if (customSerializingExtension != null) {
- customSerializingExtension.OnReceiving();
+ // Give extensions that require custom serialization a chance to do their work.
+ var customSerializingExtension = extension as IMessageWithEvents;
+ if (customSerializingExtension != null) {
+ customSerializingExtension.OnReceiving();
+ }
+ } catch (ProtocolException ex) {
+ Logger.OpenId.ErrorFormat(OpenIdStrings.BadExtension, extension.GetType(), ex);
+ extension = null;
}
- yield return extension;
+ if (extension != null) {
+ yield return extension;
+ }
} else {
Logger.OpenId.WarnFormat("Extension with type URI '{0}' ignored because it is not a recognized extension.", typeUri);
}
diff --git a/src/DotNetOpenAuth/OpenId/DiffieHellmanUtilities.cs b/src/DotNetOpenAuth/OpenId/DiffieHellmanUtilities.cs
index ef59fed..249f1f3 100644
--- a/src/DotNetOpenAuth/OpenId/DiffieHellmanUtilities.cs
+++ b/src/DotNetOpenAuth/OpenId/DiffieHellmanUtilities.cs
@@ -22,12 +22,12 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// An array of known Diffie Hellman sessions, sorted by decreasing hash size.
/// </summary>
- private static DHSha[] diffieHellmanSessionTypes = {
+ private static DHSha[] diffieHellmanSessionTypes = new List<DHSha> {
new DHSha(new SHA512Managed(), protocol => protocol.Args.SessionType.DH_SHA512),
new DHSha(new SHA384Managed(), protocol => protocol.Args.SessionType.DH_SHA384),
new DHSha(new SHA256Managed(), protocol => protocol.Args.SessionType.DH_SHA256),
new DHSha(new SHA1Managed(), protocol => protocol.Args.SessionType.DH_SHA1),
- };
+ } .ToArray();
/// <summary>
/// Finds the hashing algorithm to use given an openid.session_type value.
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs
index 7e4ed73..decd296 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs
@@ -35,7 +35,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// All known schemas.
/// </summary>
- All = 0xff,
+ All = AXSchemaOrg | SchemaOpenIdNet | OpenIdNetSchema,
/// <summary>
/// The most common schemas.
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
index 16283c0..cd7575e 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.Extensions {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -39,6 +40,7 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// <para>If the request does not carry an sreg extension, the method logs a warning but
/// otherwise quietly returns doing nothing.</para>
/// </remarks>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Abbreviation")]
public static void SpreadSregToAX(this RelyingParty.IAuthenticationRequest request, AXAttributeFormats attributeFormats) {
Contract.Requires<ArgumentNullException>(request != null);
@@ -94,6 +96,7 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// or a fabricated one based on the Attribute Exchange extension if found,
/// or just an empty <see cref="ClaimsResponse"/> if there was no data.
/// Never <c>null</c>.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Abbreviation")]
public static ClaimsResponse UnifyExtensionsAsSreg(this RelyingParty.IAuthenticationResponse response, bool allowUnsigned) {
Contract.Requires<ArgumentNullException>(response != null);
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/DateTimeEncoder.cs b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/DateTimeEncoder.cs
index 82297d0..9dc0574 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/DateTimeEncoder.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/DateTimeEncoder.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
using System;
using System.Globalization;
+ using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
/// <summary>
@@ -39,7 +40,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
public string Encode(object value) {
DateTime? dateTime = value as DateTime?;
if (dateTime.HasValue) {
- return dateTime.Value.ToUniversalTime().ToString(PermissibleDateTimeFormats[0], CultureInfo.InvariantCulture);
+ return dateTime.Value.ToUniversalTimeSafe().ToString(PermissibleDateTimeFormats[0], CultureInfo.InvariantCulture);
} else {
return null;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
index 4b2bcc9..b476cf7 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
@@ -90,7 +90,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
// Convert to UTC and cut to the second, since the protocol only allows for
// that level of precision.
- this.authenticationTimeUtc = OpenIdUtilities.CutToSecond(value.Value.ToUniversalTime());
+ this.authenticationTimeUtc = OpenIdUtilities.CutToSecond(value.Value.ToUniversalTimeSafe());
} else {
this.authenticationTimeUtc = null;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
index 871ac27..f775492 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
@@ -254,6 +254,8 @@ TimeZone = '{8}'";
internal void SetProfileRequestFromList(IEnumerable<string> fieldNames, DemandLevel requestLevel) {
foreach (string field in fieldNames) {
switch (field) {
+ case "": // this occurs for empty lists
+ break;
case Constants.nickname:
this.Nickname = requestLevel;
break;
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIConstants.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIConstants.cs
new file mode 100644
index 0000000..963b301
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIConstants.cs
@@ -0,0 +1,28 @@
+//-----------------------------------------------------------------------
+// <copyright file="UIConstants.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions.UI {
+ /// <summary>
+ /// Constants used to support the UI extension.
+ /// </summary>
+ internal static class UIConstants {
+ /// <summary>
+ /// The type URI associated with this extension.
+ /// </summary>
+ internal const string UITypeUri = "http://specs.openid.net/extensions/ui/1.0";
+
+ /// <summary>
+ /// The Type URI that appears in an XRDS document when the OP supports popups through the UI extension.
+ /// </summary>
+ internal const string PopupSupported = "http://specs.openid.net/extensions/ui/1.0/mode/popup";
+
+ /// <summary>
+ /// The Type URI that appears in an XRDS document when the OP supports the RP
+ /// specifying the user's preferred language through the UI extension.
+ /// </summary>
+ internal const string LangPrefSupported = "http://specs.openid.net/extensions/ui/1.0/lang-pref";
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
index 476b4ad..d67d932 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
@@ -33,7 +33,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// The factory method that may be used in deserialization of this message.
/// </summary>
internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
- if (typeUri == UITypeUri && isProviderRole) {
+ if (typeUri == UIConstants.UITypeUri && isProviderRole) {
return new UIRequest();
}
@@ -41,9 +41,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
};
/// <summary>
- /// The type URI associated with this extension.
+ /// Additional type URIs that this extension is sometimes known by remote parties.
/// </summary>
- private const string UITypeUri = "http://specs.openid.net/extensions/ui/1.0";
+ private static readonly string[] additionalTypeUris = new string[] {
+ UIConstants.LangPrefSupported,
+ UIConstants.PopupSupported,
+ };
/// <summary>
/// Backing store for <see cref="ExtraData"/>.
@@ -75,13 +78,25 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
[MessagePart("mode", AllowEmpty = false, IsRequired = true)]
public string Mode { get { return UIModes.Popup; } }
+ /// <summary>
+ /// Gets or sets a value indicating whether the Relying Party has an icon
+ /// it would like the Provider to display to the user while asking them
+ /// whether they would like to log in.
+ /// </summary>
+ /// <value><c>true</c> if the Provider should display an icon; otherwise, <c>false</c>.</value>
+ /// <remarks>
+ /// By default, the Provider displays the relying party's favicon.ico.
+ /// </remarks>
+ [MessagePart("popup", AllowEmpty = false, IsRequired = false)]
+ public bool? Icon { get; set; }
+
#region IOpenIdMessageExtension Members
/// <summary>
/// Gets the TypeURI the extension uses in the OpenID protocol and in XRDS advertisements.
/// </summary>
/// <value></value>
- public string TypeUri { get { return UITypeUri; } }
+ public string TypeUri { get { return UIConstants.UITypeUri; } }
/// <summary>
/// Gets the additional TypeURIs that are supported by this extension, in preferred order.
@@ -98,7 +113,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// given the version of the extension in the request message.
/// The <see cref="Extensions.SimpleRegistration.ClaimsRequest.CreateResponse"/> for an example.
/// </remarks>
- public IEnumerable<string> AdditionalSupportedTypeUris { get { return Enumerable.Empty<string>(); } }
+ public IEnumerable<string> AdditionalSupportedTypeUris { get { return additionalTypeUris; } }
/// <summary>
/// Gets or sets a value indicating whether this extension was
diff --git a/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs b/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
index f95536c..e0317db 100644
--- a/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
+++ b/src/DotNetOpenAuth/OpenId/HmacShaAssociation.cs
@@ -31,7 +31,7 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// A list of HMAC-SHA algorithms in order of decreasing bit lengths.
/// </summary>
- private static HmacSha[] hmacShaAssociationTypes = {
+ private static HmacSha[] hmacShaAssociationTypes = new List<HmacSha> {
new HmacSha {
CreateHasher = secretKey => new HMACSHA512(secretKey),
GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA512,
@@ -52,7 +52,7 @@ namespace DotNetOpenAuth.OpenId {
GetAssociationType = protocol => protocol.Args.SignatureAlgorithm.HMAC_SHA1,
BaseHashAlgorithm = new SHA1Managed(),
},
- };
+ } .ToArray();
/// <summary>
/// The specific variety of HMAC-SHA this association is based on (whether it be HMAC-SHA1, HMAC-SHA256, etc.)
diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs
index c8aa8c0..0475db1 100644
--- a/src/DotNetOpenAuth/OpenId/Identifier.cs
+++ b/src/DotNetOpenAuth/OpenId/Identifier.cs
@@ -24,15 +24,30 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// Initializes a new instance of the <see cref="Identifier"/> class.
/// </summary>
- /// <param name="isDiscoverySecureEndToEnd">
- /// Whether the derived class is prepared to guarantee end-to-end discovery
- /// and initial redirect for authentication is performed using SSL.
- /// </param>
- protected Identifier(bool isDiscoverySecureEndToEnd) {
+ /// <param name="originalString">The original string before any normalization.</param>
+ /// <param name="isDiscoverySecureEndToEnd">Whether the derived class is prepared to guarantee end-to-end discovery
+ /// and initial redirect for authentication is performed using SSL.</param>
+ protected Identifier(string originalString, bool isDiscoverySecureEndToEnd) {
+ this.OriginalString = originalString;
this.IsDiscoverySecureEndToEnd = isDiscoverySecureEndToEnd;
}
/// <summary>
+ /// Gets the original string that was normalized to create this Identifier.
+ /// </summary>
+ public string OriginalString { get; private set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether <see cref="Identifier"/> instances are considered equal
+ /// based solely on their string reprsentations.
+ /// </summary>
+ /// <remarks>
+ /// This property serves as a test hook, so that MockIdentifier instances can be considered "equal"
+ /// to UriIdentifier instances.
+ /// </remarks>
+ protected internal static bool EqualityOnStrings { get; set; }
+
+ /// <summary>
/// Gets a value indicating whether this Identifier will ensure SSL is
/// used throughout the discovery phase and initial redirect of authentication.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/IdentifierContract.cs b/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
index 79518a6..498ae45 100644
--- a/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
+++ b/src/DotNetOpenAuth/OpenId/IdentifierContract.cs
@@ -20,7 +20,7 @@ namespace DotNetOpenAuth.OpenId {
/// Prevents a default instance of the IdentifierContract class from being created.
/// </summary>
private IdentifierContract()
- : base(false) {
+ : base(null, false) {
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
index d44809f..41c4e21 100644
--- a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
+++ b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
@@ -87,6 +87,19 @@ namespace DotNetOpenAuth.OpenId.Interop {
[ClassInterface(ClassInterfaceType.None)]
public sealed class OpenIdRelyingPartyShim : IOpenIdRelyingParty {
/// <summary>
+ /// The OpenIdRelyingParty instance to use for requests.
+ /// </summary>
+ private static OpenIdRelyingParty relyingParty;
+
+ /// <summary>
+ /// Initializes static members of the <see cref="OpenIdRelyingPartyShim"/> class.
+ /// </summary>
+ static OpenIdRelyingPartyShim() {
+ relyingParty = new OpenIdRelyingParty(null);
+ relyingParty.Behaviors.Add(new Behaviors.AXFetchAsSregTransform());
+ }
+
+ /// <summary>
/// Creates an authentication request to verify that a user controls
/// some given Identifier.
/// </summary>
@@ -109,9 +122,8 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
public string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl) {
- OpenIdRelyingParty rp = new OpenIdRelyingParty(null);
- var request = rp.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
- return request.RedirectingResponse.GetDirectUriRequest(rp.Channel).AbsoluteUri;
+ var request = relyingParty.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
+ return request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel).AbsoluteUri;
}
/// <summary>
@@ -133,8 +145,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
public string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg) {
- OpenIdRelyingParty rp = new OpenIdRelyingParty(null);
- var request = rp.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
+ var request = relyingParty.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
ClaimsRequest sreg = new ClaimsRequest();
if (!string.IsNullOrEmpty(optionalSreg)) {
@@ -144,7 +155,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
sreg.SetProfileRequestFromList(requiredSreg.Split(','), DemandLevel.Require);
}
request.AddExtension(sreg);
- return request.RedirectingResponse.GetDirectUriRequest(rp.Channel).AbsoluteUri;
+ return request.RedirectingResponse.GetDirectUriRequest(relyingParty.Channel).AbsoluteUri;
}
/// <summary>
@@ -155,14 +166,13 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// <param name="form">The form data that may have been included in the case of a POST request.</param>
/// <returns>The Provider's response to a previous authentication request, or null if no response is present.</returns>
public AuthenticationResponseShim ProcessAuthentication(string url, string form) {
- OpenIdRelyingParty rp = new OpenIdRelyingParty(null);
HttpRequestInfo requestInfo = new HttpRequestInfo { UrlBeforeRewriting = new Uri(url) };
if (!string.IsNullOrEmpty(form)) {
requestInfo.HttpMethod = "POST";
requestInfo.InputStream = new MemoryStream(Encoding.Unicode.GetBytes(form));
}
- var response = rp.GetResponse(requestInfo);
+ var response = relyingParty.GetResponse(requestInfo);
if (response != null) {
return new AuthenticationResponseShim(response);
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
index 4ea9995..2f02974 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
@@ -200,7 +200,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </exception>
DateTime IExpiringProtocolMessage.UtcCreationDate {
get { return this.creationDateUtc; }
- set { this.creationDateUtc = value.ToUniversalTime(); }
+ set { this.creationDateUtc = value.ToUniversalTimeSafe(); }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
index 3b65178..636df67 100644
--- a/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/NoDiscoveryIdentifier.cs
@@ -29,7 +29,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="wrappedIdentifier">The ordinary Identifier whose discovery is being masked.</param>
/// <param name="claimSsl">Whether this Identifier should claim to be SSL-secure, although no discovery will never generate service endpoints anyway.</param>
internal NoDiscoveryIdentifier(Identifier wrappedIdentifier, bool claimSsl)
- : base(claimSsl) {
+ : base(wrappedIdentifier.OriginalString, claimSsl) {
Contract.Requires<ArgumentNullException>(wrappedIdentifier != null);
this.wrappedIdentifier = wrappedIdentifier;
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index 86a8715..1ff45f7 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.4918
+// Runtime Version:2.0.50727.4927
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -151,6 +151,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The {0} extension failed to deserialize and will be skipped. {1}.
+ /// </summary>
+ internal static string BadExtension {
+ get {
+ return ResourceManager.GetString("BadExtension", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Callback arguments are only supported when a {0} is provided to the {1}..
/// </summary>
internal static string CallbackArgumentsRequireSecretStore {
@@ -488,6 +497,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party&apos;s whitelist..
+ /// </summary>
+ internal static string PositiveAssertionFromNonWhitelistedProvider {
+ get {
+ return ResourceManager.GetString("PositiveAssertionFromNonWhitelistedProvider", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Unable to find the signing secret by the handle &apos;{0}&apos;..
/// </summary>
internal static string PrivateRPSecretNotFound {
@@ -524,6 +542,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Sorry. This site only accepts OpenIDs that are HTTPS-secured, but {0} is not a secure Identifier..
+ /// </summary>
+ internal static string RequireSslNotSatisfiedByAssertedClaimedId {
+ get {
+ return ResourceManager.GetString("RequireSslNotSatisfiedByAssertedClaimedId", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The response is not ready. Use IsResponseReady to check whether a response is ready first..
/// </summary>
internal static string ResponseNotReady {
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index a4e560e..0c07a90 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -334,4 +334,13 @@ Discovered endpoint info:
<data name="ArgumentIsPpidIdentifier" xml:space="preserve">
<value>This is already a PPID Identifier.</value>
</data>
-</root> \ No newline at end of file
+ <data name="RequireSslNotSatisfiedByAssertedClaimedId" xml:space="preserve">
+ <value>Sorry. This site only accepts OpenIDs that are HTTPS-secured, but {0} is not a secure Identifier.</value>
+ </data>
+ <data name="BadExtension" xml:space="preserve">
+ <value>The {0} extension failed to deserialize and will be skipped. {1}</value>
+ </data>
+ <data name="PositiveAssertionFromNonWhitelistedProvider" xml:space="preserve">
+ <value>An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party's whitelist.</value>
+ </data>
+</root>
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.sr.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.sr.resx
new file mode 100644
index 0000000..0df62c0
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.sr.resx
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="AssociationSecretAndTypeLengthMismatch" xml:space="preserve">
+ <value>Dužina deljene tajne ({0}) ne slaže se sa dužinom zahtevanom od povezujućeg tipa ('{1}').</value>
+ </data>
+ <data name="AssociationSecretHashLengthMismatch" xml:space="preserve">
+ <value>Dužina šifrovane deljene tajne ({0}) ne slaže se sa dužinom hashing algoritma ({1}).</value>
+ </data>
+ <data name="AssociationStoreRequiresNonceStore" xml:space="preserve">
+ <value>Ako je dato povezujuće skladište, jedinstveni identifikator skladišta takođe mora biti prisutan.</value>
+ </data>
+ <data name="BadAssociationPrivateData" xml:space="preserve">
+ <value>Dostavljeni privatni podaci ne slažu se ni sa jednim poznatim Association tipom. Dužina im je možda prekratka ili su podaci neispravni.</value>
+ </data>
+ <data name="CallbackArgumentsRequireSecretStore" xml:space="preserve">
+ <value>Callback argumenti su podržani jedino kada je {0} dustupan za {1}.</value>
+ </data>
+ <data name="CallDeserializeBeforeCreateResponse" xml:space="preserve">
+ <value>Simple Registration zahtev može generisati odgovor jedino na prijemnoj strani.</value>
+ </data>
+ <data name="ClaimedIdAndLocalIdMustBothPresentOrAbsent" xml:space="preserve">
+ <value>openid.claimed_id i openid.identity parametri moraju istovremeno biti prisutni ili nedostajati.</value>
+ </data>
+ <data name="ClaimedIdentifierCannotBeSetOnDelegatedAuthentication" xml:space="preserve">
+ <value>ClaimedIdentifier svojstvo ne može se podesiti kada IsDelegatedIdentifier ima vrednost true da bi se izbeglo narušavanje OpenID URL delegiranja.</value>
+ </data>
+ <data name="ClaimedIdentifierMustBeSetFirst" xml:space="preserve">
+ <value>ClaimedIdentifier svojstvo se najpre mora podesiti.</value>
+ </data>
+ <data name="DiffieHellmanRequiredPropertiesNotSet" xml:space="preserve">
+ <value>Sledeća svojstva moraju biti podešena pre nego što Diffie-Hellmanov algoritam može generisati javni ključ: {0}</value>
+ </data>
+ <data name="ExplicitHttpUriSuppliedWithSslRequirement" xml:space="preserve">
+ <value>URI nije SSL a svojstvo requireSslDiscovery je podešeno na true.</value>
+ </data>
+ <data name="ExtensionAlreadyAddedWithSameTypeURI" xml:space="preserve">
+ <value>Prostor deljenja proširenja '{0}' je već dodat. Samo jedno proširenje po prostoru je dozvoljeno u datom zahtevu.</value>
+ </data>
+ <data name="ExtensionLookupSupportUnavailable" xml:space="preserve">
+ <value>Ne može se tražiti podrška za proširenja na rehidriranom ServiceEndpoint.</value>
+ </data>
+ <data name="FragmentNotAllowedOnXRIs" xml:space="preserve">
+ <value>Segmenti fragmenta se ne primenjuju na XRI identifikatore.</value>
+ </data>
+ <data name="IdentifierSelectRequiresMatchingIdentifiers" xml:space="preserve">
+ <value>ClaimedIdentifier i LocalIdentifier moraju biti isti kada IsIdentifierSelect ima vrednost true.</value>
+ </data>
+ <data name="IndirectErrorFormattedMessage" xml:space="preserve">
+ <value>{0} (Kontakt: {1}, Referenca: {2})</value>
+ </data>
+ <data name="InvalidCharacterInKeyValueFormInput" xml:space="preserve">
+ <value>Ne može se enkodovati '{0}' jer sadrži nevalidan znak za Key-Value Form enkodiranje. (linija {1}: '{2}')</value>
+ </data>
+ <data name="InvalidKeyValueFormCharacterMissing" xml:space="preserve">
+ <value>Ne može se dekodovati Key-Value Form jer je pronađena linija bez '{0}' znaka. (linija {1}: '{2}')</value>
+ </data>
+ <data name="InvalidScheme" xml:space="preserve">
+ <value>Šema mora biti http ili https a bila je '{0}'.</value>
+ </data>
+ <data name="InvalidUri" xml:space="preserve">
+ <value>Vrednost '{0}' nije validan URI.</value>
+ </data>
+ <data name="InvalidXri" xml:space="preserve">
+ <value>Nije prepoznat XRI format: '{0}'.</value>
+ </data>
+ <data name="IssuedAssertionFailsIdentifierDiscovery" xml:space="preserve">
+ <value>OpenID Provider dao je iskaz za Identifier čije se informacije o pronalaženju ne slažu.
+Informacije o krajnoj tački iskaza:
+{0}
+Informacije o otkrivenoj krajnjoj tački:
+{1}</value>
+ </data>
+ <data name="KeysListAndDictionaryDoNotMatch" xml:space="preserve">
+ <value>Lista ključeva se ne slaže sa ponuđenim rečnikom.</value>
+ </data>
+ <data name="MatchingArgumentsExpected" xml:space="preserve">
+ <value>Parametri '{0}' i '{1}' moraju oba biti ili ne smeju oba biti '{2}'.</value>
+ </data>
+ <data name="NoAssociationTypeFoundByLength" xml:space="preserve">
+ <value>Ni jedan prepoznati tip asociranja se ne uklapa sa zahtevanom dužinom {0}.</value>
+ </data>
+ <data name="NoAssociationTypeFoundByName" xml:space="preserve">
+ <value>Ni jedan prepoznati tip asociranja se ne uklapa sa zahtevanim imenom '{0}'.</value>
+ </data>
+ <data name="NoEncryptionSessionRequiresHttps" xml:space="preserve">
+ <value>Osim ako se ne koristi enkripcija transportnog sloja, "no-encryption" NE SME biti korišćen.</value>
+ </data>
+ <data name="NoSessionTypeFound" xml:space="preserve">
+ <value>Diffie-Hellman sesija tipa '{0}' nije pronađena za OpenID {1}.</value>
+ </data>
+ <data name="OpenIdEndpointNotFound" xml:space="preserve">
+ <value>Nijedna OpenID krajnja tačka nije pronađena.</value>
+ </data>
+ <data name="OperationOnlyValidForSetupRequiredState" xml:space="preserve">
+ <value>Ova operacija je jedino dozvoljena kada je IAuthenticationResponse.State == AuthenticationStatus.SetupRequired.</value>
+ </data>
+ <data name="ProviderVersionUnrecognized" xml:space="preserve">
+ <value>Nije moguće utvrditi verziju OpenID protokola implementiranog od strane Provider-a na krajnjoj tački '{0}'.</value>
+ </data>
+ <data name="RealmCausedRedirectUponDiscovery" xml:space="preserve">
+ <value>HTTP zahtev ka URL-u domena ({0}) rezultovao je redirekcijom, koja nije dozvoljena u togu pronalaženja Relying Party.</value>
+ </data>
+ <data name="ReturnToNotUnderRealm" xml:space="preserve">
+ <value>return_to '{0}' nije unutar domena '{1}'.</value>
+ </data>
+ <data name="ReturnToParamDoesNotMatchRequestUrl" xml:space="preserve">
+ <value>{0} parametar ({1}) se ne slaže sa trenutnim URL ({2}) sa kojim je zahtev napravljen.</value>
+ </data>
+ <data name="ReturnToRequiredForResponse" xml:space="preserve">
+ <value>openid.return_to parametar je neophodan u poruci zahteva da bi se konstruisao odgovor, ali ovaj parametar nedostaje.</value>
+ </data>
+ <data name="SignatureDoesNotIncludeMandatoryParts" xml:space="preserve">
+ <value>Sledeći parametri nisu uključeni u potpis a moraju da budu: {0}</value>
+ </data>
+ <data name="SregInvalidBirthdate" xml:space="preserve">
+ <value>Neispravna vrednost za datum rođenja. Mora biti u formi gggg-MM-dd.</value>
+ </data>
+ <data name="TypeMustImplementX" xml:space="preserve">
+ <value>Tip mora implementirati {0}.</value>
+ </data>
+ <data name="UnsolicitedAssertionsNotAllowedFrom1xOPs" xml:space="preserve">
+ <value>Nezahtevani iskazi nisu dozvoljeni od strane 1.0 OpenID Providers.</value>
+ </data>
+ <data name="UserSetupUrlRequiredInImmediateNegativeResponse" xml:space="preserve">
+ <value>openid.user_setup_url parametar je neophodan prilikom slanja negativnih poruka sa iskazima prilikom odgovaranja na zahteve u trenutnom modu.</value>
+ </data>
+ <data name="XriResolutionFailed" xml:space="preserve">
+ <value>XRI razrešivanje neuspešno.</value>
+ </data>
+ <data name="StoreRequiredWhenNoHttpContextAvailable" xml:space="preserve">
+ <value>Tekući HttpContext nije detektovan, tako da {0} instanca mora biti eksplicitno postavljena ili specificirana u .config fajlu. Pozvati preklopljeni konstruktor koji uzima parametar {0}.</value>
+ </data>
+ <data name="AttributeAlreadyAdded" xml:space="preserve">
+ <value>Atribut sa URI tipom '{0}' je već dodat.</value>
+ </data>
+ <data name="AttributeTooManyValues" xml:space="preserve">
+ <value>Samo {0} vrednosti za atribut '{1}' su zahtevane, ali {2} su ponuđene.</value>
+ </data>
+ <data name="UnspecifiedDateTimeKindNotAllowed" xml:space="preserve">
+ <value>Prosleđivanje objekta tipa DateTime čije svojstvo Kind ima vrednost Unspecified nije dozvoljeno.</value>
+ </data>
+ <data name="AssociationOrSessionTypeUnrecognizedOrNotSupported" xml:space="preserve">
+ <value>Zahtevani tip asocijacije '{0}' sa sesijom tipa '{1}' nije prepoznat ili nije podržan od strane ovog Provider-a zbog bezbedonosnih zahteva.</value>
+ </data>
+ <data name="IncompatibleAssociationAndSessionTypes" xml:space="preserve">
+ <value>Provider je zahtevao asocijaciju tipa '{0}' i sesiju tipa '{1}', koje nisu međusobno kompatibilne.</value>
+ </data>
+ <data name="CreateRequestAlreadyCalled" xml:space="preserve">
+ <value>Zahtev za autentifikacijom je već kreiran korišćenjem CreateRequest().</value>
+ </data>
+ <data name="OpenIdTextBoxEmpty" xml:space="preserve">
+ <value>Nijedan OpenID url nije ponuđen.</value>
+ </data>
+ <data name="ClientScriptExtensionPropertyNameCollision" xml:space="preserve">
+ <value>Ekstenzija sa svojstvom ovog imena ('{0}') je već registrovana.</value>
+ </data>
+ <data name="ClientScriptExtensionTypeCollision" xml:space="preserve">
+ <value>Ekstenzija '{0}' je već registrovana.</value>
+ </data>
+ <data name="UnexpectedHttpStatusCode" xml:space="preserve">
+ <value>Neočekivani HTTP statusni kod {0} {1} primljen u direktnom odgovoru.</value>
+ </data>
+ <data name="NotSupportedByAuthenticationSnapshot" xml:space="preserve">
+ <value>Ova operacija nije podržana od strane serijalizovanih odgovora za autentifikaciju. Pokušati ovu operaciju iz LoggedIn handler-a događaja.</value>
+ </data>
+ <data name="NoRelyingPartyEndpointDiscovered" xml:space="preserve">
+ <value>Nijedan XRDS dokument koji sadrži informaciju o OpenID Relying Party krajnjoj tački nije pronadjen u {0}.</value>
+ </data>
+ <data name="AbsoluteUriRequired" xml:space="preserve">
+ <value>Absolutni URI je zahtevan za ovu vrednost.</value>
+ </data>
+ <data name="UnsolicitedAssertionForUnrelatedClaimedIdentifier" xml:space="preserve">
+ <value>Nezahtevani iskaz ne može biti poslat za navedeni identifikator {0} jer ovo nije autorizovani Provider za taj identifikator.</value>
+ </data>
+ <data name="MaximumAuthenticationTimeExpired" xml:space="preserve">
+ <value>Maksimalno dozvoljeno vreme za kompletiranje autentifikacije je isteklo. Molimo pokušajte ponovo.</value>
+ </data>
+ <data name="PrivateRPSecretNotFound" xml:space="preserve">
+ <value>Ne može se pronaći tajna za potpisivanje od strane handle-a '{0}'.</value>
+ </data>
+ <data name="ResponseNotReady" xml:space="preserve">
+ <value>Odgovor nije spreman. Koristiti najpre IsResponseReady za proveru da li je odgovor spreman.</value>
+ </data>
+ <data name="UnsupportedChannelConfiguration" xml:space="preserve">
+ <value>Ovo svojstvo nije dostupno zbog nepoznate konfiguracije kanala.</value>
+ </data>
+ <data name="IdentityAndClaimedIdentifierMustBeBothPresentOrAbsent" xml:space="preserve">
+ <value>openid.identity i openid.claimed_id parametri moraju istovremeno biti prisutna ili istovremeno odsutna u poruci.</value>
+ </data>
+ <data name="ReturnToRequiredForOperation" xml:space="preserve">
+ <value>Svojstvo ReturnTo ne sme biti null da bi se podržala ova operacija.</value>
+ </data>
+ <data name="UnsolicitedAssertionRejectionRequiresNonceStore" xml:space="preserve">
+ <value>Odbijanje nezahtevanih iskaza zahteva skladište jedinstvenih identifikatora i skladište asocijacija.</value>
+ </data>
+ <data name="UnsolicitedAssertionsNotAllowed" xml:space="preserve">
+ <value>Nezahtevani iskazi nisu dozvoljeni od strane ovog Relying Party.</value>
+ </data>
+ <data name="DelegatingIdentifiersNotAllowed" xml:space="preserve">
+ <value>Samo OpenID-jevi izdati direktno od strane njihovog OpenID Provider-a su ovde dozvoljeni.</value>
+ </data>
+ <data name="XriResolutionDisabled" xml:space="preserve">
+ <value>XRI podrška je onemogućena na ovom sajtu.</value>
+ </data>
+ <data name="AssociationStoreRequired" xml:space="preserve">
+ <value>Skladište asocijacija nije dato a zahtevano je za trenutnu konfiguraciju.</value>
+ </data>
+ <data name="UnexpectedEnumPropertyValue" xml:space="preserve">
+ <value>Svojstvo {0} je imalo neočekivanu vrednost {1}.</value>
+ </data>
+ <data name="NoIdentifierSet" xml:space="preserve">
+ <value>Ni jedan identifikator nije podešen.</value>
+ </data>
+ <data name="PropertyValueNotSupported" xml:space="preserve">
+ <value>Ova vrednost svojstva nije podržana od strane ove kontrole.</value>
+ </data>
+ <data name="ArgumentIsPpidIdentifier" xml:space="preserve">
+ <value>Ovo je već PPID Identifier.</value>
+ </data>
+ <data name="RequireSslNotSatisfiedByAssertedClaimedId" xml:space="preserve">
+ <value>Žao nam je. Ovaj sajt jedino prihvata OpenID-jeve koji su HTTPS-bezbedni, a {0} nije bezbedni Identifier.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs b/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
index 85743d6..fd9e8d8 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdXrdsHelper.cs
@@ -44,7 +44,7 @@ namespace DotNetOpenAuth.OpenId {
/// </returns>
internal static IEnumerable<ServiceEndpoint> CreateServiceEndpoints(this XrdsDocument xrds, UriIdentifier claimedIdentifier, UriIdentifier userSuppliedIdentifier) {
var endpoints = new List<ServiceEndpoint>();
- endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(claimedIdentifier));
+ endpoints.AddRange(xrds.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier));
// If any OP Identifier service elements were found, we must not proceed
// to return any Claimed Identifier services.
@@ -84,7 +84,7 @@ namespace DotNetOpenAuth.OpenId {
/// Generates OpenID Providers that can authenticate using directed identity.
/// </summary>
/// <param name="xrds">The XrdsDocument instance to use in this process.</param>
- /// <param name="opIdentifier">The OP Identifier entered (and resolved) by the user.</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) {
Contract.Requires<ArgumentNullException>(xrds != null);
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
index d2efc19..a069f3b 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OpenId.Provider {
using System;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -26,6 +27,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <param name="provider">The provider that received the request.</param>
/// <param name="request">The incoming authentication request message.</param>
+ [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts require it.")]
internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
: base(provider, request) {
Contract.Requires<ArgumentNullException>(provider != null);
diff --git a/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
index 8c1fafc..84ff6da 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/HostProcessedRequest.cs
@@ -105,6 +105,8 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// See OpenID Authentication 2.0 spec section 9.2.1.
/// </remarks>
public RelyingPartyDiscoveryResult IsReturnUrlDiscoverable(OpenIdProvider provider) {
+ Contract.Requires<ArgumentNullException>(provider != null);
+
if (!this.realmDiscoveryResult.HasValue) {
this.realmDiscoveryResult = this.IsReturnUrlDiscoverableCore(provider);
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index b114ac8..a9d197f 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -363,7 +363,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
var discoveredEndpoints = claimedIdentifier.Discover(this.WebRequestHandler);
if (!discoveredEndpoints.Contains(serviceEndpoint)) {
Logger.OpenId.DebugFormat(
- "Failed to send unsolicited assertion for {0} because its discovered services did not include this endpoint. This endpoint: {1}{2} Discovered endpoints: {1}{3}",
+ "Failed to send unsolicited assertion for {0} because its discovered services did not include this endpoint: {1}{2}{1}Discovered endpoints: {1}{3}",
claimedIdentifier,
Environment.NewLine,
serviceEndpoint,
diff --git a/src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs b/src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs
index b65609d..03442dc 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/PrivatePersonalIdentifierProviderBase.cs
@@ -34,7 +34,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// Initializes a new instance of the <see cref="PrivatePersonalIdentifierProviderBase"/> class.
/// </summary>
/// <param name="baseIdentifier">The base URI on which to append the anonymous part.</param>
- public PrivatePersonalIdentifierProviderBase(Uri baseIdentifier) {
+ protected PrivatePersonalIdentifierProviderBase(Uri baseIdentifier) {
Contract.Requires<ArgumentNullException>(baseIdentifier != null);
ErrorUtilities.VerifyArgumentNotNull(baseIdentifier, "baseIdentifier");
@@ -47,6 +47,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// A granularity description for who wide of an audience sees the same generated PPID.
/// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Breaking change")]
public enum AudienceScope {
/// <summary>
/// A unique Identifier is generated for every realm. This is the highest security setting.
@@ -78,6 +79,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// for the authenticating uesr.
/// </summary>
/// <value>The default value is <see cref="AudienceScope.Realm"/>.</value>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Pairwise", Justification = "Meaningful word")]
public AudienceScope PairwiseUnique { get; set; }
/// <summary>
@@ -178,6 +180,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <param name="uriHash">The unique part of the Identifier to append to the common first part.</param>
/// <returns>The full PPID Identifier.</returns>
+ [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "NOT equivalent overload. The recommended one breaks on relative URIs.")]
protected virtual Uri AppendIdentifiers(string uriHash) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(uriHash));
diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs
index 78662ce..770aca0 100644
--- a/src/DotNetOpenAuth/OpenId/Realm.cs
+++ b/src/DotNetOpenAuth/OpenId/Realm.cs
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.OpenId {
/// </remarks>
[Serializable]
[Pure]
- public sealed class Realm {
+ public class Realm {
/// <summary>
/// A regex used to detect a wildcard that is being used in the realm.
/// </summary>
@@ -381,7 +381,7 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// The details of the endpoints if found; or <c>null</c> if no service document was discovered.
/// </returns>
- internal IEnumerable<RelyingPartyEndpointDescription> Discover(IDirectWebRequestHandler requestHandler, bool allowRedirects) {
+ internal virtual IEnumerable<RelyingPartyEndpointDescription> Discover(IDirectWebRequestHandler requestHandler, bool allowRedirects) {
// Attempt YADIS discovery
DiscoveryResult yadisResult = Yadis.Discover(requestHandler, this.UriWithWildcardChangedToWww, false);
if (yadisResult != null) {
@@ -400,6 +400,18 @@ namespace DotNetOpenAuth.OpenId {
return null;
}
+#if CONTRACTS_FULL
+ /// <summary>
+ /// Verifies conditions that should be true for any valid state of this object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")]
+ [ContractInvariantMethod]
+ protected void ObjectInvariant() {
+ Contract.Invariant(this.uri != null);
+ Contract.Invariant(this.uri.AbsoluteUri != null);
+ }
+#endif
+
/// <summary>
/// Calls <see cref="UriBuilder.ToString"/> if the argument is non-null.
/// Otherwise throws <see cref="ArgumentNullException"/>.
@@ -420,18 +432,5 @@ namespace DotNetOpenAuth.OpenId {
// is safe: http://blog.nerdbank.net/2008/04/uriabsoluteuri-and-uritostring-are-not.html
return realmUriBuilder.ToString();
}
-
-#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.uri != null);
- Contract.Invariant(this.uri.AbsoluteUri != null);
- }
-#endif
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index a32ca38..09b0a0c 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -229,6 +229,28 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Makes a key/value pair available when the authentication is completed.
+ /// </summary>
+ /// <param name="key">The parameter name.</param>
+ /// <param name="value">The value of the argument. Must not be null.</param>
+ /// <remarks>
+ /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// security-sensitive data should be stored using this method.</para>
+ /// <para>The value stored here can be retrieved using
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
+ /// <para>Since the data set here is sent in the querystring of the request and some
+ /// servers place limits on the size of a request URL, this data should be kept relatively
+ /// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
+ /// </remarks>
+ public void SetCallbackArgument(string key, string value) {
+ ErrorUtilities.VerifyNonZeroLength(key, "key");
+ ErrorUtilities.VerifyArgumentNotNull(value, "value");
+ ErrorUtilities.VerifyOperation(this.RelyingParty.CanSignCallbackArguments, OpenIdStrings.CallbackArgumentsRequireSecretStore, typeof(IAssociationStore<Uri>).Name, typeof(OpenIdRelyingParty).Name);
+
+ this.returnToArgs[key] = value;
+ }
+
+ /// <summary>
/// Adds an OpenID extension to the request directed at the OpenID provider.
/// </summary>
/// <param name="extension">The initialized extension to add to the request.</param>
@@ -336,11 +358,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// before calling this method.
/// </remarks>
private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<ServiceEndpoint> serviceEndpoints, bool createNewAssociationsAsNeeded) {
- // Can't use code contracts here because this is a yield return method.
+ // DO NOT USE CODE CONTRACTS IN THIS METHOD, since it uses yield return
ErrorUtilities.VerifyArgumentNotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty");
ErrorUtilities.VerifyArgumentNotNull(realm, "realm");
ErrorUtilities.VerifyArgumentNotNull(serviceEndpoints, "serviceEndpoints");
+ ////Contract.Ensures(Contract.Result<IEnumerable<AuthenticationRequest>>() != null);
// If shared associations are required, then we had better have an association store.
ErrorUtilities.VerifyOperation(!relyingParty.SecuritySettings.RequireAssociation || relyingParty.AssociationManager.HasAssociationStore, OpenIdStrings.AssociationStoreRequired);
@@ -468,7 +491,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
request.AssociationHandle = association != null ? association.Handle : null;
request.AddReturnToArguments(this.returnToArgs);
if (this.endpoint.UserSuppliedIdentifier != null) {
- request.AddReturnToArguments(UserSuppliedIdentifierParameterName, this.endpoint.UserSuppliedIdentifier);
+ request.AddReturnToArguments(UserSuppliedIdentifierParameterName, this.endpoint.UserSuppliedIdentifier.OriginalString);
}
foreach (IOpenIdMessageExtension extension in this.extensions) {
request.Extensions.Add(extension);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/Controls.cd b/src/DotNetOpenAuth/OpenId/RelyingParty/Controls.cd
new file mode 100644
index 0000000..f96db36
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/Controls.cd
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1">
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyAjaxControlBase">
+ <Position X="0.5" Y="9.75" Width="3" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>BARAAAAAAAAAAACQAAAAAAAEAAAgAAAAAQAFAAAAAFk=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdRelyingPartyAjaxControlBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdMobileTextBox">
+ <Position X="8.5" Y="5.25" Width="2.5" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AI0JADgFQRQQDAIw4lAYSEIWCAMZhMVlELAASQIAgSI=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdMobileTextBox.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdLogin">
+ <Position X="6.25" Y="1.25" Width="1.75" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <NestedTypes>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdLogin.InPlaceControl" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>OpenId\RelyingParty\OpenIdLogin.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Class>
+ </NestedTypes>
+ <TypeIdentifier>
+ <HashCode>gIMgADAIAQEQIJAYOQBSADiQBgiIECk0jQCggdAp4BQ=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdLogin.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdAjaxTextBox">
+ <Position X="3.75" Y="10" Width="2.25" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>ACBEEbABZzOzAKCYJNOEwM3uSIR5AAOkUFANCQ7DsVs=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdAjaxTextBox.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdButton">
+ <Position X="8.75" Y="1" Width="1.75" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <InheritanceLine Type="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase" ManuallyRouted="true" FixedFromPoint="true" FixedToPoint="true">
+ <Path>
+ <Point X="2.875" Y="0.5" />
+ <Point X="7.194" Y="0.5" />
+ <Point X="7.194" Y="1" />
+ <Point X="8.75" Y="1" />
+ </Path>
+ </InheritanceLine>
+ <TypeIdentifier>
+ <HashCode>BAAEQAAAAAAAAAACAAAgAAAAAIAAAACQABAECABAAAA=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdButton.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox">
+ <Position X="3.5" Y="1.25" Width="2.25" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AIEVQjgBIxYITIARcAAACEc2CIAIlER1CBAQSQoEpCg=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdTextBox.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase">
+ <Position X="0.5" Y="0.5" Width="2.5" />
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <NestedTypes>
+ <Enum Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.LoginSiteNotification" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Enum>
+ <Enum Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.LoginPersistence" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName>
+ </TypeIdentifier>
+ </Enum>
+ <Class Name="DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingPartyControlBase.DuplicateRequestedHostsComparer" Collapsed="true">
+ <TypeIdentifier>
+ <NewMemberFileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</NewMemberFileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ </NestedTypes>
+ <TypeIdentifier>
+ <HashCode>BA0AAsAAQCAwQAJAoFAWwADSAgE5EIEEEbAGSAwAgfI=</HashCode>
+ <FileName>OpenId\RelyingParty\OpenIdRelyingPartyControlBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
index 5e92645..c8039b6 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
@@ -128,6 +128,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
void AddCallbackArguments(string key, string value);
/// <summary>
+ /// Makes a key/value pair available when the authentication is completed.
+ /// </summary>
+ /// <param name="key">The parameter name.</param>
+ /// <param name="value">The value of the argument. Must not be null.</param>
+ /// <remarks>
+ /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// security-sensitive data should be stored using this method.</para>
+ /// <para>The value stored here can be retrieved using
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
+ /// <para>Since the data set here is sent in the querystring of the request and some
+ /// servers place limits on the size of a request URL, this data should be kept relatively
+ /// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
+ /// </remarks>
+ void SetCallbackArgument(string key, string value);
+
+ /// <summary>
/// Adds an OpenID extension to the request directed at the OpenID provider.
/// </summary>
/// <param name="extension">The initialized extension to add to the request.</param>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
index 4d14067..3dcaa35 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequestContract.cs
@@ -70,6 +70,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
throw new NotImplementedException();
}
+ void IAuthenticationRequest.SetCallbackArgument(string key, string value) {
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(key));
+ Contract.Requires<ArgumentNullException>(value != null);
+ throw new NotImplementedException();
+ }
+
void IAuthenticationRequest.AddExtension(IOpenIdMessageExtension extension) {
Contract.Requires<ArgumentNullException>(extension != null);
throw new NotImplementedException();
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index bb06163..3b7b78f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -22,16 +22,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.Diagnostics.Contracts;
using System.Drawing.Design;
using System.Globalization;
- using System.Linq;
using System.Text;
- using System.Text.RegularExpressions;
- using System.Web;
using System.Web.UI;
- using System.Web.UI.WebControls;
using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId.ChannelElements;
- using DotNetOpenAuth.OpenId.Extensions;
- using DotNetOpenAuth.OpenId.Extensions.UI;
/// <summary>
/// An ASP.NET control that provides a minimal text box that is OpenID-aware and uses AJAX for
@@ -39,7 +32,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
[DefaultProperty("Text"), ValidationProperty("Text")]
[ToolboxData("<{0}:OpenIdAjaxTextBox runat=\"server\" />")]
- public sealed class OpenIdAjaxTextBox : WebControl, ICallbackEventHandler {
+ public class OpenIdAjaxTextBox : OpenIdRelyingPartyAjaxControlBase, ICallbackEventHandler, IEditableTextControl, ITextControl, IPostBackDataHandler {
/// <summary>
/// The name of the manifest stream containing the OpenIdAjaxTextBox.js file.
/// </summary>
@@ -73,19 +66,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string ColumnsViewStateKey = "Columns";
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="OnClientAssertionReceived"/> property.
- /// </summary>
- private const string OnClientAssertionReceivedViewStateKey = "OnClientAssertionReceived";
-
- /// <summary>
- /// The viewstate key to use for storing the value of the <see cref="AuthenticationResponse"/> property.
+ /// The viewstate key to use for the <see cref="CssClass"/> property.
/// </summary>
- private const string AuthenticationResponseViewStateKey = "AuthenticationResponse";
+ private const string CssClassViewStateKey = "CssClass";
/// <summary>
- /// The viewstate key to use for storing the value of the a successful authentication.
+ /// The viewstate key to use for storing the value of the <see cref="OnClientAssertionReceived"/> property.
/// </summary>
- private const string AuthDataViewStateKey = "AuthData";
+ private const string OnClientAssertionReceivedViewStateKey = "OnClientAssertionReceived";
/// <summary>
/// The viewstate key to use for storing the value of the <see cref="AuthenticatedAsToolTip"/> property.
@@ -98,16 +86,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string AuthenticationSucceededToolTipViewStateKey = "AuthenticationSucceededToolTip";
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="ReturnToUrl"/> property.
- /// </summary>
- private const string ReturnToUrlViewStateKey = "ReturnToUrl";
-
- /// <summary>
- /// The viewstate key to use for storing the value of the <see cref="RealmUrl"/> property.
- /// </summary>
- private const string RealmUrlViewStateKey = "RealmUrl";
-
- /// <summary>
/// The viewstate key to use for storing the value of the <see cref="LogOnInProgressMessage"/> property.
/// </summary>
private const string LogOnInProgressMessageViewStateKey = "BusyToolTip";
@@ -153,14 +131,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string TimeoutViewStateKey = "Timeout";
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="Text"/> property.
+ /// The viewstate key to use for storing the value of the <see cref="TabIndex"/> property.
/// </summary>
- private const string TextViewStateKey = "Text";
+ private const string TabIndexViewStateKey = "TabIndex";
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="TabIndex"/> property.
+ /// The viewstate key to use for the <see cref="Enabled"/> property.
/// </summary>
- private const string TabIndexViewStateKey = "TabIndex";
+ private const string EnabledViewStateKey = "Enabled";
/// <summary>
/// The viewstate key to use for storing the value of the <see cref="RetryToolTip"/> property.
@@ -182,14 +160,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const int ColumnsDefault = 40;
/// <summary>
- /// The default value for the <see cref="ReturnToUrl"/> property.
- /// </summary>
- private const string ReturnToUrlDefault = "";
-
- /// <summary>
- /// The default value for the <see cref="RealmUrl"/> property.
+ /// The default value for the <see cref="CssClass"/> property.
/// </summary>
- private const string RealmUrlDefault = "~/";
+ private const string CssClassDefault = "openid";
/// <summary>
/// The default value for the <see cref="LogOnInProgressMessage"/> property.
@@ -259,64 +232,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
- /// Backing field for the <see cref="RelyingParty"/> property.
- /// </summary>
- private OpenIdRelyingParty relyingParty;
-
- /// <summary>
- /// Backing field for the <see cref="RelyingPartyNonVerifying"/> property.
- /// </summary>
- private OpenIdRelyingParty relyingPartyNonVerifying;
-
- /// <summary>
- /// Tracks whether the text box should receive input focus when the page is rendered.
- /// </summary>
- private bool focusCalled;
-
- /// <summary>
- /// The authentication response that just came in.
- /// </summary>
- private IAuthenticationResponse authenticationResponse;
-
- /// <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>
- /// Stores the result of an AJAX discovery request while it is waiting
- /// to be picked up by ASP.NET on the way down to the user agent.
- /// </summary>
- private string discoveryResult;
-
#region Events
/// <summary>
- /// Fired when the user has typed in their identifier, discovery was successful
- /// and a login attempt is about to begin.
- /// </summary>
- [Description("Fired when the user has typed in their identifier, discovery was successful and a login attempt is about to begin.")]
- public event EventHandler<OpenIdEventArgs> LoggingIn;
-
- /// <summary>
- /// Fired when a Provider sends back a positive assertion to this control,
- /// but the authentication has not yet been verified.
- /// </summary>
- /// <remarks>
- /// <b>No security critical decisions should be made within event handlers
- /// for this event</b> as the authenticity of the assertion has not been
- /// verified yet. All security related code should go in the event handler
- /// for the <see cref="LoggedIn"/> event.
- /// </remarks>
- [Description("Fired when a Provider sends back a positive assertion to this control, but the authentication has not yet been verified.")]
- public event EventHandler<OpenIdEventArgs> UnconfirmedPositiveAssertion;
-
- /// <summary>
- /// Fired when authentication has completed successfully.
+ /// Fired when the content of the text changes between posts to the server.
/// </summary>
- [Description("Fired when authentication has completed successfully.")]
- public event EventHandler<OpenIdEventArgs> LoggedIn;
+ [Description("Occurs when the content of the text changes between posts to the server."), Category(BehaviorCategory)]
+ public event EventHandler TextChanged;
/// <summary>
/// Gets or sets the client-side script that executes when an authentication
@@ -332,10 +259,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// the authentication has not been verified and may have been spoofed.
/// No security-sensitive operations should take place in this javascript code.
/// The authentication is verified on the server by the time the
- /// <see cref="LoggedIn"/> server-side event fires.</para>
+ /// <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> server-side event fires.</para>
/// </remarks>
[Description("Gets or sets the client-side script that executes when an authentication assertion is received (but before it is verified).")]
- [Bindable(true), DefaultValue(""), Category("Behavior")]
+ [Bindable(true), DefaultValue(""), Category(BehaviorCategory)]
public string OnClientAssertionReceived {
get { return this.ViewState[OnClientAssertionReceivedViewStateKey] as string; }
set { this.ViewState[OnClientAssertionReceivedViewStateKey] = value; }
@@ -346,54 +273,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Properties
/// <summary>
- /// Gets the completed authentication response.
- /// </summary>
- public IAuthenticationResponse AuthenticationResponse {
- get {
- if (this.authenticationResponse == null) {
- // We will either validate a new response and return a live AuthenticationResponse
- // or we will try to deserialize a previous IAuthenticationResponse (snapshot)
- // from viewstate and return that.
- IAuthenticationResponse viewstateResponse = this.ViewState[AuthenticationResponseViewStateKey] as IAuthenticationResponse;
- string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string;
- string formAuthData = this.Page.Request.Form[this.OpenIdAuthDataFormKey];
-
- // First see if there is fresh auth data to be processed into a response.
- if (!string.IsNullOrEmpty(formAuthData) && !string.Equals(viewstateAuthData, formAuthData, StringComparison.Ordinal)) {
- this.ViewState[AuthDataViewStateKey] = formAuthData;
-
- Uri authUri = new Uri(formAuthData);
- HttpRequestInfo clientResponseInfo = new HttpRequestInfo {
- UrlBeforeRewriting = authUri,
- };
-
- this.authenticationResponse = this.RelyingParty.GetResponse(clientResponseInfo);
-
- // Save out the authentication response to viewstate so we can find it on
- // a subsequent postback.
- this.ViewState[AuthenticationResponseViewStateKey] = new AuthenticationResponseSnapshot(this.authenticationResponse);
- } else {
- this.authenticationResponse = viewstateResponse;
- }
- }
- return this.authenticationResponse;
- }
- }
-
- /// <summary>
/// Gets or sets the value in the text field, completely unprocessed or normalized.
/// </summary>
- [Bindable(true), DefaultValue(""), Category("Appearance")]
- [Description("The value in the text field, completely unprocessed or normalized.")]
+ [Bindable(true), DefaultValue(""), Category(AppearanceCategory)]
+ [Description("The content of the text box.")]
public string Text {
- get { return (string)(this.ViewState[TextViewStateKey] ?? string.Empty); }
- set { this.ViewState[TextViewStateKey] = value ?? string.Empty; }
+ get { return this.Identifier != null ? this.Identifier.OriginalString : string.Empty; }
+ set { this.Identifier = value; }
}
/// <summary>
/// Gets or sets the width of the text box in characters.
/// </summary>
- [Bindable(true), Category("Appearance"), DefaultValue(ColumnsDefault)]
+ [Bindable(true), Category(AppearanceCategory), DefaultValue(ColumnsDefault)]
[Description("The width of the text box in characters.")]
public int Columns {
get {
@@ -407,16 +299,38 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets or sets the CSS class assigned to the text box.
+ /// </summary>
+ [Bindable(true), DefaultValue(CssClassDefault), Category(AppearanceCategory)]
+ [Description("The CSS class assigned to the text box.")]
+ public string CssClass {
+ get { return (string)this.ViewState[CssClassViewStateKey]; }
+ set { this.ViewState[CssClassViewStateKey] = value; }
+ }
+
+ /// <summary>
/// Gets or sets the tab index of the text box control. Use 0 to omit an explicit tabindex.
/// </summary>
- [Bindable(true), Category("Behavior"), DefaultValue(TabIndexDefault)]
+ [Bindable(true), Category(BehaviorCategory), DefaultValue(TabIndexDefault)]
[Description("The tab index of the text box control. Use 0 to omit an explicit tabindex.")]
- public override short TabIndex {
+ public virtual short TabIndex {
get { return (short)(this.ViewState[TabIndexViewStateKey] ?? TabIndexDefault); }
set { this.ViewState[TabIndexViewStateKey] = value; }
}
/// <summary>
+ /// Gets or sets a value indicating whether this <see cref="OpenIdTextBox"/> is enabled
+ /// in the browser for editing and will respond to incoming OpenID messages.
+ /// </summary>
+ /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
+ [Bindable(true), DefaultValue(true), Category(BehaviorCategory)]
+ [Description("Whether the control is editable in the browser and will respond to OpenID messages.")]
+ public bool Enabled {
+ get { return (bool)(this.ViewState[EnabledViewStateKey] ?? true); }
+ set { this.ViewState[EnabledViewStateKey] = value; }
+ }
+
+ /// <summary>
/// Gets or sets the HTML name to assign to the text field.
/// </summary>
[Bindable(true), DefaultValue(NameDefault), Category("Misc")]
@@ -435,7 +349,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <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:01"), Category("Behavior")]
+ [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 {
@@ -451,7 +365,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the maximum number of OpenID Providers to simultaneously try to authenticate with.
/// </summary>
- [Browsable(true), DefaultValue(ThrottleDefault), Category("Behavior")]
+ [Browsable(true), DefaultValue(ThrottleDefault), Category(BehaviorCategory)]
[Description("The maximum number of OpenID Providers to simultaneously try to authenticate with.")]
public int Throttle {
get {
@@ -467,7 +381,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.
/// </summary>
- [Bindable(true), DefaultValue(LogOnTextDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(LogOnTextDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.")]
public string LogOnText {
get {
@@ -483,7 +397,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the rool tip text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.
/// </summary>
- [Bindable(true), DefaultValue(LogOnToolTipDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(LogOnToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears on the LOG IN button in cases where immediate (invisible) authentication fails.")]
public string LogOnToolTip {
get { return (string)(this.ViewState[LogOnToolTipViewStateKey] ?? LogOnToolTipDefault); }
@@ -493,7 +407,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the text that appears on the RETRY button in cases where authentication times out.
/// </summary>
- [Bindable(true), DefaultValue(RetryTextDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(RetryTextDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The text that appears on the RETRY button in cases where authentication times out.")]
public string RetryText {
get {
@@ -509,7 +423,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the tool tip text that appears on the RETRY button in cases where authentication times out.
/// </summary>
- [Bindable(true), DefaultValue(RetryToolTipDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(RetryToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears on the RETRY button in cases where authentication times out.")]
public string RetryToolTip {
get { return (string)(this.ViewState[RetryToolTipViewStateKey] ?? RetryToolTipDefault); }
@@ -519,7 +433,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the tool tip text that appears when authentication succeeds.
/// </summary>
- [Bindable(true), DefaultValue(AuthenticationSucceededToolTipDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(AuthenticationSucceededToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears when authentication succeeds.")]
public string AuthenticationSucceededToolTip {
get { return (string)(this.ViewState[AuthenticationSucceededToolTipViewStateKey] ?? AuthenticationSucceededToolTipDefault); }
@@ -529,7 +443,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <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("Appearance")]
+ [Bindable(true), DefaultValue(AuthenticatedAsToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears on the green checkmark when authentication succeeds.")]
public string AuthenticatedAsToolTip {
get { return (string)(this.ViewState[AuthenticatedAsToolTipViewStateKey] ?? AuthenticatedAsToolTipDefault); }
@@ -539,7 +453,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the tool tip text that appears when authentication fails.
/// </summary>
- [Bindable(true), DefaultValue(AuthenticationFailedToolTipDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(AuthenticationFailedToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears when authentication fails.")]
public string AuthenticationFailedToolTip {
get { return (string)(this.ViewState[AuthenticationFailedToolTipViewStateKey] ?? AuthenticationFailedToolTipDefault); }
@@ -549,7 +463,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the tool tip text that appears over the text box when it is discovering and authenticating.
/// </summary>
- [Bindable(true), DefaultValue(BusyToolTipDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(BusyToolTipDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The tool tip text that appears over the text box when it is discovering and authenticating.")]
public string BusyToolTip {
get { return (string)(this.ViewState[BusyToolTipViewStateKey] ?? BusyToolTipDefault); }
@@ -559,7 +473,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the message that is displayed if a postback is about to occur before the identifier has been supplied.
/// </summary>
- [Bindable(true), DefaultValue(IdentifierRequiredMessageDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(IdentifierRequiredMessageDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The message that is displayed if a postback is about to occur before the identifier has been supplied.")]
public string IdentifierRequiredMessage {
get { return (string)(this.ViewState[IdentifierRequiredMessageViewStateKey] ?? IdentifierRequiredMessageDefault); }
@@ -569,230 +483,25 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the message that is displayed if a postback is attempted while login is in process.
/// </summary>
- [Bindable(true), DefaultValue(LogOnInProgressMessageDefault), Localizable(true), Category("Appearance")]
+ [Bindable(true), DefaultValue(LogOnInProgressMessageDefault), Localizable(true), Category(AppearanceCategory)]
[Description("The message that is displayed if a postback is attempted while login is in process.")]
public string LogOnInProgressMessage {
get { return (string)(this.ViewState[LogOnInProgressMessageViewStateKey] ?? LogOnInProgressMessageDefault); }
set { this.ViewState[LogOnInProgressMessageViewStateKey] = value ?? string.Empty; }
}
- /// <summary>
- /// Gets or sets the OpenID <see cref="Realm"/> of the relying party web site.
- /// </summary>
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")]
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using ctor for validation.")]
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Property grid on form designer only supports primitive types.")]
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid on form designer only supports primitive types.")]
- [Bindable(true)]
- [Category("Behavior")]
- [DefaultValue(RealmUrlDefault)]
- [Description("The OpenID Realm of the relying party web site.")]
- [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
- public string RealmUrl {
- get {
- return (string)(this.ViewState[RealmUrlViewStateKey] ?? RealmUrlDefault);
- }
-
- set {
- 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.
- } else {
- // We can't fully test it, but it should start with either ~/ or a protocol.
- if (Regex.IsMatch(value, @"^https?://")) {
- new Uri(value.Replace("*.", "")); // make sure it's fully-qualified, but ignore wildcards
- } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
- // this is valid too
- } else {
- throw new UriFormatException();
- }
- }
- this.ViewState[RealmUrlViewStateKey] = value;
- }
- }
-
- /// <summary>
- /// Gets or sets the OpenID ReturnTo of the relying party web site.
- /// </summary>
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")]
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Property grid on form designer only supports primitive types.")]
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid on form designer only supports primitive types.")]
- [Bindable(true)]
- [Category("Behavior")]
- [DefaultValue(ReturnToUrlDefault)]
- [Description("The OpenID ReturnTo of the relying party web site.")]
- [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
- public string ReturnToUrl {
- get {
- return (string)(this.ViewState[ReturnToUrlViewStateKey] ?? ReturnToUrlDefault);
- }
-
- set {
- if (Page != null && !DesignMode) {
- // Validate new value by trying to construct a Uri based on it.
- new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, Page.ResolveUrl(value)); // throws an exception on failure.
- } else {
- // We can't fully test it, but it should start with either ~/ or a protocol.
- if (Regex.IsMatch(value, @"^https?://")) {
- new Uri(value); // make sure it's fully-qualified, but ignore wildcards
- } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
- // this is valid too
- } else {
- throw new UriFormatException();
- }
- }
- this.ViewState[ReturnToUrlViewStateKey] = value;
- }
- }
-
#endregion
- #region Properties to hide
-
- /// <summary>
- /// Gets or sets the foreground color (typically the color of the text) of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the foreground color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color ForeColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the background color of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the background color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>, which indicates that this property is not set.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color BackColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border color of the Web control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the border color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>, which indicates that this property is not set.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color BorderColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border width of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the border width of a Web server control. The default value is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>, which indicates that this property is not set.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The specified border width is a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit BorderWidth {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border style of the Web server control.
- /// </summary>
- /// <returns>
- /// One of the <see cref="T:System.Web.UI.WebControls.BorderStyle"/> enumeration values. The default is NotSet.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override BorderStyle BorderStyle {
- get { return BorderStyle.None; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets the font properties associated with the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.FontInfo"/> that represents the font properties of the Web server control.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override FontInfo Font {
- get { return null; }
- }
-
- /// <summary>
- /// Gets or sets the height of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the height of the control. The default is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The height was set to a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit Height {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the width of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the width of the control. The default is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The width of the Web server control was set to a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit Width {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the text displayed when the mouse pointer hovers over the Web server control.
- /// </summary>
- /// <returns>
- /// The text displayed when the mouse pointer hovers over the Web server control. The default is <see cref="F:System.String.Empty"/>.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override string ToolTip {
- get { return string.Empty; }
- set { throw new NotSupportedException(); }
- }
-
/// <summary>
- /// Gets or sets the skin to apply to the control.
- /// </summary>
- /// <returns>
- /// The name of the skin to apply to the control. The default is <see cref="F:System.String.Empty"/>.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The skin specified in the <see cref="P:System.Web.UI.WebControls.WebControl.SkinID"/> property does not exist in the theme.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override string SkinID {
- get { return string.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets a value indicating whether themes apply to this control.
+ /// Gets the name of the open id auth data form key.
/// </summary>
- /// <returns>true to use themes; otherwise, false. The default is false.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override bool EnableTheming {
- get { return false; }
- set { throw new NotSupportedException(); }
+ /// <value>
+ /// A concatenation of <see cref="Name"/> and <c>"_openidAuthData"</c>.
+ /// </value>
+ protected override string OpenIdAuthDataFormKey {
+ get { return this.Name + "_openidAuthData"; }
}
- #endregion
-
/// <summary>
/// Gets the default value for the <see cref="Timeout"/> property.
/// </summary>
@@ -808,171 +517,37 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
- /// <summary>
- /// Gets the relying party to use when verification of incoming messages is needed.
- /// </summary>
- private OpenIdRelyingParty RelyingParty {
- get {
- if (this.relyingParty == null) {
- this.relyingParty = CreateRelyingParty(true);
- }
- return this.relyingParty;
- }
- }
-
- /// <summary>
- /// Gets the relying party to use when verification of incoming messages is NOT wanted.
- /// </summary>
- private OpenIdRelyingParty RelyingPartyNonVerifying {
- get {
- if (this.relyingPartyNonVerifying == null) {
- this.relyingPartyNonVerifying = CreateRelyingParty(false);
- }
- return this.relyingPartyNonVerifying;
- }
- }
-
- /// <summary>
- /// Gets the name of the open id auth data form key.
- /// </summary>
- /// <value>A concatenation of <see cref="Name"/> and <c>"_openidAuthData"</c>.</value>
- private string OpenIdAuthDataFormKey {
- get { return this.Name + "_openidAuthData"; }
- }
-
- /// <summary>
- /// Places focus on the text box when the page is rendered on the browser.
- /// </summary>
- public override void Focus() {
- // we don't emit the code to focus the control immediately, in case the control
- // is never rendered to the page because its Visible property is false or that
- // of any of its parent containers.
- this.focusCalled = true;
- }
+ #region IPostBackDataHandler Members
/// <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.
+ /// When implemented by a class, processes postback data for an ASP.NET server control.
/// </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 from the <see cref="UnconfirmedPositiveAssertion"/> event handler.
- /// </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);
+ /// <param name="postDataKey">The key identifier for the control.</param>
+ /// <param name="postCollection">The collection of all incoming name values.</param>
+ /// <returns>
+ /// true if the server control's state changes as a result of the postback; otherwise, false.
+ /// </returns>
+ bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) {
+ return this.LoadPostData(postDataKey, postCollection);
}
- #region ICallbackEventHandler Members
-
/// <summary>
- /// Returns the result of discovery on some Identifier passed to <see cref="ICallbackEventHandler.RaiseCallbackEvent"/>.
+ /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
/// </summary>
- /// <returns>The result of the callback.</returns>
- /// <value>A whitespace delimited list of URLs that can be used to initiate authentication.</value>
- string ICallbackEventHandler.GetCallbackResult() {
- this.Page.Response.ContentType = "text/javascript";
- return this.discoveryResult;
- }
-
- /// <summary>
- /// Performs discovery on some OpenID Identifier. Called directly from the user agent via
- /// AJAX callback mechanisms.
- /// </summary>
- /// <param name="eventArgument">The identifier to perform discovery on.</param>
- void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument) {
- ErrorUtilities.VerifyNonZeroLength(eventArgument, "eventArgument");
- string userSuppliedIdentifier = eventArgument;
-
- Logger.OpenId.InfoFormat("AJAX discovery on {0} requested.", userSuppliedIdentifier);
-
- // 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 {
- List<IAuthenticationRequest> requests = this.CreateRequests(userSuppliedIdentifier, true).Where(req => this.OnLoggingIn(req)).ToList();
- if (requests.Count > 0) {
- discoveryResultBuilder.AppendFormat("claimedIdentifier: {0},", MessagingUtilities.GetSafeJavascriptValue(requests[0].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: new Array(),");
- discoveryResultBuilder.AppendFormat("error: {0}", MessagingUtilities.GetSafeJavascriptValue(OpenIdStrings.OpenIdEndpointNotFound));
- }
- } catch (ProtocolException ex) {
- discoveryResultBuilder.Append("requests: new Array(),");
- discoveryResultBuilder.AppendFormat("error: {0}", MessagingUtilities.GetSafeJavascriptValue(ex.Message));
- }
- discoveryResultBuilder.Append("}");
- this.discoveryResult = discoveryResultBuilder.ToString();
+ void IPostBackDataHandler.RaisePostDataChangedEvent() {
+ this.RaisePostDataChangedEvent();
}
#endregion
/// <summary>
- /// Enables a server control to perform final clean up before it is released from memory.
+ /// Raises the <see cref="E:Load"/> event.
/// </summary>
- public sealed override void Dispose() {
- this.Dispose(true);
- base.Dispose();
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Prepares the control for loading.
- /// </summary>
- /// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
+ /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
- if (this.Page.IsPostBack) {
- // 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 (this.Page.Request.Form[this.Name] != null) {
- this.Text = this.Page.Request.Form[this.Name];
- }
-
- // If there is a response, and it is fresh (live object, not a snapshot object)...
- if (this.AuthenticationResponse != null && this.AuthenticationResponse.Status == AuthenticationStatus.Authenticated) {
- this.OnLoggedIn(this.AuthenticationResponse);
- }
- } else {
- NameValueCollection query = this.RelyingParty.Channel.GetRequestFromContext().GetQueryOrFormFromContext();
- string userSuppliedIdentifier = query["dotnetopenid.userSuppliedIdentifier"];
- if (!string.IsNullOrEmpty(userSuppliedIdentifier) && query["dotnetopenid.phase"] == "2") {
- this.ReportAuthenticationResult();
- }
- }
+ this.Page.RegisterRequiresPostBack(this);
}
/// <summary>
@@ -989,180 +564,82 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Renders the control.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
- protected override void Render(System.Web.UI.HtmlTextWriter writer) {
+ protected override void Render(HtmlTextWriter writer) {
+ base.Render(writer);
+
// We surround the textbox with a span so that the .js file can inject a
// login button within the text box with easy placement.
- writer.WriteBeginTag("span");
- writer.WriteAttribute("class", this.CssClass);
- writer.Write(" style='");
- writer.WriteStyleAttribute("display", "inline-block");
- writer.WriteStyleAttribute("position", "relative");
- writer.WriteStyleAttribute("font-size", "16px");
- writer.Write("'>");
-
- writer.WriteBeginTag("input");
- writer.WriteAttribute("name", this.Name);
- writer.WriteAttribute("id", this.ClientID);
- writer.WriteAttribute("value", this.Text, true);
- writer.WriteAttribute("size", this.Columns.ToString(CultureInfo.InvariantCulture));
+ if (!string.IsNullOrEmpty(this.CssClass)) {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
+ }
+
+ writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "inline-block");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.Position, "relative");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.FontSize, "16px");
+ writer.RenderBeginTag(HtmlTextWriterTag.Span);
+
+ writer.AddAttribute(HtmlTextWriterAttribute.Name, this.Name);
+ writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
+ writer.AddAttribute(HtmlTextWriterAttribute.Size, this.Columns.ToString(CultureInfo.InvariantCulture));
+ if (!string.IsNullOrEmpty(this.Text)) {
+ writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text, true);
+ }
+
if (this.TabIndex > 0) {
- writer.WriteAttribute("tabindex", this.TabIndex.ToString(CultureInfo.InvariantCulture));
+ writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, this.TabIndex.ToString(CultureInfo.InvariantCulture));
}
if (!this.Enabled) {
- writer.WriteAttribute("disabled", "true");
+ writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "true");
}
if (!string.IsNullOrEmpty(this.CssClass)) {
- writer.WriteAttribute("class", this.CssClass);
- }
- writer.Write(" style='");
- writer.WriteStyleAttribute("padding-left", "18px");
- writer.WriteStyleAttribute("border-style", "solid");
- writer.WriteStyleAttribute("border-width", "1px");
- writer.WriteStyleAttribute("border-color", "lightgray");
- writer.Write("'");
- writer.Write(" />");
-
- writer.WriteEndTag("span");
-
- // Emit a hidden field to let the javascript on the user agent know if an
- // authentication has already successfully taken place.
- string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string;
- if (!string.IsNullOrEmpty(viewstateAuthData)) {
- writer.WriteBeginTag("input");
- writer.WriteAttribute("type", "hidden");
- writer.WriteAttribute("name", this.OpenIdAuthDataFormKey);
- writer.WriteAttribute("value", viewstateAuthData, true);
- writer.Write(" />");
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
}
+ writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "18px");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "lightgray");
+ writer.RenderBeginTag(HtmlTextWriterTag.Input);
+ writer.RenderEndTag(); // </input>
+ writer.RenderEndTag(); // </span>
}
/// <summary>
- /// Filters a sequence of OP endpoints so that an OP hostname only appears once in the list.
+ /// When implemented by a class, processes postback data for an ASP.NET server control.
/// </summary>
- /// <param name="requests">The authentication requests against those OP endpoints.</param>
- /// <returns>The filtered list.</returns>
- private static List<IAuthenticationRequest> RemoveDuplicateEndpoints(List<IAuthenticationRequest> requests) {
- var filteredRequests = new List<IAuthenticationRequest>(requests.Count);
- foreach (IAuthenticationRequest request in requests) {
- // 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.
- if (!filteredRequests.Any(req => string.Equals(req.Provider.Uri.Host, request.Provider.Uri.Host, StringComparison.OrdinalIgnoreCase))) {
- filteredRequests.Add(request);
- }
- }
-
- return filteredRequests;
- }
-
- /// <summary>
- /// Creates the relying party.
- /// </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>
- /// <returns>The newly instantiated relying party.</returns>
- private static OpenIdRelyingParty CreateRelyingParty(bool verifySignature) {
- return verifySignature ? new OpenIdRelyingParty() : OpenIdRelyingParty.CreateNonVerifying();
- }
-
- /// <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) {
- if (disposing) {
- if (this.relyingParty != null) {
- this.relyingParty.Dispose();
- this.relyingParty = null;
- }
-
- if (this.relyingPartyNonVerifying != null) {
- this.relyingPartyNonVerifying.Dispose();
- this.relyingPartyNonVerifying = null;
+ /// <param name="postDataKey">The key identifier for the control.</param>
+ /// <param name="postCollection">The collection of all incoming name values.</param>
+ /// <returns>
+ /// 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) {
+ // 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) {
+ Identifier identifier = postCollection[this.Name].Length == 0 ? null : postCollection[this.Name];
+ if (identifier != this.Identifier) {
+ this.Identifier = identifier;
+ return true;
}
}
- }
-
- /// <summary>
- /// Fires the <see cref="LoggingIn"/> event.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns><c>true</c> if the login should proceed; <c>false</c> otherwise.</returns>
- private bool OnLoggingIn(IAuthenticationRequest request) {
- var loggingIn = this.LoggingIn;
- if (loggingIn != null) {
- var args = new OpenIdEventArgs(request);
- loggingIn(this, args);
- return !args.Cancel;
- }
-
- return true;
- }
- /// <summary>
- /// Fires the <see cref="UnconfirmedPositiveAssertion"/> event.
- /// </summary>
- private void OnUnconfirmedPositiveAssertion() {
- var unconfirmedPositiveAssertion = this.UnconfirmedPositiveAssertion;
- if (unconfirmedPositiveAssertion != null) {
- unconfirmedPositiveAssertion(this, null);
- }
+ return false;
}
/// <summary>
- /// Fires the <see cref="LoggedIn"/> event.
+ /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
/// </summary>
- /// <param name="response">The response.</param>
- private void OnLoggedIn(IAuthenticationResponse response) {
- var loggedIn = this.LoggedIn;
- if (loggedIn != null) {
- loggedIn(this, new OpenIdEventArgs(response));
- }
+ protected virtual void RaisePostDataChangedEvent() {
+ this.OnTextChanged();
}
/// <summary>
- /// Invokes a method on a parent frame/window's OpenIdAjaxTextBox,
- /// and closes the calling popup window if applicable.
+ /// Called on a postback when the Text property has changed.
/// </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) {
- this.CallbackUserAgentMethod(methodCall, null);
- }
-
- /// <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>
- /// <param name="preAssignments">An optional list of assignments to make to the input box object before placing the method call.</param>
- private void CallbackUserAgentMethod(string methodCall, string[] preAssignments) {
- Logger.OpenId.InfoFormat("Sending Javascript callback: {0}", methodCall);
- Page.Response.Write(@"<html><body><script language='javascript'>
- var inPopup = !window.frameElement;
- var objSrc = inPopup ? window.opener.waiting_openidBox : window.frameElement.openidBox;
-");
- if (preAssignments != null) {
- foreach (string assignment in preAssignments) {
- Page.Response.Write(string.Format(CultureInfo.InvariantCulture, " objSrc.{0};\n", assignment));
- }
+ protected virtual void OnTextChanged() {
+ EventHandler textChanged = this.TextChanged;
+ if (textChanged != null) {
+ textChanged(this, EventArgs.Empty);
}
-
- // 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>
@@ -1187,9 +664,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
StringBuilder startupScript = new StringBuilder();
startupScript.AppendLine("<script language='javascript'>");
startupScript.AppendFormat("var box = document.getElementsByName('{0}')[0];{1}", this.Name, Environment.NewLine);
- if (this.focusCalled) {
- startupScript.AppendLine("box.focus();");
- }
startupScript.AppendFormat(
CultureInfo.InvariantCulture,
"initAjaxOpenId(box, {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, function({18}, {19}, {20}) {{{21}}});{22}",
@@ -1229,106 +703,5 @@ if (!openidbox.dnoi_internal.onSubmit()) {{ return false; }}
"loginvalidation",
string.Format(CultureInfo.InvariantCulture, htmlFormat, this.Name));
}
-
- /// <summary>
- /// Creates the authentication requests for a given user-supplied Identifier.
- /// </summary>
- /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
- /// <param name="immediate">A value indicating whether the authentication
- /// requests should be initialized for use in invisible iframes for background authentication.</param>
- /// <returns>The list 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> CreateRequests(string userSuppliedIdentifier, bool immediate) {
- var requests = new List<IAuthenticationRequest>();
-
- // Approximate the returnTo (either based on the customize property or the page URL)
- // so we can use it to help with Realm resolution.
- Uri returnToApproximation = this.ReturnToUrl != null ? new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.ReturnToUrl) : this.Page.Request.Url;
-
- // Resolve the trust root, and swap out the scheme and port if necessary to match the
- // return_to URL, since this match is required by OpenId, and the consumer app
- // may be using HTTP at some times and HTTPS at others.
- UriBuilder realm = OpenIdUtilities.GetResolvedRealm(this.Page, this.RealmUrl, this.RelyingParty.Channel.GetRequestFromContext());
- realm.Scheme = returnToApproximation.Scheme;
- realm.Port = returnToApproximation.Port;
-
- // Initiate openid request
- // We use TryParse here to avoid throwing an exception which
- // might slip through our validator control if it is disabled.
- Realm typedRealm = new Realm(realm);
- if (string.IsNullOrEmpty(this.ReturnToUrl)) {
- requests.AddRange(this.RelyingParty.CreateRequests(userSuppliedIdentifier, typedRealm));
- } else {
- // Since the user actually gave us a return_to value,
- // the "approximation" is exactly what we want.
- requests.AddRange(this.RelyingParty.CreateRequests(userSuppliedIdentifier, typedRealm, returnToApproximation));
- }
-
- // 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 = RemoveDuplicateEndpoints(requests);
-
- // Configure each generated request.
- int reqIndex = 0;
- foreach (var req in requests) {
- req.AddCallbackArguments("index", (reqIndex++).ToString(CultureInfo.InvariantCulture));
-
- if (req.Provider.IsExtensionSupported<UIRequest>()) {
- // Inform the OP that we'll be using a popup window.
- 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.AddCallbackArguments("dotnetopenid.popupUISupported", "1");
- }
-
- // If the ReturnToUrl was explicitly set, we'll need to reset our first parameter
- if (string.IsNullOrEmpty(HttpUtility.ParseQueryString(req.ReturnToUrl.Query)["dotnetopenid.userSuppliedIdentifier"])) {
- req.AddCallbackArguments("dotnetopenid.userSuppliedIdentifier", userSuppliedIdentifier);
- }
-
- // 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.AddCallbackArguments("dotnetopenid.op_endpoint", req.Provider.Uri.AbsoluteUri);
- req.AddCallbackArguments("dotnetopenid.claimed_id", (string)req.ClaimedIdentifier ?? string.Empty);
- req.AddCallbackArguments("dotnetopenid.phase", "2");
- if (immediate) {
- req.Mode = AuthenticationRequestMode.Immediate;
- ((AuthenticationRequest)req).AssociationPreference = AssociationPreference.IfAlreadyEstablished;
- }
- }
-
- return requests;
- }
-
- /// <summary>
- /// Notifies the user agent via an AJAX response of a completed authentication attempt.
- /// </summary>
- private void ReportAuthenticationResult() {
- Logger.OpenId.InfoFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
- List<string> assignments = new List<string>();
-
- var authResponse = this.RelyingPartyNonVerifying.GetResponse();
- if (authResponse.Status == AuthenticationStatus.Authenticated) {
- this.OnUnconfirmedPositiveAssertion();
- 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)) {
- js = "null";
- }
- assignments.Add(pair.Value + " = " + js);
- }
- }
-
- this.CallbackUserAgentMethod("dnoi_internal.processAuthorizationResult(document.URL)", assignments.ToArray());
- }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.js
index 1078003..531748a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.js
@@ -4,46 +4,12 @@
// </copyright>
//-----------------------------------------------------------------------
-// Options that can be set on the host page:
-//window.openid_visible_iframe = true; // causes the hidden iframe to show up
-//window.openid_trace = true; // causes lots of messages
-
-function trace(msg) {
- if (window.openid_trace) {
- if (!window.tracediv) {
- window.tracediv = document.createElement("ol");
- document.body.appendChild(window.tracediv);
- }
- var el = document.createElement("li");
- el.appendChild(document.createTextNode(msg));
- window.tracediv.appendChild(el);
- //alert(msg);
- }
-}
-
-/// <summary>Removes a given element from the array.</summary>
-/// <returns>True if the element was in the array, or false if it was not found.</returns>
-Array.prototype.remove = function(element) {
- function elementToRemoveLast(a, b) {
- if (a == element) { return 1; }
- if (b == element) { return -1; }
- return 0;
- }
- this.sort(elementToRemoveLast);
- if (this[this.length - 1] == element) {
- this.pop();
- return true;
- } else {
- return false;
- }
-};
-
function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url, success_icon_url, failure_icon_url,
throttle, timeout, assertionReceivedCode,
loginButtonText, loginButtonToolTip, retryButtonText, retryButtonToolTip, busyToolTip,
identifierRequiredMessage, loginInProgressMessage,
authenticatedByToolTip, authenticatedAsToolTip, authenticationFailedToolTip,
- discoverCallback, discoveryFailedCallback) {
+ discoverCallback/*removeme*/, discoveryFailedCallback) {
box.dnoi_internal = new Object();
if (assertionReceivedCode) {
box.dnoi_internal.onauthenticated = function(sender, e) { eval(assertionReceivedCode); }
@@ -51,79 +17,8 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
box.dnoi_internal.originalBackground = box.style.background;
box.timeout = timeout;
- box.dnoi_internal.discoverIdentifier = discoverCallback;
- box.dnoi_internal.authenticationRequests = new Array();
-
- // The possible authentication results
- var authSuccess = new Object();
- var authRefused = new Object();
- var timedOut = new Object();
-
- function FrameManager(maxFrames) {
- this.queuedWork = new Array();
- this.frames = new Array();
- this.maxFrames = maxFrames;
-
- /// <summary>Called to queue up some work that will use an iframe as soon as it is available.</summary>
- /// <param name="job">
- /// A delegate that must return the url to point to iframe to.
- /// Its first parameter is the iframe created to service the request.
- /// It will only be called when the work actually begins.
- /// </param>
- this.enqueueWork = function(job) {
- // Assign an iframe to this task immediately if there is one available.
- if (this.frames.length < this.maxFrames) {
- this.createIFrame(job);
- } else {
- this.queuedWork.unshift(job);
- }
- };
-
- /// <summary>Clears the job queue and immediately closes all iframes.</summary>
- this.cancelAllWork = function() {
- trace('Canceling all open and pending iframes.');
- while (this.queuedWork.pop());
- this.closeFrames();
- };
-
- /// <summary>An event fired when a frame is closing.</summary>
- this.onJobCompleted = function() {
- // If there is a job in the queue, go ahead and start it up.
- if (job = this.queuedWork.pop()) {
- this.createIFrame(job);
- }
- }
- this.createIFrame = function(job) {
- var iframe = document.createElement("iframe");
- if (!window.openid_visible_iframe) {
- iframe.setAttribute("width", 0);
- iframe.setAttribute("height", 0);
- iframe.setAttribute("style", "display: none");
- }
- iframe.setAttribute("src", job(iframe));
- iframe.openidBox = box;
- box.parentNode.insertBefore(iframe, box);
- this.frames.push(iframe);
- return iframe;
- };
- this.closeFrames = function() {
- if (this.frames.length == 0) { return false; }
- for (var i = 0; i < this.frames.length; i++) {
- if (this.frames[i].parentNode) { this.frames[i].parentNode.removeChild(this.frames[i]); }
- }
- while (this.frames.length > 0) { this.frames.pop(); }
- return true;
- };
- this.closeFrame = function(frame) {
- if (frame.parentNode) { frame.parentNode.removeChild(frame); }
- var removed = this.frames.remove(frame);
- this.onJobCompleted();
- return removed;
- };
- }
-
- box.dnoi_internal.authenticationIFrames = new FrameManager(throttle);
+ box.dnoi_internal.authenticationIFrames = new window.dnoa_internal.FrameManager(throttle);
box.dnoi_internal.constructButton = function(text, tooltip, onclick) {
var button = document.createElement('input');
@@ -199,14 +94,14 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
};
box.dnoi_internal.loginButton = box.dnoi_internal.constructButton(loginButtonText, loginButtonToolTip, function() {
- var discoveryInfo = box.dnoi_internal.authenticationRequests[box.lastDiscoveredIdentifier];
+ var discoveryInfo = window.dnoa_internal.discoveryResults[box.lastDiscoveredIdentifier];
if (discoveryInfo == null) {
trace('Ooops! Somehow the login button click event was invoked, but no openid discovery information for ' + box.lastDiscoveredIdentifier + ' is available.');
return;
}
// The login button always sends a setup message to the first OP.
var selectedProvider = discoveryInfo[0];
- selectedProvider.trySetup();
+ selectedProvider.loginPopup(box.dnoi_internal.onAuthSuccess, box.dnoi_internal.onAuthFailed);
return false;
});
box.dnoi_internal.retryButton = box.dnoi_internal.constructButton(retryButtonText, retryButtonToolTip, function() {
@@ -250,8 +145,9 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
box.dnoi_internal.op_logo.style.visibility = 'visible';
box.dnoi_internal.op_logo.title = box.dnoi_internal.op_logo.originalTitle.replace('{0}', authenticatedBy.getHost());
}
- trace("OP icon size: " + box.dnoi_internal.op_logo.fileSize);
- if (opLogo == null || box.dnoi_internal.op_logo.fileSize == -1 /*IE*/ || box.dnoi_internal.op_logo.fileSize === undefined /* FF */) {
+ //trace("OP icon size: " + box.dnoi_internal.op_logo.fileSize);
+ // The filesize check just doesn't seem to work any more.
+ if (opLogo == null) {// || box.dnoi_internal.op_logo.fileSize == -1 /*IE*/ || box.dnoi_internal.op_logo.fileSize === undefined /* FF */) {
trace('recovering from missing OP icon');
box.dnoi_internal.op_logo.style.visibility = 'hidden';
box.dnoi_internal.openid_logo.style.visibility = 'visible';
@@ -291,20 +187,20 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
}
box.dnoi_internal.isBusy = function() {
- var lastDiscovery = box.dnoi_internal.authenticationRequests[box.lastDiscoveredIdentifier];
+ var lastDiscovery = window.dnoa_internal.discoveryResults[box.lastDiscoveredIdentifier];
return box.dnoi_internal.state == 'discovering' ||
(lastDiscovery && lastDiscovery.busy());
};
box.dnoi_internal.canAttemptLogin = function() {
if (box.value.length == 0) return false;
- if (box.dnoi_internal.authenticationRequests[box.value] == null) return false;
+ if (window.dnoa_internal.discoveryResults[box.value] == null) return false;
if (box.dnoi_internal.state == 'failed') return false;
return true;
};
box.dnoi_internal.getUserSuppliedIdentifierResults = function() {
- return box.dnoi_internal.authenticationRequests[box.value];
+ return window.dnoa_internal.discoveryResults[box.value];
}
box.dnoi_internal.isAuthenticated = function() {
@@ -316,7 +212,7 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
var hiddenField = findOrCreateHiddenField();
if (box.dnoi_internal.isAuthenticated()) {
// stick the result in a hidden field so the RP can verify it
- hiddenField.setAttribute("value", box.dnoi_internal.authenticationRequests[box.value].successAuthData);
+ hiddenField.setAttribute("value", window.dnoa_internal.discoveryResults[box.value].successAuthData);
} else {
hiddenField.setAttribute("value", '');
if (box.dnoi_internal.isBusy()) {
@@ -380,180 +276,26 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
/// <summary>
/// Returns the URL of the authenticating OP's logo so it can be displayed to the user.
/// </summary>
- box.dnoi_internal.deriveOPFavIcon = function() {
- var response = box.dnoi_internal.getUserSuppliedIdentifierResults().successAuthData;
- if (!response || response.length == 0) return;
- var authResult = new Uri(response);
- var opUri;
- if (authResult.getQueryArgValue("openid.op_endpoint")) {
- opUri = new Uri(authResult.getQueryArgValue("openid.op_endpoint"));
- } if (authResult.getQueryArgValue("dotnetopenid.op_endpoint")) {
- opUri = new Uri(authResult.getQueryArgValue("dotnetopenid.op_endpoint"));
- } else if (authResult.getQueryArgValue("openid.user_setup_url")) {
- opUri = new Uri(authResult.getQueryArgValue("openid.user_setup_url"));
- } else return null;
- var favicon = opUri.getAuthority() + "/favicon.ico";
- return favicon;
- };
-
- box.dnoi_internal.createDiscoveryInfo = function(discoveryInfo, identifier) {
- this.identifier = identifier;
- // The claimed identifier may be null if the user provided an OP Identifier.
- this.claimedIdentifier = discoveryInfo.claimedIdentifier;
- trace('Discovered claimed identifier: ' + this.claimedIdentifier);
-
- // Add extra tracking bits and behaviors.
- this.findByEndpoint = function(opEndpoint) {
- for (var i = 0; i < this.length; i++) {
- if (this[i].endpoint == opEndpoint) {
- return this[i];
- }
+ /// <param name="opUri">The OP Endpoint, if known.</param>
+ box.dnoi_internal.deriveOPFavIcon = function(opUri) {
+ if (!opUri) {
+ var response = box.dnoi_internal.getUserSuppliedIdentifierResults().successAuthData;
+ if (!response || response.length == 0) {
+ trace('No favicon because no successAuthData.');
+ return;
}
- };
- this.findSuccessfulRequest = function() {
- for (var i = 0; i < this.length; i++) {
- if (this[i].result == authSuccess) {
- return this[i];
- }
- }
- };
- this.busy = function() {
- for (var i = 0; i < this.length; i++) {
- if (this[i].busy()) {
- return true;
- }
- }
- };
- this.abortAll = function() {
- // Abort all other asynchronous authentication attempts that may be in progress.
- box.dnoi_internal.authenticationIFrames.cancelAllWork();
- for (var i = 0; i < this.length; i++) {
- this[i].abort();
- }
- };
- this.tryImmediate = function() {
- if (this.length > 0) {
- for (var i = 0; i < this.length; i++) {
- box.dnoi_internal.authenticationIFrames.enqueueWork(this[i].tryImmediate);
- }
- } else {
- box.dnoi_internal.discoveryFailed(null, this.identifier);
- }
- };
-
- this.length = discoveryInfo.requests.length;
- for (var i = 0; i < discoveryInfo.requests.length; i++) {
- this[i] = new box.dnoi_internal.createTrackingRequest(discoveryInfo.requests[i], identifier);
- }
- };
-
- box.dnoi_internal.createTrackingRequest = function(requestInfo, identifier) {
- // It's possible during a postback that discovered request URLs are not available.
- this.immediate = requestInfo.immediate ? new Uri(requestInfo.immediate) : null;
- this.setup = requestInfo.setup ? new Uri(requestInfo.setup) : null;
- this.endpoint = new Uri(requestInfo.endpoint);
- this.identifier = identifier;
- var self = this; // closure so that delegates have the right instance
-
- this.host = self.endpoint.getHost();
-
- this.getDiscoveryInfo = function() {
- return box.dnoi_internal.authenticationRequests[self.identifier];
+ var authResult = new window.dnoa_internal.Uri(response);
+ if (authResult.getQueryArgValue("openid.op_endpoint")) {
+ opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("openid.op_endpoint"));
+ } else if (authResult.getQueryArgValue("dnoa.op_endpoint")) {
+ opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("dnoa.op_endpoint"));
+ } else if (authResult.getQueryArgValue("openid.user_setup_url")) {
+ opUri = new window.dnoa_internal.Uri(authResult.getQueryArgValue("openid.user_setup_url"));
+ } else return null;
}
-
- this.busy = function() {
- return self.iframe != null || self.popup != null;
- };
-
- this.completeAttempt = function() {
- if (!self.busy()) return false;
- if (self.iframe) {
- trace('iframe hosting ' + self.endpoint + ' now CLOSING.');
- box.dnoi_internal.authenticationIFrames.closeFrame(self.iframe);
- self.iframe = null;
- }
- if (self.popup) {
- self.popup.close();
- self.popup = null;
- }
- if (self.timeout) {
- window.clearTimeout(self.timeout);
- self.timeout = null;
- }
-
- if (!self.getDiscoveryInfo().busy() && self.getDiscoveryInfo().findSuccessfulRequest() == null) {
- trace('No asynchronous authentication attempt is in progress. Display setup view.');
- // visual cue that auth failed
- box.dnoi_internal.setVisualCue('setup');
- }
-
- return true;
- };
-
- this.authenticationTimedOut = function() {
- if (self.completeAttempt()) {
- trace(self.host + " timed out");
- self.result = timedOut;
- }
- };
- this.authSuccess = function(authUri) {
- if (self.completeAttempt()) {
- trace(self.host + " authenticated!");
- self.result = authSuccess;
- self.response = authUri;
- box.dnoi_internal.authenticationRequests[self.identifier].abortAll();
- }
- };
- this.authFailed = function() {
- if (self.completeAttempt()) {
- //trace(self.host + " failed authentication");
- self.result = authRefused;
- }
- };
- this.abort = function() {
- if (self.completeAttempt()) {
- trace(self.host + " aborted");
- // leave the result as whatever it was before.
- }
- };
-
- this.tryImmediate = function(iframe) {
- self.abort(); // ensure no concurrent attempts
- self.timeout = setTimeout(function() { self.authenticationTimedOut(); }, box.timeout);
- trace('iframe hosting ' + self.endpoint + ' now OPENING.');
- self.iframe = iframe;
- //trace('initiating auth attempt with: ' + self.immediate);
- return self.immediate.toString();
- };
- this.trySetup = function() {
- self.abort(); // ensure no concurrent attempts
- window.waiting_openidBox = box;
- var width = 800;
- var height = 600;
- if (self.setup.getQueryArgValue("openid.return_to").indexOf("dotnetopenid.popupUISupported") >= 0) {
- width = 450;
- height = 500;
- }
-
- var left = (screen.width - width) / 2;
- var top = (screen.height - height) / 2;
- self.popup = window.open(self.setup, 'opLogin', 'status=0,toolbar=0,location=1,resizable=1,scrollbars=1,left=' + left + ',top=' + top + ',width=' + width + ',height=' + height);
-
- // If the OP supports the UI extension it MAY close its own window
- // for a negative assertion. We must be able to recover from that scenario.
- var localSelf = self;
- self.popupCloseChecker = window.setInterval(function() {
- if (localSelf.popup && localSelf.popup.closed) {
- // So the user canceled and the window closed.
- // It turns out we hae nothing special to do.
- // If we were graying out the entire page while the child window was up,
- // we would probably revert that here.
- trace('User or OP canceled by closing the window.');
- window.clearInterval(localSelf.popupCloseChecker);
- localSelf.popup = null;
- }
- }, 250);
- };
+ var favicon = opUri.getAuthority() + "/favicon.ico";
+ trace('Guessing favicon location of: ' + favicon);
+ return favicon;
};
/*****************************************
@@ -565,7 +307,8 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
box.dnoi_internal.authenticationIFrames.closeFrames();
box.dnoi_internal.setVisualCue('discovering');
box.lastDiscoveredIdentifier = identifier;
- box.dnoi_internal.discoverIdentifier(identifier, box.dnoi_internal.discoveryResult, box.dnoi_internal.discoveryFailed);
+ var openid = new window.OpenIdIdentifier(identifier);
+ openid.discover(box.dnoi_internal.discoverySuccess, box.dnoi_internal.discoveryFailed);
};
/// <summary>Callback that is invoked when discovery fails.</summary>
@@ -577,95 +320,65 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
/// <summary>Callback that is invoked when discovery results are available.</summary>
/// <param name="discoveryResult">The JSON object containing the OpenID auth requests.</param>
/// <param name="identifier">The identifier that discovery was performed on.</param>
- box.dnoi_internal.discoveryResult = function(discoveryResult, identifier) {
- // Deserialize the JSON object and store the result if it was a successful discovery.
- discoveryResult = eval('(' + discoveryResult + ')');
- // Store the discovery results and added behavior for later use.
- box.dnoi_internal.authenticationRequests[identifier] = discoveryBehavior = new box.dnoi_internal.createDiscoveryInfo(discoveryResult, identifier);
-
+ box.dnoi_internal.discoverySuccess = function(discoveryResult) {
// Only act on the discovery event if we're still interested in the result.
// If the user already changed the identifier since discovery was initiated,
// we aren't interested in it any more.
- if (identifier == box.lastDiscoveredIdentifier) {
- discoveryBehavior.tryImmediate();
+ if (discoveryResult.userSuppliedIdentifier === box.lastDiscoveredIdentifier) {
+ // Start pre-fetching the OP favicons
+ for (var i = 0; i < discoveryResult.length; i++) {
+ var favicon = box.dnoi_internal.deriveOPFavIcon(discoveryResult[i].endpoint);
+ if (favicon) {
+ trace('Prefetching ' + favicon);
+ box.dnoi_internal.prefetchImage(favicon);
+ }
+ }
+ discoveryResult.loginBackground(
+ box.dnoi_internal.authenticationIFrames,
+ box.dnoi_internal.onAuthSuccess,
+ box.dnoi_internal.onAuthFailed,
+ box.dnoi_internal.lastAuthenticationFailed,
+ box.timeout);
}
}
- /// <summary>Invoked by RP web server when an authentication has completed.</summary>
- /// <remarks>The duty of this method is to distribute the notification to the appropriate tracking object.</remarks>
- box.dnoi_internal.processAuthorizationResult = function(resultUrl) {
- self.waiting_openidBox = null;
- //trace('processAuthorizationResult ' + resultUrl);
- var resultUri = new Uri(resultUrl);
+ box.dnoi_internal.lastAuthenticationFailed = function() {
+ trace('No asynchronous authentication attempt is in progress. Display setup view.');
+ // visual cue that auth failed
+ box.dnoi_internal.setVisualCue('setup');
+ };
- // Find the tracking object responsible for this request.
- var discoveryInfo = box.dnoi_internal.authenticationRequests[resultUri.getQueryArgValue('dotnetopenid.userSuppliedIdentifier')];
- if (discoveryInfo == null) {
- trace('processAuthorizationResult called but no userSuppliedIdentifier parameter was found. Exiting function.');
- return;
+ box.dnoi_internal.onAuthSuccess = function(discoveryResult, respondingEndpoint) {
+ // visual cue that auth was successful
+ var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(discoveryResult.successAuthData);
+ box.dnoi_internal.claimedIdentifier = parsedPositiveAssertion.claimedIdentifier;
+ box.dnoi_internal.setVisualCue('authenticated', parsedPositiveAssertion.endpoint, parsedPositiveAssertion.claimedIdentifier);
+ if (box.dnoi_internal.onauthenticated) {
+ box.dnoi_internal.onauthenticated(box);
}
- var opEndpoint = resultUri.getQueryArgValue("openid.op_endpoint") ? resultUri.getQueryArgValue("openid.op_endpoint") : resultUri.getQueryArgValue("dotnetopenid.op_endpoint");
- var tracker = discoveryInfo.findByEndpoint(opEndpoint);
- //trace('Auth result for ' + tracker.host + ' received:\n' + resultUrl);
-
- if (isAuthSuccessful(resultUri)) {
- tracker.authSuccess(resultUri);
-
- discoveryInfo.successAuthData = resultUrl;
- var claimed_id = resultUri.getQueryArgValue("openid.claimed_id");
- if (claimed_id && claimed_id != discoveryInfo.claimedIdentifier) {
- discoveryInfo.claimedIdentifier = resultUri.getQueryArgValue("openid.claimed_id");
- trace('Authenticated as ' + claimed_id);
- }
- // visual cue that auth was successful
- box.dnoi_internal.claimedIdentifier = discoveryInfo.claimedIdentifier;
- box.dnoi_internal.setVisualCue('authenticated', tracker.endpoint, discoveryInfo.claimedIdentifier);
- if (box.dnoi_internal.onauthenticated) {
- box.dnoi_internal.onauthenticated(box);
- }
- if (box.dnoi_internal.submitPending) {
- // We submit the form BEFORE resetting the submitPending so
- // the submit handler knows we've already tried this route.
- if (box.dnoi_internal.submitPending == true) {
- box.parentForm.submit();
- } else {
- box.dnoi_internal.submitPending.click();
- }
+ if (box.dnoi_internal.submitPending) {
+ // We submit the form BEFORE resetting the submitPending so
+ // the submit handler knows we've already tried this route.
+ if (box.dnoi_internal.submitPending == true) {
+ box.parentForm.submit();
+ } else {
+ box.dnoi_internal.submitPending.click();
}
- } else {
- tracker.authFailed();
- }
-
- box.dnoi_internal.submitPending = null;
- };
- function isAuthSuccessful(resultUri) {
- if (isOpenID2Response(resultUri)) {
- return resultUri.getQueryArgValue("openid.mode") == "id_res";
- } else {
- return resultUri.getQueryArgValue("openid.mode") == "id_res" && !resultUri.containsQueryArg("openid.user_setup_url");
+ box.dnoi_internal.submitPending = null;
}
};
- function isOpenID2Response(resultUri) {
- return resultUri.containsQueryArg("openid.ns");
+ box.dnoi_internal.onAuthFailed = function() {
+ box.dnoi_internal.submitPending = null;
};
-
+
box.onblur = function(event) {
- var discoveryInfo = box.dnoi_internal.authenticationRequests[box.value];
- if (discoveryInfo == null) {
- if (box.value.length > 0) {
- box.dnoi_internal.performDiscovery(box.value);
- } else {
- box.dnoi_internal.setVisualCue();
- }
+ if (box.value.length > 0) {
+ box.dnoi_internal.performDiscovery(box.value);
} else {
- if ((priorSuccess = discoveryInfo.findSuccessfulRequest())) {
- box.dnoi_internal.setVisualCue('authenticated', priorSuccess.endpoint, discoveryInfo.claimedIdentifier);
- } else {
- discoveryInfo.tryImmediate();
- }
+ box.dnoi_internal.setVisualCue();
}
return true;
};
@@ -677,101 +390,5 @@ function initAjaxOpenId(box, openid_logo_url, dotnetopenid_logo_url, spinner_url
box.getClaimedIdentifier = function() { return box.dnoi_internal.claimedIdentifier; };
// Restore a previously achieved state (from pre-postback) if it is given.
- var oldAuth = findOrCreateHiddenField().value;
- if (oldAuth.length > 0) {
- var oldAuthResult = new Uri(oldAuth);
- // The control ensures that we ALWAYS have an OpenID 2.0-style claimed_id attribute, even against
- // 1.0 Providers via the return_to URL mechanism.
- var claimedId = oldAuthResult.getQueryArgValue("dotnetopenid.claimed_id");
- var endpoint = oldAuthResult.getQueryArgValue("dotnetopenid.op_endpoint");
- // We weren't given a full discovery history, but we can spoof this much from the
- // authentication assertion.
- box.dnoi_internal.authenticationRequests[box.value] = new box.dnoi_internal.createDiscoveryInfo({
- claimedIdentifier: claimedId,
- requests: [{ endpoint: endpoint }]
- }, box.value);
-
- box.dnoi_internal.processAuthorizationResult(oldAuthResult.toString());
- }
+ window.dnoa_internal.deserializePreviousAuthentication(findOrCreateHiddenField().value, box.dnoi_internal.onAuthSuccess);
}
-
-function Uri(url) {
- this.originalUri = url;
-
- this.toString = function() {
- return this.originalUri;
- };
-
- this.getAuthority = function() {
- var authority = this.getScheme() + "://" + this.getHost();
- return authority;
- }
-
- this.getHost = function() {
- var hostStartIdx = this.originalUri.indexOf("://") + 3;
- var hostEndIndex = this.originalUri.indexOf("/", hostStartIdx);
- if (hostEndIndex < 0) hostEndIndex = this.originalUri.length;
- var host = this.originalUri.substr(hostStartIdx, hostEndIndex - hostStartIdx);
- return host;
- }
-
- this.getScheme = function() {
- var schemeStartIdx = this.indexOf("://");
- return this.originalUri.substr(this.originalUri, schemeStartIdx);
- }
-
- this.trimFragment = function() {
- var hashmark = this.originalUri.indexOf('#');
- if (hashmark >= 0) {
- return new Uri(this.originalUri.substr(0, hashmark));
- }
- return this;
- };
-
- this.appendQueryVariable = function(name, value) {
- var pair = encodeURI(name) + "=" + encodeURI(value);
- if (this.originalUri.indexOf('?') >= 0) {
- this.originalUri = this.originalUri + "&" + pair;
- } else {
- this.originalUri = this.originalUri + "?" + pair;
- }
- };
-
- function KeyValuePair(key, value) {
- this.key = key;
- this.value = value;
- };
-
- this.Pairs = new Array();
-
- var queryBeginsAt = this.originalUri.indexOf('?');
- if (queryBeginsAt >= 0) {
- this.queryString = url.substr(queryBeginsAt + 1);
- var queryStringPairs = this.queryString.split('&');
-
- for (var i = 0; i < queryStringPairs.length; i++) {
- var equalsAt = queryStringPairs[i].indexOf('=');
- left = (equalsAt >= 0) ? queryStringPairs[i].substring(0, equalsAt) : null;
- right = (equalsAt >= 0) ? queryStringPairs[i].substring(equalsAt + 1) : queryStringPairs[i];
- this.Pairs.push(new KeyValuePair(unescape(left), unescape(right)));
- }
- };
-
- this.getQueryArgValue = function(key) {
- for (var i = 0; i < this.Pairs.length; i++) {
- if (this.Pairs[i].key == key) {
- return this.Pairs[i].value;
- }
- }
- };
-
- this.containsQueryArg = function(key) {
- return this.getQueryArgValue(key);
- };
-
- this.indexOf = function(args) {
- return this.originalUri.indexOf(args);
- };
-
- return this;
-};
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
index b367944..8b517b4 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
@@ -92,6 +92,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets or sets a value indicating whether to pre-discover the identifier so
/// the user agent has an immediate redirect.
/// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Precreate", Justification = "Breaking change to public API")]
[Bindable(true), Category(OpenIdCategory), DefaultValue(PrecreateRequestDefault)]
[Description("Whether to pre-discover the identifier so the user agent has an immediate redirect.")]
public bool PrecreateRequest {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
index fe1ce67..b0dce61 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
@@ -8,10 +8,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Globalization;
+ using System.Linq;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
+ using DotNetOpenAuth.Messaging;
/// <summary>
/// An ASP.NET control providing a complete OpenID login experience.
@@ -105,7 +108,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// The default value for the <see cref="RememberMe"/> property.
/// </summary>
- private const bool RememberMeDefault = UsePersistentCookieDefault;
+ private const bool RememberMeDefault = false;
/// <summary>
/// The default value for the <see cref="UriValidatorEnabled"/> property.
@@ -226,14 +229,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Events
/// <summary>
- /// Fired after the user clicks the log in button, but before the authentication
- /// process begins. Offers a chance for the web application to disallow based on
- /// OpenID URL before redirecting the user to the OpenID Provider.
- /// </summary>
- [Description("Fired after the user clicks the log in button, but before the authentication process begins. Offers a chance for the web application to disallow based on OpenID URL before redirecting the user to the OpenID Provider.")]
- public event EventHandler<OpenIdEventArgs> LoggingIn;
-
- /// <summary>
/// Fired when the Remember Me checkbox is changed by the user.
/// </summary>
[Description("Fires when the Remember Me checkbox is changed by the user.")]
@@ -242,6 +237,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
#region Properties
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Web.UI.ControlCollection"/> object that represents the child controls for a specified server control in the UI hierarchy.
+ /// </summary>
+ /// <returns>
+ /// The collection of child controls for the specified server control.
+ /// </returns>
+ public override ControlCollection Controls {
+ get {
+ this.EnsureChildControls();
+ return base.Controls;
+ }
+ }
+
/// <summary>
/// Gets or sets the caption that appears before the text box.
/// </summary>
@@ -251,8 +260,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The caption that appears before the text box.")]
public string LabelText {
- get { return this.label.InnerText; }
- set { this.label.InnerText = value; }
+ get {
+ EnsureChildControls();
+ return this.label.InnerText;
+ }
+
+ set {
+ EnsureChildControls();
+ this.label.InnerText = value;
+ }
}
/// <summary>
@@ -264,8 +280,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text that introduces the example OpenID url.")]
public string ExamplePrefix {
- get { return this.examplePrefixLabel.Text; }
- set { this.examplePrefixLabel.Text = value; }
+ get {
+ EnsureChildControls();
+ return this.examplePrefixLabel.Text;
+ }
+
+ set {
+ EnsureChildControls();
+ this.examplePrefixLabel.Text = value;
+ }
}
/// <summary>
@@ -278,8 +301,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The example OpenID Identifier to display to the user.")]
public string ExampleUrl {
- get { return this.exampleUrlLabel.Text; }
- set { this.exampleUrlLabel.Text = value; }
+ get {
+ EnsureChildControls();
+ return this.exampleUrlLabel.Text;
+ }
+
+ set {
+ EnsureChildControls();
+ this.exampleUrlLabel.Text = value;
+ }
}
/// <summary>
@@ -292,8 +322,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text to display if the user attempts to login without providing an Identifier.")]
public string RequiredText {
- get { return this.requiredValidator.Text.Substring(0, this.requiredValidator.Text.Length - RequiredTextSuffix.Length); }
- set { this.requiredValidator.ErrorMessage = this.requiredValidator.Text = value + RequiredTextSuffix; }
+ get {
+ EnsureChildControls();
+ return this.requiredValidator.Text.Substring(0, this.requiredValidator.Text.Length - RequiredTextSuffix.Length);
+ }
+
+ set {
+ EnsureChildControls();
+ this.requiredValidator.ErrorMessage = this.requiredValidator.Text = value + RequiredTextSuffix;
+ }
}
/// <summary>
@@ -306,8 +343,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text to display if the user provides an invalid form for an Identifier.")]
public string UriFormatText {
- get { return this.identifierFormatValidator.Text.Substring(0, this.identifierFormatValidator.Text.Length - RequiredTextSuffix.Length); }
- set { this.identifierFormatValidator.ErrorMessage = this.identifierFormatValidator.Text = value + RequiredTextSuffix; }
+ get {
+ EnsureChildControls();
+ return this.identifierFormatValidator.Text.Substring(0, this.identifierFormatValidator.Text.Length - RequiredTextSuffix.Length);
+ }
+
+ set {
+ EnsureChildControls();
+ this.identifierFormatValidator.ErrorMessage = this.identifierFormatValidator.Text = value + RequiredTextSuffix;
+ }
}
/// <summary>
@@ -319,8 +363,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[DefaultValue(UriValidatorEnabledDefault)]
[Description("Whether to perform Identifier format validation prior to an authentication attempt.")]
public bool UriValidatorEnabled {
- get { return this.identifierFormatValidator.Enabled; }
- set { this.identifierFormatValidator.Enabled = value; }
+ get {
+ EnsureChildControls();
+ return this.identifierFormatValidator.Enabled;
+ }
+
+ set {
+ EnsureChildControls();
+ this.identifierFormatValidator.Enabled = value;
+ }
}
/// <summary>
@@ -332,8 +383,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text of the link users can click on to obtain an OpenID.")]
public string RegisterText {
- get { return this.registerLink.Text; }
- set { this.registerLink.Text = value; }
+ get {
+ EnsureChildControls();
+ return this.registerLink.Text;
+ }
+
+ set {
+ EnsureChildControls();
+ this.registerLink.Text = value;
+ }
}
/// <summary>
@@ -346,8 +404,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The URL to link users to who click the link to obtain a new OpenID.")]
public string RegisterUrl {
- get { return this.registerLink.NavigateUrl; }
- set { this.registerLink.NavigateUrl = value; }
+ get {
+ EnsureChildControls();
+ return this.registerLink.NavigateUrl;
+ }
+
+ set {
+ EnsureChildControls();
+ this.registerLink.NavigateUrl = value;
+ }
}
/// <summary>
@@ -360,8 +425,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text of the tooltip to display when the user hovers over the link to obtain a new OpenID.")]
public string RegisterToolTip {
- get { return this.registerLink.ToolTip; }
- set { this.registerLink.ToolTip = value; }
+ get {
+ EnsureChildControls();
+ return this.registerLink.ToolTip;
+ }
+
+ set {
+ EnsureChildControls();
+ this.registerLink.ToolTip = value;
+ }
}
/// <summary>
@@ -373,8 +445,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[DefaultValue(RegisterVisibleDefault)]
[Description("Whether to display a link to allow users to easily obtain a new OpenID.")]
public bool RegisterVisible {
- get { return this.registerLink.Visible; }
- set { this.registerLink.Visible = value; }
+ get {
+ EnsureChildControls();
+ return this.registerLink.Visible;
+ }
+
+ set {
+ EnsureChildControls();
+ this.registerLink.Visible = value;
+ }
}
/// <summary>
@@ -386,8 +465,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text that appears on the button that initiates login.")]
public string ButtonText {
- get { return this.loginButton.Text; }
- set { this.loginButton.Text = value; }
+ get {
+ EnsureChildControls();
+ return this.loginButton.Text;
+ }
+
+ set {
+ EnsureChildControls();
+ this.loginButton.Text = value;
+ }
}
/// <summary>
@@ -399,8 +485,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The text of the \"Remember Me\" checkbox.")]
public string RememberMeText {
- get { return this.rememberMeCheckBox.Text; }
- set { this.rememberMeCheckBox.Text = value; }
+ get {
+ EnsureChildControls();
+ return this.rememberMeCheckBox.Text;
+ }
+
+ set {
+ EnsureChildControls();
+ this.rememberMeCheckBox.Text = value;
+ }
}
/// <summary>
@@ -438,8 +531,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[DefaultValue(RememberMeVisibleDefault)]
[Description("Whether the \"Remember Me\" checkbox should be displayed.")]
public bool RememberMeVisible {
- get { return this.rememberMeCheckBox.Visible; }
- set { this.rememberMeCheckBox.Visible = value; }
+ get {
+ EnsureChildControls();
+ return this.rememberMeCheckBox.Visible;
+ }
+
+ set {
+ EnsureChildControls();
+ this.rememberMeCheckBox.Visible = value;
+ }
}
/// <summary>
@@ -448,11 +548,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
[Bindable(true)]
[Category("Appearance")]
- [DefaultValue(UsePersistentCookieDefault)]
+ [DefaultValue(RememberMeDefault)]
[Description("Whether a successful authentication should result in a persistent cookie being saved to the browser.")]
public bool RememberMe {
- get { return this.UsePersistentCookie; }
- set { this.UsePersistentCookie = value; }
+ get { return this.UsePersistentCookie != LoginPersistence.Session; }
+ set { this.UsePersistentCookie = value ? LoginPersistence.PersistentAuthentication : LoginPersistence.Session; }
}
/// <summary>
@@ -468,7 +568,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
set {
unchecked {
- this.WrappedTextBox.TabIndex = (short)(value + TextBoxTabIndexOffset);
+ base.TabIndex = (short)(value + TextBoxTabIndexOffset);
this.loginButton.TabIndex = (short)(value + LoginButtonTabIndexOffset);
this.rememberMeCheckBox.TabIndex = (short)(value + RememberMeTabIndexOffset);
this.registerLink.TabIndex = (short)(value + RegisterTabIndexOffset);
@@ -485,8 +585,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Localizable(true)]
[Description("The tooltip to display when the user hovers over the login button.")]
public string ButtonToolTip {
- get { return this.loginButton.ToolTip; }
- set { this.loginButton.ToolTip = value; }
+ get {
+ EnsureChildControls();
+ return this.loginButton.ToolTip;
+ }
+
+ set {
+ EnsureChildControls();
+ this.loginButton.ToolTip = value;
+ }
}
/// <summary>
@@ -497,10 +604,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Description("The validation group that the login button and text box validator belong to.")]
public string ValidationGroup {
get {
+ EnsureChildControls();
return this.requiredValidator.ValidationGroup;
}
set {
+ EnsureChildControls();
this.requiredValidator.ValidationGroup = value;
this.loginButton.ValidationGroup = value;
}
@@ -525,7 +634,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// cookie should persist across user sessions.
/// </summary>
[Browsable(false), Bindable(false)]
- public override bool UsePersistentCookie {
+ public override LoginPersistence UsePersistentCookie {
get {
return base.UsePersistentCookie;
}
@@ -535,8 +644,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// use conditional here to prevent infinite recursion
// with CheckedChanged event.
- if (this.rememberMeCheckBox.Checked != value) {
- this.rememberMeCheckBox.Checked = value;
+ bool rememberMe = value != LoginPersistence.Session;
+ if (this.rememberMeCheckBox.Checked != rememberMe) {
+ this.rememberMeCheckBox.Checked = rememberMe;
}
}
}
@@ -544,27 +654,27 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// Outputs server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object and stores tracing information about the control if tracing is enabled.
+ /// </summary>
+ /// <param name="writer">The <see cref="T:System.Web.UI.HTmlTextWriter"/> object that receives the control content.</param>
+ public override void RenderControl(HtmlTextWriter writer) {
+ this.RenderChildren(writer);
+ }
+
+ /// <summary>
/// Creates the child controls.
/// </summary>
protected override void CreateChildControls() {
- // Don't call base.CreateChildControls(). This would add the WrappedTextBox
- // to the Controls collection, which would implicitly remove it from the table
- // we have already added it to.
+ this.InitializeControls();
// Just add the panel we've assembled earlier.
- this.Controls.Add(this.panel);
-
- if (ShouldBeFocused) {
- WrappedTextBox.Focus();
- }
+ base.Controls.Add(this.panel);
}
/// <summary>
/// Initializes the child controls.
/// </summary>
- protected override void InitializeControls() {
- base.InitializeControls();
-
+ protected void InitializeControls() {
this.panel = new Panel();
Table table = new Table();
@@ -583,7 +693,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// top row, middle cell
cell = new TableCell();
- cell.Controls.Add(this.WrappedTextBox);
+ cell.Controls.Add(new InPlaceControl(this));
row1.Cells.Add(cell);
// top row, right cell
@@ -611,7 +721,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix;
this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix;
this.requiredValidator.Display = ValidatorDisplay.Dynamic;
- this.requiredValidator.ControlToValidate = WrappedTextBox.ID;
+ this.requiredValidator.ControlToValidate = this.ID;
this.requiredValidator.ValidationGroup = ValidationGroupDefault;
cell.Controls.Add(this.requiredValidator);
this.identifierFormatValidator = new CustomValidator();
@@ -620,7 +730,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate;
this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault;
this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic;
- this.identifierFormatValidator.ControlToValidate = WrappedTextBox.ID;
+ this.identifierFormatValidator.ControlToValidate = this.ID;
this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault;
cell.Controls.Add(this.identifierFormatValidator);
this.errorLabel = new Label();
@@ -680,26 +790,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Customizes HTML rendering of the control.
- /// </summary>
- /// <param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter"/> that represents the output stream to render HTML content on the client.</param>
- protected override void Render(HtmlTextWriter writer) {
- // avoid writing begin and end SPAN tags for XHTML validity.
- RenderContents(writer);
- }
-
- /// <summary>
/// Renders the child controls.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the rendered content.</param>
protected override void RenderChildren(HtmlTextWriter writer) {
if (!this.DesignMode) {
- this.label.Attributes["for"] = this.WrappedTextBox.ClientID;
+ this.label.Attributes["for"] = this.ClientID;
if (!string.IsNullOrEmpty(this.IdSelectorIdentifier)) {
this.idselectorJavascript.Visible = true;
this.idselectorJavascript.Text = @"<script type='text/javascript'><!--
-idselector_input_id = '" + WrappedTextBox.ClientID + @"';
+idselector_input_id = '" + this.ClientID + @"';
// --></script>
<script type='text/javascript' id='__openidselector' src='https://www.idselector.com/selector/" + this.IdSelectorIdentifier + @"' charset='utf-8'></script>";
} else {
@@ -737,30 +838,6 @@ idselector_input_id = '" + WrappedTextBox.ClientID + @"';
}
/// <summary>
- /// Fires the <see cref="LoggingIn"/> event.
- /// </summary>
- /// <returns>
- /// Returns whether the login should proceed. False if some event handler canceled the request.
- /// </returns>
- protected virtual bool OnLoggingIn() {
- EventHandler<OpenIdEventArgs> loggingIn = this.LoggingIn;
- if (this.Request == null) {
- this.CreateRequest();
- }
-
- if (this.Request != null) {
- OpenIdEventArgs args = new OpenIdEventArgs(this.Request);
- if (loggingIn != null) {
- loggingIn(this, args);
- }
-
- return !args.Cancel;
- } else {
- return false;
- }
- }
-
- /// <summary>
/// Fires the <see cref="RememberMeChanged"/> event.
/// </summary>
protected virtual void OnRememberMeChanged() {
@@ -799,8 +876,49 @@ idselector_input_id = '" + WrappedTextBox.ClientID + @"';
return;
}
- if (this.OnLoggingIn()) {
- this.LogOn();
+ IAuthenticationRequest request = this.CreateRequests().FirstOrDefault();
+ if (request != null) {
+ this.LogOn(request);
+ } else {
+ if (!string.IsNullOrEmpty(this.FailedMessageText)) {
+ this.errorLabel.Text = string.Format(CultureInfo.CurrentCulture, this.FailedMessageText, OpenIdStrings.OpenIdEndpointNotFound);
+ this.errorLabel.Visible = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Renders the control inner.
+ /// </summary>
+ /// <param name="writer">The writer.</param>
+ private void RenderControlInner(HtmlTextWriter writer) {
+ base.RenderControl(writer);
+ }
+
+ /// <summary>
+ /// A control that acts as a placeholder to indicate where
+ /// the OpenIdLogin control should render its OpenIdTextBox parent.
+ /// </summary>
+ private class InPlaceControl : PlaceHolder {
+ /// <summary>
+ /// The owning control to render.
+ /// </summary>
+ private OpenIdLogin renderControl;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InPlaceControl"/> class.
+ /// </summary>
+ /// <param name="renderControl">The render control.</param>
+ internal InPlaceControl(OpenIdLogin renderControl) {
+ this.renderControl = renderControl;
+ }
+
+ /// <summary>
+ /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
+ /// </summary>
+ /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
+ protected override void Render(HtmlTextWriter writer) {
+ this.renderControl.RenderControlInner(writer);
}
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
index 55160e1..7708520 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs
@@ -611,7 +611,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
// Add state that needs to survive across the redirect.
- this.Request.AddCallbackArguments(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture));
+ this.Request.SetCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture));
} else {
Logger.OpenId.WarnFormat("An invalid identifier was entered ({0}), but not caught by any validation routine.", this.Text);
this.Request = null;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cd b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cd
new file mode 100644
index 0000000..0519ecb
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cd
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index 84b60bb..9571ee3 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -490,6 +490,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
NegativeAssertionResponse negativeAssertion;
IndirectSignedResponse positiveExtensionOnly;
if ((positiveAssertion = message as PositiveAssertionResponse) != null) {
+ if (this.EndpointFilter != null) {
+ // We need to make sure that this assertion is coming from an endpoint
+ // that the host deems acceptable.
+ var providerEndpoint = new SimpleXrdsProviderEndpoint(positiveAssertion);
+ ErrorUtilities.VerifyProtocol(
+ this.EndpointFilter(providerEndpoint),
+ OpenIdStrings.PositiveAssertionFromNonWhitelistedProvider,
+ providerEndpoint.Uri);
+ }
+
var response = new PositiveAuthenticationResponse(positiveAssertion, this);
foreach (var behavior in this.Behaviors) {
behavior.OnIncomingPositiveAssertion(response);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
index 3f46e53..8a4c94e 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.cs
@@ -12,24 +12,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
- using System.Drawing.Design;
using System.Globalization;
using System.Linq;
using System.Text;
- using System.Text.RegularExpressions;
using System.Web;
- using System.Web.Security;
using System.Web.UI;
- using DotNetOpenAuth.ComponentModel;
- using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Extensions;
- using DotNetOpenAuth.OpenId.Extensions.UI;
/// <summary>
/// A common base class for OpenID Relying Party controls.
/// </summary>
- internal abstract class OpenIdRelyingPartyAjaxControlBase : OpenIdRelyingPartyControlBase, ICallbackEventHandler {
+ public abstract class OpenIdRelyingPartyAjaxControlBase : OpenIdRelyingPartyControlBase, ICallbackEventHandler {
/// <summary>
/// The manifest resource name of the javascript file to include on the hosting page.
/// </summary>
@@ -46,7 +40,47 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
protected const string CallbackJsFunctionAsync = "window.dnoa_internal.callbackAsync";
/// <summary>
- /// Stores the result of a AJAX callback discovery.
+ /// The "dnoa.op_endpoint" string.
+ /// </summary>
+ private const string OPEndpointParameterName = OpenIdUtilities.CustomParameterPrefix + "op_endpoint";
+
+ /// <summary>
+ /// The "dnoa.claimed_id" string.
+ /// </summary>
+ private const string ClaimedIdParameterName = OpenIdUtilities.CustomParameterPrefix + "claimed_id";
+
+ #region Property viewstate keys
+
+ /// <summary>
+ /// The viewstate key to use for storing the value of the a successful authentication.
+ /// </summary>
+ private const string AuthDataViewStateKey = "AuthData";
+
+ /// <summary>
+ /// The viewstate key to use for storing the value of the <see cref="AuthenticationResponse"/> property.
+ /// </summary>
+ private const string AuthenticationResponseViewStateKey = "AuthenticationResponse";
+
+ /// <summary>
+ /// The viewstate key to use for storing the value of the <see cref="AuthenticationProcessedAlready"/> property.
+ /// </summary>
+ private const string AuthenticationProcessedAlreadyViewStateKey = "AuthenticationProcessedAlready";
+
+ #endregion
+
+ /// <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;
+
+ /// <summary>
+ /// Stores the result of an AJAX discovery request while it is waiting
+ /// to be picked up by ASP.NET on the way down to the user agent.
/// </summary>
private string discoveryResult;
@@ -61,10 +95,26 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
protected OpenIdRelyingPartyAjaxControlBase() {
// The AJAX login style always uses popups (or invisible iframes).
- this.Popup = PopupBehavior.Always;
+ base.Popup = PopupBehavior.Always;
+
+ // The expected use case for the AJAX login box is for comments... not logging in.
+ this.LoginMode = LoginSiteNotification.None;
}
/// <summary>
+ /// Fired when a Provider sends back a positive assertion to this control,
+ /// but the authentication has not yet been verified.
+ /// </summary>
+ /// <remarks>
+ /// <b>No security critical decisions should be made within event handlers
+ /// for this event</b> as the authenticity of the assertion has not been
+ /// verified yet. All security related code should go in the event handler
+ /// for the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event.
+ /// </remarks>
+ [Description("Fired when a Provider sends back a positive assertion to this control, but the authentication has not yet been verified.")]
+ public event EventHandler<OpenIdEventArgs> UnconfirmedPositiveAssertion;
+
+ /// <summary>
/// Gets or sets a value indicating when to use a popup window to complete the login experience.
/// </summary>
/// <value>The default value is <see cref="PopupBehavior.Never"/>.</value>
@@ -74,6 +124,90 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
set { ErrorUtilities.VerifySupported(value == base.Popup, OpenIdStrings.PropertyValueNotSupported); }
}
+ /// <summary>
+ /// Gets the completed authentication response.
+ /// </summary>
+ public IAuthenticationResponse AuthenticationResponse {
+ get {
+ if (this.authenticationResponse == null) {
+ // We will either validate a new response and return a live AuthenticationResponse
+ // or we will try to deserialize a previous IAuthenticationResponse (snapshot)
+ // from viewstate and return that.
+ IAuthenticationResponse viewstateResponse = this.ViewState[AuthenticationResponseViewStateKey] as IAuthenticationResponse;
+ string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string;
+ string formAuthData = this.Page.Request.Form[this.OpenIdAuthDataFormKey];
+
+ // First see if there is fresh auth data to be processed into a response.
+ if (!string.IsNullOrEmpty(formAuthData) && !string.Equals(viewstateAuthData, formAuthData, StringComparison.Ordinal)) {
+ this.ViewState[AuthDataViewStateKey] = formAuthData;
+
+ Uri authUri = new Uri(formAuthData);
+ HttpRequestInfo clientResponseInfo = new HttpRequestInfo {
+ UrlBeforeRewriting = authUri,
+ };
+
+ this.authenticationResponse = this.RelyingParty.GetResponse(clientResponseInfo);
+ this.AuthenticationProcessedAlready = false;
+
+ // Save out the authentication response to viewstate so we can find it on
+ // a subsequent postback.
+ this.ViewState[AuthenticationResponseViewStateKey] = new PositiveAuthenticationResponseSnapshot(this.authenticationResponse);
+ } else {
+ this.authenticationResponse = viewstateResponse;
+ }
+ }
+
+ return this.authenticationResponse;
+ }
+ }
+
+ /// <summary>
+ /// Gets the name of the open id auth data form key.
+ /// </summary>
+ /// <value>Usually a concatenation of the control's name and <c>"_openidAuthData"</c>.</value>
+ protected abstract string OpenIdAuthDataFormKey { get; }
+
+ /// <summary>
+ /// Gets the relying party to use when verification of incoming messages is NOT wanted.
+ /// </summary>
+ private static OpenIdRelyingParty RelyingPartyNonVerifying {
+ get {
+ if (relyingPartyNonVerifying == null) {
+ relyingPartyNonVerifying = OpenIdRelyingParty.CreateNonVerifying();
+ }
+ return relyingPartyNonVerifying;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether an authentication in the page's view state
+ /// has already been processed and appropriate events fired.
+ /// </summary>
+ private bool AuthenticationProcessedAlready {
+ get { return (bool)(ViewState[AuthenticationProcessedAlreadyViewStateKey] ?? false); }
+ set { ViewState[AuthenticationProcessedAlreadyViewStateKey] = value; }
+ }
+
+ /// <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 from the <see cref="UnconfirmedPositiveAssertion"/> event handler.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "By design")]
+ public void RegisterClientScriptExtension<T>(string propertyName) where T : IClientScriptExtensionResponse {
+ ErrorUtilities.VerifyNonZeroLength(propertyName, "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 ICallbackEventHandler Members
/// <summary>
@@ -118,7 +252,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
discoveryResultBuilder.AppendFormat("claimedIdentifier: {0},", MessagingUtilities.GetSafeJavascriptValue(requests.First().ClaimedIdentifier));
discoveryResultBuilder.Append("requests: [");
foreach (IAuthenticationRequest request in requests) {
- this.OnLoggingIn(request);
discoveryResultBuilder.Append("{");
discoveryResultBuilder.AppendFormat("endpoint: {0},", MessagingUtilities.GetSafeJavascriptValue(request.Provider.Uri.AbsoluteUri));
request.Mode = AuthenticationRequestMode.Immediate;
@@ -139,6 +272,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
discoveryResultBuilder.Append("requests: new Array(),");
discoveryResultBuilder.AppendFormat("error: {0}", MessagingUtilities.GetSafeJavascriptValue(ex.Message));
}
+
discoveryResultBuilder.Append("}");
this.discoveryResult = discoveryResultBuilder.ToString();
}
@@ -146,6 +280,39 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// Fires the <see cref="UnconfirmedPositiveAssertion"/> event.
+ /// </summary>
+ protected virtual void OnUnconfirmedPositiveAssertion() {
+ var unconfirmedPositiveAssertion = this.UnconfirmedPositiveAssertion;
+ if (unconfirmedPositiveAssertion != null) {
+ unconfirmedPositiveAssertion(this, null);
+ }
+ }
+
+ /// <summary>
+ /// Raises the <see cref="E:Load"/> event.
+ /// </summary>
+ /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
+ protected override void OnLoad(EventArgs e) {
+ base.OnLoad(e);
+
+ // Our parent control ignores all OpenID messages included in a postback,
+ // but our AJAX controls hide an old OpenID message in a postback payload,
+ // so we deserialize it and process it when appropriate.
+ if (this.Page.IsPostBack) {
+ if (this.AuthenticationResponse != null && !this.AuthenticationProcessedAlready) {
+ // Only process messages targeted at this control.
+ // Note that Stateless mode causes no receiver to be indicated.
+ string receiver = this.AuthenticationResponse.GetCallbackArgument(ReturnToReceivingControlId);
+ if (receiver == null || receiver == this.ClientID) {
+ this.ProcessResponse(this.AuthenticationResponse);
+ this.AuthenticationProcessedAlready = true;
+ }
+ }
+ }
+ }
+
+ /// <summary>
/// Creates the authentication requests for a given user-supplied Identifier.
/// </summary>
/// <returns>A sequence of authentication requests, any one of which may be
@@ -174,6 +341,62 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
+ /// </summary>
+ /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
+ protected override void Render(HtmlTextWriter writer) {
+ base.Render(writer);
+
+ // Emit a hidden field to let the javascript on the user agent know if an
+ // authentication has already successfully taken place.
+ string viewstateAuthData = this.ViewState[AuthDataViewStateKey] as string;
+ if (!string.IsNullOrEmpty(viewstateAuthData)) {
+ writer.AddAttribute(HtmlTextWriterAttribute.Name, this.OpenIdAuthDataFormKey);
+ writer.AddAttribute(HtmlTextWriterAttribute.Value, viewstateAuthData, true);
+ writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
+ writer.RenderBeginTag(HtmlTextWriterTag.Input);
+ writer.RenderEndTag();
+ }
+ }
+
+ /// <summary>
+ /// Notifies the user agent via an AJAX response of a completed authentication attempt.
+ /// </summary>
+ protected override void ScriptClosingPopupOrIFrame() {
+ Logger.OpenId.InfoFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
+ List<string> assignments = new List<string>();
+
+ var authResponse = RelyingPartyNonVerifying.GetResponse();
+ if (authResponse.Status == AuthenticationStatus.Authenticated) {
+ this.OnUnconfirmedPositiveAssertion(); // event handler will fill the clientScriptExtensions collection.
+ 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)) {
+ js = "null";
+ }
+ assignments.Add(pair.Value + " = " + js);
+ }
+ }
+
+ 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);
+ }
+ this.CallbackUserAgentMethod("dnoa_internal.processAuthorizationResult(" + payload + ")", assignments.ToArray());
+ }
+
+ /// <summary>
/// Creates the authentication requests for a given user-supplied Identifier.
/// </summary>
/// <param name="requests">The authentication requests to prepare.</param>
@@ -187,25 +410,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Configure each generated request.
int reqIndex = 0;
foreach (var req in requests) {
- req.AddCallbackArguments("index", (reqIndex++).ToString(CultureInfo.InvariantCulture));
-
- if (req.Provider.IsExtensionSupported<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.AddCallbackArguments("dotnetopenid.popupUISupported", "1");
- }
+ req.SetCallbackArgument("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)["dotnetopenid.userSuppliedIdentifier"])) {
- req.AddCallbackArguments("dotnetopenid.userSuppliedIdentifier", this.Identifier);
+ if (string.IsNullOrEmpty(HttpUtility.ParseQueryString(req.ReturnToUrl.Query)[AuthenticationRequest.UserSuppliedIdentifierParameterName])) {
+ req.SetCallbackArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName, this.Identifier.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.AddCallbackArguments("dotnetopenid.op_endpoint", req.Provider.Uri.AbsoluteUri);
- req.AddCallbackArguments("dotnetopenid.claimed_id", (string)req.ClaimedIdentifier ?? string.Empty);
+ req.SetCallbackArgument(OPEndpointParameterName, req.Provider.Uri.AbsoluteUri);
+ req.SetCallbackArgument(ClaimedIdParameterName, (string)req.ClaimedIdentifier ?? string.Empty);
+
+ // Inform ourselves in return_to that we're in a popup or iframe.
+ req.SetCallbackArgument(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
@@ -245,33 +463,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Notifies the user agent via an AJAX response of a completed authentication attempt.
- /// </summary>
- private void ReportAuthenticationResult() {
- Logger.OpenId.InfoFormat("AJAX (iframe) callback from OP: {0}", this.Page.Request.Url);
- List<string> assignments = new List<string>();
-
- var authResponse = this.RelyingParty.GetResponse();
- if (authResponse.Status == AuthenticationStatus.Authenticated) {
- this.OnLoggedIn(authResponse);
- 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)) {
- js = "null";
- }
- assignments.Add(pair.Value + " = " + js);
- }
- }
-
- this.CallbackUserAgentMethod("dnoi_internal.processAuthorizationResult(document.URL)", assignments.ToArray());
- }
-
- /// <summary>
/// Invokes a method on a parent frame/window's OpenIdAjaxTextBox,
/// and closes the calling popup window if applicable.
/// </summary>
@@ -292,7 +483,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Logger.OpenId.InfoFormat("Sending Javascript callback: {0}", methodCall);
Page.Response.Write(@"<html><body><script language='javascript'>
var inPopup = !window.frameElement;
- var objSrc = inPopup ? window.opener.waiting_openidBox : window.frameElement.openidBox;
+ var objSrc = inPopup ? window.opener : window.frameElement;
");
if (preAssignments != null) {
foreach (string assignment in preAssignments) {
@@ -304,11 +495,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// 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};
-}}
+ objSrc.{0};
+ window.self.close();
+ }} else {{
+ objSrc.{0};
+ }}
</script></body></html>";
Page.Response.Write(string.Format(CultureInfo.InvariantCulture, htmlFormat, methodCall));
Page.Response.End();
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
index 65b1b99..c6f6a75 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyAjaxControlBase.js
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="OpenIdRelyingPartyControlBase.js" company="Andrew Arnott">
+// <copyright file="OpenIdRelyingPartyAjaxControlBase.js" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -8,139 +8,170 @@ if (window.dnoa_internal === undefined) {
window.dnoa_internal = new Object();
};
+/// <summary>Removes a given element from the array.</summary>
+/// <returns>True if the element was in the array, or false if it was not found.</returns>
+Array.prototype.remove = function(element) {
+ function elementToRemoveLast(a, b) {
+ if (a == element) { return 1; }
+ if (b == element) { return -1; }
+ return 0;
+ }
+ this.sort(elementToRemoveLast);
+ if (this[this.length - 1] == element) {
+ this.pop();
+ return true;
+ } else {
+ return false;
+ }
+};
+
window.dnoa_internal.discoveryResults = new Array(); // user supplied identifiers and discovery results
-/// <summary>Instantiates an object that represents an OpenID Identifier.</summary>
-window.OpenId = function(identifier) {
- /// <summary>Performs discovery on the identifier.</summary>
- /// <param name="onCompleted">A function(DiscoveryResult) callback to be called when discovery has completed.</param>
- this.discover = function(onCompleted) {
- /// <summary>Instantiates an object that stores discovery results of some identifier.</summary>
- function DiscoveryResult(identifier, discoveryInfo) {
- /// <summary>
- /// Instantiates an object that describes an OpenID service endpoint and facilitates
- /// initiating and tracking an authentication request.
- /// </summary>
- function ServiceEndpoint(requestInfo, userSuppliedIdentifier) {
- this.immediate = requestInfo.immediate ? new window.dnoa_internal.Uri(requestInfo.immediate) : null;
- this.setup = requestInfo.setup ? new window.dnoa_internal.Uri(requestInfo.setup) : null;
- this.endpoint = new window.dnoa_internal.Uri(requestInfo.endpoint);
- this.userSuppliedIdentifier = userSuppliedIdentifier;
- var self = this; // closure so that delegates have the right instance
- this.loginPopup = function(onSuccess, onFailure) {
- //self.abort(); // ensure no concurrent attempts
- window.dnoa_internal.processAuthorizationResult = function(childLocation) {
- window.dnoa_internal.processAuthorizationResult = null;
- trace('Received event from child window: ' + childLocation);
- var success = true; // TODO: discern between success and failure, and fire the correct event.
-
- if (success) {
- if (onSuccess) {
- onSuccess();
- }
- } else {
- if (onFailure) {
- onFailure();
- }
- }
- };
- var width = 800;
- var height = 600;
- if (self.setup.getQueryArgValue("openid.return_to").indexOf("dotnetopenid.popupUISupported") >= 0) {
- width = 450;
- height = 500;
- }
+// The possible authentication results
+window.dnoa_internal.authSuccess = new Object();
+window.dnoa_internal.authRefused = new Object();
+window.dnoa_internal.timedOut = new Object();
- var left = (screen.width - width) / 2;
- var top = (screen.height - height) / 2;
- self.popup = window.open(self.setup, 'opLogin', 'status=0,toolbar=0,location=1,resizable=1,scrollbars=1,left=' + left + ',top=' + top + ',width=' + width + ',height=' + height);
-
- // If the OP supports the UI extension it MAY close its own window
- // for a negative assertion. We must be able to recover from that scenario.
- var localSelf = self;
- self.popupCloseChecker = window.setInterval(function() {
- if (localSelf.popup && localSelf.popup.closed) {
- // The window closed, either because the user closed it, canceled at the OP,
- // or approved at the OP and the popup window closed itself due to our script.
- // If we were graying out the entire page while the child window was up,
- // we would probably revert that here.
- window.clearInterval(localSelf.popupCloseChecker);
- localSelf.popup = null;
-
- // The popup may have managed to inform us of the result already,
- // so check whether the callback method was cleared already, which
- // would indicate we've already processed this.
- if (window.dnoa_internal.processAuthorizationResult) {
- trace('User or OP canceled by closing the window.');
- if (onFailure) {
- onFailure();
- }
- window.dnoa_internal.processAuthorizationResult = null;
- }
- }
- }, 250);
- };
- };
-
- this.userSuppliedIdentifier = identifier;
- this.claimedIdentifier = discoveryInfo.claimedIdentifier; // The claimed identifier may be null if the user provided an OP Identifier.
- trace('Discovered claimed identifier: ' + (this.claimedIdentifier ? this.claimedIdentifier : "(directed identity)"));
-
- if (discoveryInfo) {
- this.length = discoveryInfo.requests.length;
- for (var i = 0; i < discoveryInfo.requests.length; i++) {
- this[i] = new ServiceEndpoint(discoveryInfo.requests[i], identifier);
- }
- } else {
- this.length = 0;
- }
- };
+/// <summary>Instantiates a new FrameManager.</summary>
+/// <param name="maxFrames">The maximum number of concurrent 'jobs' (authentication attempts).</param>
+window.dnoa_internal.FrameManager = function(maxFrames) {
+ this.queuedWork = new Array();
+ this.frames = new Array();
+ this.maxFrames = maxFrames;
+
+ /// <summary>Called to queue up some work that will use an iframe as soon as it is available.</summary>
+ /// <param name="job">
+ /// A delegate that must return the url to point the iframe to.
+ /// Its first parameter is the iframe created to service the request.
+ /// It will only be called when the work actually begins.
+ /// </param>
+ /// <param name="p1">Arbitrary additional parameter to pass to the job.</param>
+ this.enqueueWork = function(job, p1) {
+ // Assign an iframe to this task immediately if there is one available.
+ if (this.frames.length < this.maxFrames) {
+ this.createIFrame(job, p1);
+ } else {
+ this.queuedWork.unshift({ job: job, p1: p1 });
+ }
+ };
+
+ /// <summary>Clears the job queue and immediately closes all iframes.</summary>
+ this.cancelAllWork = function() {
+ trace('Canceling all open and pending iframes.');
+ while (this.queuedWork.pop());
+ this.closeFrames();
+ };
+ /// <summary>An event fired when a frame is closing.</summary>
+ this.onJobCompleted = function() {
+ // If there is a job in the queue, go ahead and start it up.
+ if (jobDesc = this.queuedWork.pop()) {
+ this.createIFrame(jobDesc.job, jobDesc.p1);
+ }
+ }
+
+ this.createIFrame = function(job, p1) {
+ var iframe = document.createElement("iframe");
+ if (!window.openid_visible_iframe) {
+ iframe.setAttribute("width", 0);
+ iframe.setAttribute("height", 0);
+ iframe.setAttribute("style", "display: none");
+ }
+ iframe.setAttribute("src", job(iframe, p1));
+ iframe.dnoa_internal = window.dnoa_internal;
+ box.parentNode.insertBefore(iframe, box);
+ this.frames.push(iframe);
+ return iframe;
+ };
+
+ this.closeFrames = function() {
+ if (this.frames.length == 0) { return false; }
+ for (var i = 0; i < this.frames.length; i++) {
+ if (this.frames[i].parentNode) { this.frames[i].parentNode.removeChild(this.frames[i]); }
+ }
+ while (this.frames.length > 0) { this.frames.pop(); }
+ return true;
+ };
+
+ this.closeFrame = function(frame) {
+ if (frame.parentNode) { frame.parentNode.removeChild(frame); }
+ var removed = this.frames.remove(frame);
+ this.onJobCompleted();
+ return removed;
+ };
+};
+
+/// <summary>Instantiates an object that represents an OpenID Identifier.</summary>
+window.OpenIdIdentifier = function(identifier) {
+ /// <summary>Performs discovery on the identifier.</summary>
+ /// <param name="onDiscoverSuccess">A function(DiscoveryResult) callback to be called when discovery has completed successfully.</param>
+ /// <param name="onDiscoverFailure">A function callback to be called when discovery has completed in failure.</param>
+ this.discover = function(onDiscoverSuccess, onDiscoverFailure) {
/// <summary>Receives the results of a successful discovery (even if it yielded 0 results).</summary>
- function successCallback(discoveryResult, identifier) {
+ function discoverSuccessCallback(discoveryResult, identifier) {
trace('Discovery completed for: ' + identifier);
// Deserialize the JSON object and store the result if it was a successful discovery.
discoveryResult = eval('(' + discoveryResult + ')');
// Add behavior for later use.
- discoveryResult = new DiscoveryResult(identifier, discoveryResult);
+ discoveryResult = new window.dnoa_internal.DiscoveryResult(identifier, discoveryResult);
window.dnoa_internal.discoveryResults[identifier] = discoveryResult;
- if (onCompleted) {
- onCompleted(discoveryResult);
+ if (onDiscoverSuccess) {
+ onDiscoverSuccess(discoveryResult);
}
};
/// <summary>Receives the discovery failure notification.</summary>
- failureCallback = function(message, userSuppliedIdentifier) {
+ function discoverFailureCallback(message, userSuppliedIdentifier) {
trace('Discovery failed for: ' + identifier);
- if (onCompleted) {
- onCompleted();
+ if (onDiscoverFailure) {
+ onDiscoverFailure();
}
};
if (window.dnoa_internal.discoveryResults[identifier]) {
trace("We've already discovered " + identifier + " so we're skipping it this time.");
- onCompleted(window.dnoa_internal.discoveryResults[identifier]);
+ if (onDiscoverSuccess) {
+ onDiscoverSuccess(window.dnoa_internal.discoveryResults[identifier]);
+ }
+ return;
}
trace('starting discovery on ' + identifier);
- window.dnoa_internal.callbackAsync(identifier, successCallback, failureCallback);
+ window.dnoa_internal.callbackAsync(identifier, discoverSuccessCallback, discoverFailureCallback);
};
/// <summary>Performs discovery and immediately begins checkid_setup to authenticate the user using a given identifier.</summary>
- this.login = function(onSuccess, onFailure) {
+ this.login = function(onSuccess, onLoginFailure) {
+ this.discover(function(discoveryResult) {
+ if (discoveryResult) {
+ trace('Discovery succeeded and found ' + discoveryResult.length + ' OpenID service endpoints.');
+ if (discoveryResult.length > 0) {
+ discoveryResult[0].loginPopup(onSuccess, onLoginFailure);
+ } else {
+ trace("This doesn't look like an OpenID Identifier. Aborting login.");
+ if (onLoginFailure) {
+ onLoginFailure();
+ }
+ }
+ }
+ });
+ };
+
+ /// <summary>Performs discovery and immediately begins checkid_immediate on all discovered endpoints.</summary>
+ this.loginBackground = function(frameManager, onLoginSuccess, onLoginFailure, timeout) {
this.discover(function(discoveryResult) {
if (discoveryResult) {
trace('Discovery succeeded and found ' + discoveryResult.length + ' OpenID service endpoints.');
if (discoveryResult.length > 0) {
- discoveryResult[0].loginPopup(onSuccess, onFailure);
+ discoveryResult.loginBackground(frameManager, onLoginSuccess, onLoginFailure, onLoginFailure, timeout);
} else {
trace("This doesn't look like an OpenID Identifier. Aborting login.");
- if (onFailure) {
- onFailure();
+ if (onLoginFailure) {
+ onLoginFailure();
}
}
}
@@ -148,3 +179,314 @@ window.OpenId = function(identifier) {
};
};
+/// <summary>Invoked by RP web server when an authentication has completed.</summary>
+/// <remarks>The duty of this method is to distribute the notification to the appropriate tracking object.</remarks>
+window.dnoa_internal.processAuthorizationResult = function(resultUrl) {
+ //trace('processAuthorizationResult ' + resultUrl);
+ var resultUri = new window.dnoa_internal.Uri(resultUrl);
+
+ // Find the tracking object responsible for this request.
+ var userSuppliedIdentifier = resultUri.getQueryArgValue('dnoa.userSuppliedIdentifier');
+ if (!userSuppliedIdentifier) {
+ trace('processAuthorizationResult called but no userSuppliedIdentifier parameter was found. Exiting function.');
+ return;
+ }
+ var discoveryResult = window.dnoa_internal.discoveryResults[userSuppliedIdentifier];
+ if (discoveryResult == null) {
+ trace('processAuthorizationResult called but no discovery result matching user supplied identifier ' + userSuppliedIdentifier + ' was found. Exiting function.');
+ return;
+ }
+
+ var opEndpoint = resultUri.getQueryArgValue("openid.op_endpoint") ? resultUri.getQueryArgValue("openid.op_endpoint") : resultUri.getQueryArgValue("dnoa.op_endpoint");
+ var respondingEndpoint = discoveryResult.findByEndpoint(opEndpoint);
+ trace('Auth result for ' + respondingEndpoint.host + ' received.'); //: ' + resultUrl);
+
+ if (window.dnoa_internal.isAuthSuccessful(resultUri)) {
+ discoveryResult.successAuthData = resultUrl;
+ respondingEndpoint.onAuthSuccess(resultUri);
+
+ var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(resultUri);
+ if (parsedPositiveAssertion.claimedIdentifier && parsedPositiveAssertion.claimedIdentifier != discoveryResult.claimedIdentifier) {
+ discoveryResult.claimedIdentifier = parsedPositiveAssertion.claimedIdentifier;
+ trace('Authenticated as ' + parsedPositiveAssertion.claimedIdentifier);
+ }
+ } else {
+ respondingEndpoint.onAuthFailed();
+ }
+};
+
+window.dnoa_internal.isAuthSuccessful = function(resultUri) {
+ if (window.dnoa_internal.isOpenID2Response(resultUri)) {
+ return resultUri.getQueryArgValue("openid.mode") == "id_res";
+ } else {
+ return resultUri.getQueryArgValue("openid.mode") == "id_res" && !resultUri.containsQueryArg("openid.user_setup_url");
+ }
+};
+
+window.dnoa_internal.isOpenID2Response = function(resultUri) {
+ return resultUri.containsQueryArg("openid.ns");
+};
+
+/// <summary>Instantiates an object that stores discovery results of some identifier.</summary>
+window.dnoa_internal.DiscoveryResult = function(identifier, discoveryInfo) {
+ var thisDiscoveryResult = this;
+
+ /// <summary>
+ /// Instantiates an object that describes an OpenID service endpoint and facilitates
+ /// initiating and tracking an authentication request.
+ /// </summary>
+ function ServiceEndpoint(requestInfo, userSuppliedIdentifier) {
+ this.immediate = requestInfo.immediate ? new window.dnoa_internal.Uri(requestInfo.immediate) : null;
+ this.setup = requestInfo.setup ? new window.dnoa_internal.Uri(requestInfo.setup) : null;
+ this.endpoint = new window.dnoa_internal.Uri(requestInfo.endpoint);
+ this.host = this.endpoint.getHost();
+ this.userSuppliedIdentifier = userSuppliedIdentifier;
+ var thisServiceEndpoint = this; // closure so that delegates have the right instance
+ this.loginPopup = function(onAuthSuccess, onAuthFailed) {
+ thisServiceEndpoint.abort(); // ensure no concurrent attempts
+ thisDiscoveryResult.onAuthSuccess = onAuthSuccess;
+ thisDiscoveryResult.onAuthFailed = onAuthFailed;
+ var width = 800;
+ var height = 600;
+ if (thisServiceEndpoint.setup.getQueryArgValue("openid.return_to").indexOf("dnoa.popupUISupported") >= 0) {
+ trace('This OP supports the UI extension. Using smaller window size.');
+ width = 450;
+ height = 500;
+ } else {
+ trace("This OP doesn't appear to support the UI extension. Using larger window size.");
+ }
+
+ var left = (screen.width - width) / 2;
+ var top = (screen.height - height) / 2;
+ thisServiceEndpoint.popup = window.open(thisServiceEndpoint.setup, 'opLogin', 'status=0,toolbar=0,location=1,resizable=1,scrollbars=1,left=' + left + ',top=' + top + ',width=' + width + ',height=' + height);
+
+ // If the OP supports the UI extension it MAY close its own window
+ // for a negative assertion. We must be able to recover from that scenario.
+ var thisServiceEndpointLocal = thisServiceEndpoint;
+ thisServiceEndpoint.popupCloseChecker = window.setInterval(function() {
+ if (thisServiceEndpointLocal.popup && thisServiceEndpointLocal.popup.closed) {
+ // The window closed, either because the user closed it, canceled at the OP,
+ // or approved at the OP and the popup window closed itself due to our script.
+ // If we were graying out the entire page while the child window was up,
+ // we would probably revert that here.
+ window.clearInterval(thisServiceEndpointLocal.popupCloseChecker);
+ thisServiceEndpointLocal.popup = null;
+
+ // The popup may have managed to inform us of the result already,
+ // so check whether the callback method was cleared already, which
+ // would indicate we've already processed this.
+ if (window.dnoa_internal.processAuthorizationResult) {
+ trace('User or OP canceled by closing the window.');
+ if (thisDiscoveryResult.onAuthFailed) {
+ thisDiscoveryResult.onAuthFailed(thisDiscoveryResult, thisServiceEndpoint);
+ }
+ window.dnoa_internal.processAuthorizationResult = null;
+ }
+ }
+ }, 250);
+ };
+
+ this.loginBackgroundJob = function(iframe, timeout) {
+ thisServiceEndpoint.abort(); // ensure no concurrent attempts
+ if (timeout) {
+ thisServiceEndpoint.timeout = setTimeout(function() { thisServiceEndpoint.onAuthenticationTimedOut(); }, timeout);
+ }
+ trace('iframe hosting ' + thisServiceEndpoint.endpoint + ' now OPENING (timeout ' + timeout + ').');
+ //trace('initiating auth attempt with: ' + thisServiceEndpoint.immediate);
+ thisServiceEndpoint.iframe = iframe;
+ return thisServiceEndpoint.immediate.toString();
+ };
+
+ this.busy = function() {
+ return thisServiceEndpoint.iframe != null || thisServiceEndpoint.popup != null;
+ };
+
+ this.completeAttempt = function(successful) {
+ if (!thisServiceEndpoint.busy()) return false;
+ window.clearInterval(thisServiceEndpoint.timeout);
+ if (thisServiceEndpoint.iframe) {
+ trace('iframe hosting ' + thisServiceEndpoint.endpoint + ' now CLOSING.');
+ thisDiscoveryResult.frameManager.closeFrame(thisServiceEndpoint.iframe);
+ thisServiceEndpoint.iframe = null;
+ }
+ if (thisServiceEndpoint.popup) {
+ thisServiceEndpoint.popup.close();
+ thisServiceEndpoint.popup = null;
+ }
+ if (thisServiceEndpoint.timeout) {
+ window.clearTimeout(thisServiceEndpoint.timeout);
+ thisServiceEndpoint.timeout = null;
+ }
+
+ if (!successful && !thisDiscoveryResult.busy() && thisDiscoveryResult.findSuccessfulRequest() == null) {
+ if (thisDiscoveryResult.onLastAttemptFailed) {
+ thisDiscoveryResult.onLastAttemptFailed();
+ }
+ }
+
+ return true;
+ };
+
+ this.onAuthenticationTimedOut = function() {
+ if (thisServiceEndpoint.completeAttempt()) {
+ trace(thisServiceEndpoint.host + " timed out");
+ thisServiceEndpoint.result = window.dnoa_internal.timedOut;
+ }
+ };
+
+ this.onAuthSuccess = function(authUri) {
+ if (thisServiceEndpoint.completeAttempt(true)) {
+ trace(thisServiceEndpoint.host + " authenticated!");
+ thisServiceEndpoint.result = window.dnoa_internal.authSuccess;
+ thisServiceEndpoint.claimedIdentifier = authUri//////////////////////////////////
+ thisServiceEndpoint.response = authUri;
+ thisDiscoveryResult.abortAll();
+ if (thisDiscoveryResult.onAuthSuccess) {
+ thisDiscoveryResult.onAuthSuccess(thisDiscoveryResult, thisServiceEndpoint);
+ }
+ }
+ };
+
+ this.onAuthFailed = function() {
+ if (thisServiceEndpoint.completeAttempt()) {
+ trace(thisServiceEndpoint.host + " failed authentication");
+ thisServiceEndpoint.result = window.dnoa_internal.authRefused;
+ if (thisDiscoveryResult.onAuthFailed) {
+ thisDiscoveryResult.onAuthFailed(thisDiscoveryResult, thisServiceEndpoint);
+ }
+ }
+ };
+
+ this.abort = function() {
+ if (thisServiceEndpoint.completeAttempt()) {
+ trace(thisServiceEndpoint.host + " aborted");
+ // leave the result as whatever it was before.
+ }
+ };
+
+ };
+
+ this.userSuppliedIdentifier = identifier;
+
+ if (discoveryInfo) {
+ this.claimedIdentifier = discoveryInfo.claimedIdentifier; // The claimed identifier may be null if the user provided an OP Identifier.
+ this.length = discoveryInfo.requests.length;
+ for (var i = 0; i < discoveryInfo.requests.length; i++) {
+ this[i] = new ServiceEndpoint(discoveryInfo.requests[i], identifier);
+ }
+ } else {
+ this.length = 0;
+ }
+
+ trace('Discovered claimed identifier: ' + (this.claimedIdentifier ? this.claimedIdentifier : "(directed identity)"));
+
+ // Add extra tracking bits and behaviors.
+ this.findByEndpoint = function(opEndpoint) {
+ for (var i = 0; i < thisDiscoveryResult.length; i++) {
+ if (thisDiscoveryResult[i].endpoint == opEndpoint) {
+ return thisDiscoveryResult[i];
+ }
+ }
+ };
+
+ this.busy = function() {
+ for (var i = 0; i < thisDiscoveryResult.length; i++) {
+ if (thisDiscoveryResult[i].busy()) {
+ return true;
+ }
+ }
+ };
+
+ // Add extra tracking bits and behaviors.
+ this.findSuccessfulRequest = function() {
+ for (var i = 0; i < thisDiscoveryResult.length; i++) {
+ if (thisDiscoveryResult[i].result === window.dnoa_internal.authSuccess) {
+ return thisDiscoveryResult[i];
+ }
+ }
+ };
+
+ this.abortAll = function() {
+ if (thisDiscoveryResult.frameManager) {
+ // Abort all other asynchronous authentication attempts that may be in progress.
+ thisDiscoveryResult.frameManager.cancelAllWork();
+ for (var i = 0; i < thisDiscoveryResult.length; i++) {
+ thisDiscoveryResult[i].abort();
+ }
+ } else {
+ trace('abortAll called without a frameManager being previously set.');
+ }
+ };
+
+ /// <summary>Initiates an asynchronous checkid_immediate login attempt against all possible service endpoints for an Identifier.</summary>
+ /// <param name="frameManager">The work queue for authentication iframes.</param>
+ /// <param name="onAuthSuccess">Fired when an endpoint responds affirmatively.</param>
+ /// <param name="onAuthFailed">Fired when an endpoint responds negatively.</param>
+ /// <param name="onLastAuthFailed">Fired when all authentication attempts have responded negatively or timed out.</param>
+ /// <param name="timeout">Timeout for an individual service endpoint to respond before the iframe closes.</param>
+ this.loginBackground = function(frameManager, onAuthSuccess, onAuthFailed, onLastAuthFailed, timeout) {
+ if (!frameManager) {
+ throw "No frameManager specified.";
+ }
+ if (thisDiscoveryResult.findSuccessfulRequest() != null) {
+ onAuthSuccess(thisDiscoveryResult, thisDiscoveryResult.findSuccessfulRequest());
+ } else {
+ thisDiscoveryResult.frameManager = frameManager;
+ thisDiscoveryResult.onAuthSuccess = onAuthSuccess;
+ thisDiscoveryResult.onAuthFailed = onAuthFailed;
+ thisDiscoveryResult.onLastAttemptFailed = onLastAuthFailed;
+ if (thisDiscoveryResult.length > 0) {
+ for (var i = 0; i < thisDiscoveryResult.length; i++) {
+ thisDiscoveryResult.frameManager.enqueueWork(thisDiscoveryResult[i].loginBackgroundJob, timeout);
+ }
+ }
+ }
+ };
+};
+
+/// <summary>
+/// Called in a page had an AJAX control that had already obtained a positive assertion
+/// when a postback occurred, and now that control wants to restore its 'authenticated' state.
+/// </summary>
+/// <param name="positiveAssertion">The string form of the URI that contains the positive assertion.</param>
+/// <param name="onAuthSuccess">Fired if the positive assertion is successfully processed, as if it had just come in.</param>
+window.dnoa_internal.deserializePreviousAuthentication = function(positiveAssertion, onAuthSuccess) {
+ if (!positiveAssertion || positiveAssertion.length === 0) {
+ return;
+ }
+
+ trace('Revitalizing an old positive assertion from a prior postback.');
+ var oldAuthResult = new window.dnoa_internal.Uri(positiveAssertion);
+
+ // The control ensures that we ALWAYS have an OpenID 2.0-style claimed_id attribute, even against
+ // 1.0 Providers via the return_to URL mechanism.
+ var parsedPositiveAssertion = new window.dnoa_internal.PositiveAssertion(positiveAssertion);
+
+ // We weren't given a full discovery history, but we can spoof this much from the
+ // authentication assertion.
+ trace('Deserialized claimed_id: ' + parsedPositiveAssertion.claimedIdentifier + ' and endpoint: ' + parsedPositiveAssertion.endpoint);
+ var discoveryInfo = {
+ claimedIdentifier: parsedPositiveAssertion.claimedIdentifier,
+ requests: [{ endpoint: parsedPositiveAssertion.endpoint }]
+ };
+
+ window.dnoa_internal.discoveryResults[box.value] = discoveryResult = new window.dnoa_internal.DiscoveryResult(parsedPositiveAssertion.userSuppliedIdentifier, discoveryInfo);
+ discoveryResult[0].result = window.dnoa_internal.authSuccess;
+ discoveryResult.successAuthData = positiveAssertion;
+
+ // restore old state from before postback
+ if (onAuthSuccess) {
+ onAuthSuccess(discoveryResult, discoveryResult[0]);
+ }
+};
+
+window.dnoa_internal.PositiveAssertion = function(uri) {
+ uri = new window.dnoa_internal.Uri(uri.toString());
+ this.endpoint = new window.dnoa_internal.Uri(uri.getQueryArgValue("dnoa.op_endpoint"));
+ this.userSuppliedIdentifier = uri.getQueryArgValue('dnoa.userSuppliedIdentifier');
+ this.claimedIdentifier = uri.getQueryArgValue('openid.claimed_id');
+ if (!this.claimedIdentifier) {
+ this.claimedIdentifier = uri.getQueryArgValue('dnoa.claimed_id');
+ }
+ this.toString = function() { return uri.toString(); };
+};
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 37d5881..0e054ac 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -30,12 +30,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// A common base class for OpenID Relying Party controls.
/// </summary>
[DefaultProperty("Identifier"), ValidationProperty("Identifier")]
- public abstract class OpenIdRelyingPartyControlBase : Control {
+ public abstract class OpenIdRelyingPartyControlBase : Control, IDisposable {
/// <summary>
/// The manifest resource name of the javascript file to include on the hosting page.
/// </summary>
internal const string EmbeddedJavascriptResource = Util.DefaultNamespace + ".OpenId.RelyingParty.OpenIdRelyingPartyControlBase.js";
+ /// <summary>
+ /// The cookie used to persist the Identifier the user logged in with.
+ /// </summary>
+ internal const string PersistentIdentifierCookieName = OpenIdUtilities.CustomParameterPrefix + "OpenIDIdentifier";
+
+ /// <summary>
+ /// The callback parameter name to use to store which control initiated the auth request.
+ /// </summary>
+ internal const string ReturnToReceivingControlId = OpenIdUtilities.CustomParameterPrefix + "receiver";
+
#region Property category constants
/// <summary>
@@ -55,6 +65,31 @@ 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";
+
+ /// <summary>
+ /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property.
+ /// </summary>
+ private const string UsePersistentCookieCallbackKey = OpenIdUtilities.CustomParameterPrefix + "UsePersistentCookie";
+
+ /// <summary>
+ /// The callback parameter to use for recognizing when the callback is in the parent window.
+ /// </summary>
+ private const string UIPopupCallbackParentKey = OpenIdUtilities.CustomParameterPrefix + "uipopupParent";
+
+ #endregion
+
#region Property default values
/// <summary>
@@ -70,7 +105,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Default value of <see cref="UsePersistentCookie"/>.
/// </summary>
- private const bool UsePersistentCookieDefault = false;
+ private const LoginPersistence UsePersistentCookieDefault = LoginPersistence.Session;
+
+ /// <summary>
+ /// Default value of <see cref="LoginMode"/>.
+ /// </summary>
+ private const LoginSiteNotification LoginModeDefault = LoginSiteNotification.FormsAuthentication;
/// <summary>
/// The default value for the <see cref="RealmUrl"/> property.
@@ -102,6 +142,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string UsePersistentCookieViewStateKey = "UsePersistentCookie";
/// <summary>
+ /// The viewstate key to use for the <see cref="LoginMode"/> property.
+ /// </summary>
+ private const string LoginModeViewStateKey = "LoginMode";
+
+ /// <summary>
/// The viewstate key to use for the <see cref="RealmUrl"/> property.
/// </summary>
private const string RealmUrlViewStateKey = "RealmUrl";
@@ -128,40 +173,21 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
- #region Callback parameter names
-
- /// <summary>
- /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property.
- /// </summary>
- private const string UsePersistentCookieCallbackKey = OpenIdUtilities.CustomParameterPrefix + "UsePersistentCookie";
-
- /// <summary>
- /// The callback parameter to use for recognizing when the callback is in a popup window.
- /// </summary>
- private const string UIPopupCallbackKey = OpenIdUtilities.CustomParameterPrefix + "uipopup";
-
/// <summary>
- /// The callback parameter to use for recognizing when the callback is in the parent window.
+ /// The lifetime of the cookie used to persist the Identifier the user logged in with.
/// </summary>
- private const string UIPopupCallbackParentKey = OpenIdUtilities.CustomParameterPrefix + "uipopupParent";
+ private static readonly TimeSpan PersistentIdentifierTimeToLiveDefault = TimeSpan.FromDays(14);
/// <summary>
- /// The callback parameter name to use to store which control initiated the auth request.
- /// </summary>
- private const string ReturnToReceivingControlId = OpenIdUtilities.CustomParameterPrefix + "receiver";
-
- /// <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.
+ /// Backing field for the <see cref="RelyingParty"/> property.
/// </summary>
- private const string PopupUISupportedJsHint = "dotnetopenid.popupUISupported";
-
- #endregion
+ private OpenIdRelyingParty relyingParty;
/// <summary>
- /// Backing field for the <see cref="RelyingParty"/> property.
+ /// A value indicating whether the <see cref="relyingParty"/> field contains
+ /// an instance that we own and should Dispose.
/// </summary>
- private OpenIdRelyingParty relyingParty;
+ private bool relyingPartyOwned;
/// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartyControlBase"/> class.
@@ -172,11 +198,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Events
/// <summary>
- /// Fired after the user clicks the log in button, but before the authentication
- /// process begins. Offers a chance for the web application to disallow based on
- /// OpenID URL before redirecting the user to the OpenID Provider.
+ /// Fired when the user has typed in their identifier, discovery was successful
+ /// and a login attempt is about to begin.
/// </summary>
- [Description("Fired after the user clicks the log in button, but before the authentication process begins. Offers a chance for the web application to disallow based on OpenID URL before redirecting the user to the OpenID Provider."), Category(OpenIdCategory)]
+ [Description("Fired when the user has typed in their identifier, discovery was successful and a login attempt is about to begin."), Category(OpenIdCategory)]
public event EventHandler<OpenIdEventArgs> LoggingIn;
/// <summary>
@@ -200,6 +225,49 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// Methods of indicating to the rest of the web site that the user has logged in.
+ /// </summary>
+ public enum LoginSiteNotification {
+ /// <summary>
+ /// The rest of the web site is unaware that the user just completed an OpenID login.
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// After the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event is fired
+ /// the control automatically calls <see cref="System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string, bool)"/>
+ /// with the <see cref="IAuthenticationResponse.ClaimedIdentifier"/> as the username
+ /// unless the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event handler sets
+ /// <see cref="OpenIdEventArgs.Cancel"/> property to true.
+ /// </summary>
+ FormsAuthentication,
+ }
+
+ /// <summary>
+ /// How an OpenID user session should be persisted across visits.
+ /// </summary>
+ public enum LoginPersistence {
+ /// <summary>
+ /// The user should only be logged in as long as the browser window remains open.
+ /// Nothing is persisted to help the user on a return visit. Public kiosk mode.
+ /// </summary>
+ Session,
+
+ /// <summary>
+ /// The user should only be logged in as long as the browser window remains open.
+ /// The OpenID Identifier is persisted to help expedite re-authentication when
+ /// the user visits the next time.
+ /// </summary>
+ SessionAndPersistentIdentifier,
+
+ /// <summary>
+ /// The user is issued a persistent authentication ticket so that no login is
+ /// necessary on their return visit.
+ /// </summary>
+ PersistentAuthentication,
+ }
+
+ /// <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>
@@ -215,12 +283,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
get {
if (this.relyingParty == null) {
this.relyingParty = this.CreateRelyingParty();
+ this.relyingPartyOwned = true;
}
return this.relyingParty;
}
set {
+ if (this.relyingPartyOwned && this.relyingParty != null) {
+ this.relyingParty.Dispose();
+ }
+
this.relyingParty = value;
+ this.relyingPartyOwned = false;
}
}
@@ -306,12 +380,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Bindable(true), DefaultValue(UsePersistentCookieDefault), Category(BehaviorCategory)]
[Description("Whether to send a persistent cookie upon successful " +
"login so the user does not have to log in upon returning to this site.")]
- public virtual bool UsePersistentCookie {
- get { return (bool)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); }
+ public virtual LoginPersistence UsePersistentCookie {
+ get { return (LoginPersistence)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); }
set { this.ViewState[UsePersistentCookieViewStateKey] = value; }
}
/// <summary>
+ /// Gets or sets the way a completed login is communicated to the rest of the web site.
+ /// </summary>
+ [Bindable(true), DefaultValue(LoginModeDefault), Category(BehaviorCategory)]
+ [Description("The way a completed login is communicated to the rest of the web site.")]
+ public virtual LoginSiteNotification LoginMode {
+ get { return (LoginSiteNotification)(this.ViewState[LoginModeViewStateKey] ?? LoginModeDefault); }
+ set { this.ViewState[LoginModeViewStateKey] = value; }
+ }
+
+ /// <summary>
/// Gets or sets a value indicating when to use a popup window to complete the login experience.
/// </summary>
/// <value>The default value is <see cref="PopupBehavior.Never"/>.</value>
@@ -351,11 +435,31 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
internal AssociationPreference AssociationPreference { get; set; }
/// <summary>
+ /// Clears any cookie set by this control to help the user on a returning visit next time.
+ /// </summary>
+ public static void LogOff() {
+ HttpContext.Current.Response.SetCookie(CreateIdentifierPersistingCookie(null));
+ }
+
+ /// <summary>
/// Immediately redirects to the OpenID Provider to verify the Identifier
/// provided in the text box.
/// </summary>
public void LogOn() {
IAuthenticationRequest request = this.CreateRequests().FirstOrDefault();
+ ErrorUtilities.VerifyProtocol(request != null, OpenIdStrings.OpenIdEndpointNotFound);
+ this.LogOn(request);
+ }
+
+ /// <summary>
+ /// Immediately redirects to the OpenID Provider to verify the Identifier
+ /// provided in the text box.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void LogOn(IAuthenticationRequest request) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ ErrorUtilities.VerifyArgumentNotNull(request, "request");
+
if (this.IsPopupAppropriate(request)) {
this.ScriptPopupWindow(request);
} else {
@@ -364,6 +468,29 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Enables a server control to perform final clean up before it is released from memory.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
+ public sealed override void Dispose() {
+ this.Dispose(true);
+ base.Dispose();
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources
+ /// </summary>
+ /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ if (this.relyingPartyOwned && this.relyingParty != null) {
+ this.relyingParty.Dispose();
+ this.relyingParty = null;
+ }
+ }
+ }
+
+ /// <summary>
/// Creates the authentication requests for a given user-supplied Identifier.
/// </summary>
/// <returns>A sequence of authentication requests, any one of which may be
@@ -403,31 +530,31 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Configure each generated request.
foreach (var req in requests) {
if (this.IsPopupAppropriate(req)) {
- // Inform the OP that we'll be using a popup window.
- req.AddExtension(new UIRequest());
-
// Inform ourselves in return_to that we're in a popup.
- req.AddCallbackArguments(UIPopupCallbackKey, "1");
+ req.SetCallbackArgument(UIPopupCallbackKey, "1");
if (req.Provider.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.AddCallbackArguments(PopupUISupportedJsHint, "1");
+ req.SetCallbackArgument(PopupUISupportedJsHint, "1");
}
}
// Add state that needs to survive across the redirect.
if (!this.Stateless) {
- req.AddCallbackArguments(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture));
- req.AddCallbackArguments(ReturnToReceivingControlId, this.ClientID);
+ req.SetCallbackArgument(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString());
+ req.SetCallbackArgument(ReturnToReceivingControlId, this.ClientID);
}
((AuthenticationRequest)req).AssociationPreference = this.AssociationPreference;
- this.OnLoggingIn(req);
-
- yield return req;
+ if (this.OnLoggingIn(req)) {
+ yield return req;
+ }
}
}
@@ -443,12 +570,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return;
}
+ if (this.Identifier == null) {
+ this.TryPresetIdentifierWithCookie();
+ }
+
// Take an unreliable sneek peek to see if we're in a popup and an OpenID
// assertion is coming in. We shouldn't process assertions in a popup window.
if (this.Page.Request.QueryString[UIPopupCallbackKey] == "1" && this.Page.Request.QueryString[UIPopupCallbackParentKey] == null) {
// We're in a popup window. We need to close it and pass the
// message back to the parent window for processing.
- this.ScriptClosingPopup();
+ this.ScriptClosingPopupOrIFrame();
return; // don't do any more processing on it now
}
@@ -457,33 +588,41 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
string receiver = this.Page.Request.QueryString[ReturnToReceivingControlId] ?? this.Page.Request.Form[ReturnToReceivingControlId];
if (receiver == null || receiver == this.ClientID) {
var response = this.RelyingParty.GetResponse();
- if (response != null) {
- string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
- bool persistentBool;
- if (persistentString != null && bool.TryParse(persistentString, out persistentBool)) {
- this.UsePersistentCookie = persistentBool;
- }
+ this.ProcessResponse(response);
+ }
+ }
- switch (response.Status) {
- case AuthenticationStatus.Authenticated:
- this.OnLoggedIn(response);
- break;
- case AuthenticationStatus.Canceled:
- this.OnCanceled(response);
- break;
- case AuthenticationStatus.Failed:
- this.OnFailed(response);
- break;
- case AuthenticationStatus.SetupRequired:
- case AuthenticationStatus.ExtensionsOnly:
- default:
- // The NotApplicable (extension-only assertion) is NOT one that we support
- // in this control because that scenario is primarily interesting to RPs
- // that are asking a specific OP, and it is not user-initiated as this textbox
- // is designed for.
- throw new InvalidOperationException(MessagingStrings.UnexpectedMessageReceivedOfMany);
- }
- }
+ /// <summary>
+ /// Processes the response.
+ /// </summary>
+ /// <param name="response">The response.</param>
+ protected virtual void ProcessResponse(IAuthenticationResponse response) {
+ if (response == null) {
+ return;
+ }
+ string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
+ if (persistentString != null) {
+ this.UsePersistentCookie = (LoginPersistence)Enum.Parse(typeof(LoginPersistence), persistentString);
+ }
+
+ switch (response.Status) {
+ case AuthenticationStatus.Authenticated:
+ this.OnLoggedIn(response);
+ break;
+ case AuthenticationStatus.Canceled:
+ this.OnCanceled(response);
+ break;
+ case AuthenticationStatus.Failed:
+ this.OnFailed(response);
+ break;
+ case AuthenticationStatus.SetupRequired:
+ case AuthenticationStatus.ExtensionsOnly:
+ default:
+ // The NotApplicable (extension-only assertion) is NOT one that we support
+ // in this control because that scenario is primarily interesting to RPs
+ // that are asking a specific OP, and it is not user-initiated as this textbox
+ // is designed for.
+ throw new InvalidOperationException(MessagingStrings.UnexpectedMessageReceivedOfMany);
}
}
@@ -512,7 +651,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
if (!args.Cancel) {
- FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie);
+ if (this.UsePersistentCookie == LoginPersistence.SessionAndPersistentIdentifier) {
+ Page.Response.SetCookie(CreateIdentifierPersistingCookie(response));
+ }
+
+ switch (this.LoginMode) {
+ case LoginSiteNotification.FormsAuthentication:
+ FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie == LoginPersistence.PersistentAuthentication);
+ break;
+ case LoginSiteNotification.None:
+ default:
+ break;
+ }
}
}
@@ -569,8 +719,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <returns>The instantiated relying party.</returns>
protected virtual OpenIdRelyingParty CreateRelyingParty() {
+ return this.CreateRelyingParty(true);
+ }
+
+ /// <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>
+ /// <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 = new OpenIdRelyingParty(store);
+ var rp = verifySignature ? new OpenIdRelyingParty(store) : OpenIdRelyingParty.CreateNonVerifying();
// Only set RequireSsl to true, as we don't want to override
// a .config setting of true with false.
@@ -628,6 +790,57 @@ 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>
+ /// <returns>An persistent cookie.</returns>
+ private static HttpCookie CreateIdentifierPersistingCookie(IAuthenticationResponse response) {
+ HttpCookie cookie = new HttpCookie(PersistentIdentifierCookieName);
+ bool clearingCookie = false;
+
+ // We'll try to store whatever it was the user originally typed in, but fallback
+ // to the final claimed_id.
+ if (response != null && response.Status == AuthenticationStatus.Authenticated) {
+ var positiveResponse = (PositiveAuthenticationResponse)response;
+
+ // We must escape the value because XRIs start with =, and any leading '=' gets dropped (by ASP.NET?)
+ cookie.Value = Uri.EscapeDataString(positiveResponse.Endpoint.UserSuppliedIdentifier ?? response.ClaimedIdentifier);
+ } else {
+ clearingCookie = true;
+ cookie.Value = string.Empty;
+ if (HttpContext.Current.Request.Browser["supportsEmptyStringInCookieValue"] == "false") {
+ cookie.Value = "NoCookie";
+ }
+ }
+
+ if (clearingCookie) {
+ // mark the cookie has having already expired to cause the user agent to delete
+ // the old persisted cookie.
+ cookie.Expires = DateTime.Now.Subtract(TimeSpan.FromDays(1));
+ } else {
+ // Make the cookie persistent by setting an expiration date
+ cookie.Expires = DateTime.Now + PersistentIdentifierTimeToLiveDefault;
+ }
+
+ return cookie;
+ }
+
+ /// <summary>
/// Gets the javascript to executee to redirect or POST an OpenID message to a remote party.
/// </summary>
/// <param name="request">The authentication request to send.</param>
@@ -655,27 +868,30 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
startupScript.AppendLine("window.dnoa_internal = new Object();");
startupScript.AppendLine("window.dnoa_internal.processAuthorizationResult = function(uri) { window.location = uri; };");
startupScript.AppendLine("window.dnoa_internal.popupWindow = function() {");
- startupScript.AppendFormat(
- @"\tvar openidPopup = {0}",
- UIUtilities.GetWindowPopupScript(this.RelyingParty, request, "openidPopup"));
+ startupScript.AppendFormat(
+ @"\tvar openidPopup = {0}",
+ UIUtilities.GetWindowPopupScript(this.RelyingParty, request, "openidPopup"));
startupScript.AppendLine("};");
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "loginPopup", startupScript.ToString(), true);
}
/// <summary>
- /// Wires the popup window to close itself and pass the authentication result to the parent window.
+ /// Tries to preset the <see cref="Identifier"/> property based on a persistent
+ /// cookie on the browser.
/// </summary>
- private void ScriptClosingPopup() {
- StringBuilder startupScript = new StringBuilder();
- startupScript.AppendLine("window.opener.dnoa_internal.processAuthorizationResult(document.URL + '&" + UIPopupCallbackParentKey + "=1');");
- startupScript.AppendLine("window.close();");
-
- this.Page.ClientScript.RegisterStartupScript(typeof(OpenIdRelyingPartyControlBase), "loginPopupClose", startupScript.ToString(), true);
+ /// <returns>
+ /// A value indicating whether the <see cref="Identifier"/> property was
+ /// successfully preset to some non-empty value.
+ /// </returns>
+ private bool TryPresetIdentifierWithCookie() {
+ HttpCookie cookie = this.Page.Request.Cookies[PersistentIdentifierCookieName];
+ if (cookie != null) {
+ this.Identifier = Uri.UnescapeDataString(cookie.Value);
+ return 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.
+ return false;
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js
index 3a17b7b..4496445 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.js
@@ -25,11 +25,6 @@ if (window.dnoa_internal === undefined) {
window.dnoa_internal = new Object();
};
-// The possible authentication results
-window.dnoa_internal.authSuccess = new Object();
-window.dnoa_internal.authRefused = new Object();
-window.dnoa_internal.timedOut = new Object();
-
/// <summary>Instantiates an object that provides string manipulation services for URIs.</summary>
window.dnoa_internal.Uri = function(url) {
this.originalUri = url.toString();
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
index 5fe8646..1fb227d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs
@@ -40,7 +40,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
[DefaultProperty("Text"), ValidationProperty("Text")]
[ToolboxData("<{0}:OpenIdTextBox runat=\"server\" />")]
- public class OpenIdTextBox : CompositeControl, IEditableTextControl, ITextControl {
+ public class OpenIdTextBox : OpenIdRelyingPartyControlBase, IEditableTextControl, ITextControl, IPostBackDataHandler {
/// <summary>
/// The name of the manifest stream containing the
/// OpenID logo that is placed inside the text box.
@@ -52,38 +52,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
protected const short TabIndexDefault = 0;
- /// <summary>
- /// Default value of <see cref="UsePersistentCookie"/>.
- /// </summary>
- protected const bool UsePersistentCookieDefault = false;
-
#region Property category constants
/// <summary>
- /// The "Appearance" category for properties.
- /// </summary>
- private const string AppearanceCategory = "Appearance";
-
- /// <summary>
/// The "Simple Registration" category for properties.
/// </summary>
private const string ProfileCategory = "Simple Registration";
- /// <summary>
- /// The "Behavior" category for properties.
- /// </summary>
- private const string BehaviorCategory = "Behavior";
-
#endregion
#region Property viewstate keys
/// <summary>
- /// The viewstate key to use for the <see cref="Popup"/> property.
- /// </summary>
- private const string PopupViewStateKey = "Popup";
-
- /// <summary>
/// The viewstate key to use for the <see cref="RequestEmail"/> property.
/// </summary>
private const string RequestEmailViewStateKey = "RequestEmail";
@@ -104,11 +84,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string RequestCountryViewStateKey = "RequestCountry";
/// <summary>
- /// The viewstate key to use for the <see cref="RequireSsl"/> property.
- /// </summary>
- private const string RequireSslViewStateKey = "RequireSsl";
-
- /// <summary>
/// The viewstate key to use for the <see cref="RequestLanguage"/> property.
/// </summary>
private const string RequestLanguageViewStateKey = "RequestLanguage";
@@ -144,43 +119,48 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string ShowLogoViewStateKey = "ShowLogo";
/// <summary>
- /// The viewstate key to use for the <see cref="UsePersistentCookie"/> property.
- /// </summary>
- private const string UsePersistentCookieViewStateKey = "UsePersistentCookie";
-
- /// <summary>
/// The viewstate key to use for the <see cref="RequestGender"/> property.
/// </summary>
private const string RequestGenderViewStateKey = "RequestGender";
/// <summary>
- /// The viewstate key to use for the <see cref="ReturnToUrl"/> property.
+ /// The viewstate key to use for the <see cref="RequestBirthDate"/> property.
/// </summary>
- private const string ReturnToUrlViewStateKey = "ReturnToUrl";
+ private const string RequestBirthDateViewStateKey = "RequestBirthDate";
/// <summary>
- /// The viewstate key to use for the <see cref="Stateless"/> property.
+ /// The viewstate key to use for the <see cref="CssClass"/> property.
/// </summary>
- private const string StatelessViewStateKey = "Stateless";
+ private const string CssClassViewStateKey = "CssClass";
/// <summary>
- /// The viewstate key to use for the <see cref="RequestBirthDate"/> property.
+ /// The viewstate key to use for the <see cref="MaxLength"/> property.
/// </summary>
- private const string RequestBirthDateViewStateKey = "RequestBirthDate";
+ private const string MaxLengthViewStateKey = "MaxLength";
/// <summary>
- /// The viewstate key to use for the <see cref="RealmUrl"/> property.
+ /// The viewstate key to use for the <see cref="Columns"/> property.
/// </summary>
- private const string RealmUrlViewStateKey = "RealmUrl";
+ private const string ColumnsViewStateKey = "Columns";
- #endregion
+ /// <summary>
+ /// The viewstate key to use for the <see cref="TabIndex"/> property.
+ /// </summary>
+ private const string TabIndexViewStateKey = "TabIndex";
- #region Property defaults
+ /// <summary>
+ /// The viewstate key to use for the <see cref="Enabled"/> property.
+ /// </summary>
+ private const string EnabledViewStateKey = "Enabled";
/// <summary>
- /// The default value for the <see cref="Popup"/> property.
+ /// The viewstate key to use for the <see cref="Name"/> property.
/// </summary>
- private const PopupBehavior PopupDefault = PopupBehavior.Never;
+ private const string NameViewStateKey = "Name";
+
+ #endregion
+
+ #region Property defaults
/// <summary>
/// The default value for the <see cref="Columns"/> property.
@@ -193,19 +173,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const int MaxLengthDefault = 40;
/// <summary>
- /// The default value for the <see cref="EnableRequestProfile"/> property.
- /// </summary>
- private const bool EnableRequestProfileDefault = true;
-
- /// <summary>
- /// The default value for the <see cref="RequireSsl"/> property.
+ /// The default value for the <see cref="Name"/> property.
/// </summary>
- private const bool RequireSslDefault = false;
+ private const string NameDefault = "openid_identifier";
/// <summary>
- /// The default value for the <see cref="Stateless"/> property.
+ /// The default value for the <see cref="EnableRequestProfile"/> property.
/// </summary>
- private const bool StatelessDefault = false;
+ private const bool EnableRequestProfileDefault = true;
/// <summary>
/// The default value for the <see cref="ShowLogo"/> property.
@@ -228,21 +203,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string CssClassDefault = "openid";
/// <summary>
- /// The default value for the <see cref="ReturnToUrl"/> property.
- /// </summary>
- private const string ReturnToUrlDefault = "";
-
- /// <summary>
/// The default value for the <see cref="Text"/> property.
/// </summary>
private const string TextDefault = "";
/// <summary>
- /// The default value for the <see cref="RealmUrl"/> property.
- /// </summary>
- private const string RealmUrlDefault = "~/";
-
- /// <summary>
/// The default value for the <see cref="RequestEmail"/> property.
/// </summary>
private const DemandLevel RequestEmailDefault = DemandLevel.NoRequest;
@@ -290,79 +255,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
- /// The callback parameter to use for recognizing when the callback is in a popup window.
- /// </summary>
- private const string UIPopupCallbackKey = OpenIdUtilities.CustomParameterPrefix + "uipopup";
-
- /// <summary>
- /// The callback parameter to use for recognizing when the callback is in the parent window.
- /// </summary>
- private const string UIPopupCallbackParentKey = OpenIdUtilities.CustomParameterPrefix + "uipopupParent";
-
- /// <summary>
- /// The callback parameter for use with persisting the <see cref="UsePersistentCookie"/> property.
- /// </summary>
- private const string UsePersistentCookieCallbackKey = "OpenIdTextBox_UsePersistentCookie";
-
- /// <summary>
- /// The text in the text box before the text box is instantiated.
+ /// An empty sreg request, used to compare with others to see if they too are empty.
/// </summary>
- private string text = TextDefault;
-
- /// <summary>
- /// The text box itself.
- /// </summary>
- private TextBox wrappedTextBox;
-
- /// <summary>
- /// Backing field for the <see cref="RelyingParty"/> property.
- /// </summary>
- private OpenIdRelyingParty relyingParty;
+ private static readonly ClaimsRequest EmptyClaimsRequest = new ClaimsRequest();
/// <summary>
/// Initializes a new instance of the <see cref="OpenIdTextBox"/> class.
/// </summary>
public OpenIdTextBox() {
- this.InitializeControls();
}
- #region Events
-
- /// <summary>
- /// Fired upon completion of a successful login.
- /// </summary>
- [Description("Fired upon completion of a successful login.")]
- public event EventHandler<OpenIdEventArgs> LoggedIn;
-
- /// <summary>
- /// Fired when a login attempt fails.
- /// </summary>
- [Description("Fired when a login attempt fails.")]
- public event EventHandler<OpenIdEventArgs> Failed;
-
- /// <summary>
- /// Fired when an authentication attempt is canceled at the OpenID Provider.
- /// </summary>
- [Description("Fired when an authentication attempt is canceled at the OpenID Provider.")]
- public event EventHandler<OpenIdEventArgs> Canceled;
-
- /// <summary>
- /// Fired when an Immediate authentication attempt fails, and the Provider suggests using non-Immediate mode.
- /// </summary>
- [Description("Fired when an Immediate authentication attempt fails, and the Provider suggests using non-Immediate mode.")]
- public event EventHandler<OpenIdEventArgs> SetupRequired;
-
- #endregion
-
#region IEditableTextControl Members
/// <summary>
/// Occurs when the content of the text changes between posts to the server.
/// </summary>
- public event EventHandler TextChanged {
- add { this.WrappedTextBox.TextChanged += value; }
- remove { this.WrappedTextBox.TextChanged -= value; }
- }
+ public event EventHandler TextChanged;
#endregion
@@ -374,102 +282,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Bindable(true), DefaultValue(""), Category(AppearanceCategory)]
[Description("The content of the text box.")]
public string Text {
- get {
- return this.WrappedTextBox != null ? this.WrappedTextBox.Text : this.text;
- }
-
- set {
- this.text = value;
- if (this.WrappedTextBox != null) {
- this.WrappedTextBox.Text = value;
- }
- }
- }
-
- /// <summary>
- /// Gets or sets the OpenID <see cref="Realm"/> of the relying party web site.
- /// </summary>
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")]
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using ctor for validation.")]
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")]
- [Bindable(true), DefaultValue(RealmUrlDefault), Category(BehaviorCategory)]
- [Description("The OpenID Realm of the relying party web site.")]
- [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
- public string RealmUrl {
- get {
- return (string)(ViewState[RealmUrlViewStateKey] ?? RealmUrlDefault);
- }
-
- set {
- 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.
- } else {
- // We can't fully test it, but it should start with either ~/ or a protocol.
- if (Regex.IsMatch(value, @"^https?://")) {
- new Uri(value.Replace("*.", string.Empty)); // make sure it's fully-qualified, but ignore wildcards
- } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
- // this is valid too
- } else {
- throw new UriFormatException();
- }
- }
- ViewState[RealmUrlViewStateKey] = value;
- }
- }
-
- /// <summary>
- /// Gets or sets the OpenID ReturnTo of the relying party web site.
- /// </summary>
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Bindable property must be simple type")]
- [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")]
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")]
- [Bindable(true), DefaultValue(ReturnToUrlDefault), Category(BehaviorCategory)]
- [Description("The OpenID ReturnTo of the relying party web site.")]
- [UrlProperty, Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
- public string ReturnToUrl {
- get {
- return (string)(this.ViewState[ReturnToUrlViewStateKey] ?? ReturnToUrlDefault);
- }
-
- set {
- if (this.Page != null && !this.DesignMode) {
- // Validate new value by trying to construct a Uri based on it.
- new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(value)); // throws an exception on failure.
- } else {
- // We can't fully test it, but it should start with either ~/ or a protocol.
- if (Regex.IsMatch(value, @"^https?://")) {
- new Uri(value); // make sure it's fully-qualified, but ignore wildcards
- } else if (value.StartsWith("~/", StringComparison.Ordinal)) {
- // this is valid too
- } else {
- throw new UriFormatException();
- }
- }
-
- this.ViewState[ReturnToUrlViewStateKey] = value;
- }
- }
-
- /// <summary>
- /// Gets or sets a value indicating when to use a popup window to complete the login experience.
- /// </summary>
- /// <value>The default value is <see cref="PopupBehavior.Never"/>.</value>
- [Bindable(true), DefaultValue(PopupDefault), Category(BehaviorCategory)]
- [Description("When to use a popup window to complete the login experience.")]
- public PopupBehavior Popup {
- get { return (PopupBehavior)(ViewState[PopupViewStateKey] ?? PopupDefault); }
- set { ViewState[PopupViewStateKey] = value; }
+ get { return this.Identifier != null ? this.Identifier.OriginalString : string.Empty; }
+ set { this.Identifier = value; }
}
/// <summary>
- /// Gets or sets a value indicating whether stateless mode is used.
+ /// Gets or sets the form name to use for this input field.
/// </summary>
- [Bindable(true), DefaultValue(StatelessDefault), Category(BehaviorCategory)]
- [Description("Controls whether stateless mode is used.")]
- public bool Stateless {
- get { return (bool)(ViewState[StatelessViewStateKey] ?? StatelessDefault); }
- set { ViewState[StatelessViewStateKey] = value; }
+ [Bindable(true), DefaultValue(NameDefault), Category(BehaviorCategory)]
+ [Description("The form name of this input field.")]
+ public string Name {
+ get { return (string)(this.ViewState[NameViewStateKey] ?? NameDefault); }
+ set { this.ViewState[NameViewStateKey] = value; }
}
/// <summary>
@@ -477,9 +301,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
[Bindable(true), DefaultValue(CssClassDefault), Category(AppearanceCategory)]
[Description("The CSS class assigned to the text box.")]
- public override string CssClass {
- get { return this.WrappedTextBox.CssClass; }
- set { this.WrappedTextBox.CssClass = value; }
+ public string CssClass {
+ get { return (string)this.ViewState[CssClassViewStateKey]; }
+ set { this.ViewState[CssClassViewStateKey] = value; }
}
/// <summary>
@@ -503,25 +327,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Gets or sets a value indicating whether to send a persistent cookie upon successful
- /// login so the user does not have to log in upon returning to this site.
- /// </summary>
- [Bindable(true), DefaultValue(UsePersistentCookieDefault), Category(BehaviorCategory)]
- [Description("Whether to send a persistent cookie upon successful " +
- "login so the user does not have to log in upon returning to this site.")]
- public virtual bool UsePersistentCookie {
- get { return (bool)(this.ViewState[UsePersistentCookieViewStateKey] ?? UsePersistentCookieDefault); }
- set { this.ViewState[UsePersistentCookieViewStateKey] = value; }
- }
-
- /// <summary>
/// Gets or sets the width of the text box in characters.
/// </summary>
[Bindable(true), DefaultValue(ColumnsDefault), Category(AppearanceCategory)]
[Description("The width of the text box in characters.")]
public int Columns {
- get { return this.WrappedTextBox.Columns; }
- set { this.WrappedTextBox.Columns = value; }
+ get { return (int)(this.ViewState[ColumnsViewStateKey] ?? ColumnsDefault); }
+ set { this.ViewState[ColumnsViewStateKey] = value; }
}
/// <summary>
@@ -530,8 +342,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[Bindable(true), DefaultValue(MaxLengthDefault), Category(AppearanceCategory)]
[Description("The maximum number of characters the browser should allow.")]
public int MaxLength {
- get { return this.WrappedTextBox.MaxLength; }
- set { this.WrappedTextBox.MaxLength = value; }
+ get { return (int)(this.ViewState[MaxLengthViewStateKey] ?? MaxLengthDefault); }
+ set { this.ViewState[MaxLengthViewStateKey] = value; }
}
/// <summary>
@@ -546,9 +358,21 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </exception>
[Bindable(true), DefaultValue(TabIndexDefault), Category(BehaviorCategory)]
[Description("The tab index of the text box control.")]
- public override short TabIndex {
- get { return this.WrappedTextBox.TabIndex; }
- set { this.WrappedTextBox.TabIndex = value; }
+ public virtual short TabIndex {
+ get { return (short)(this.ViewState[TabIndexViewStateKey] ?? TabIndexDefault); }
+ set { this.ViewState[TabIndexViewStateKey] = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="OpenIdTextBox"/> is enabled
+ /// in the browser for editing and will respond to incoming OpenID messages.
+ /// </summary>
+ /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
+ [Bindable(true), DefaultValue(true), Category(BehaviorCategory)]
+ [Description("Whether the control is editable in the browser and will respond to OpenID messages.")]
+ public bool Enabled {
+ get { return (bool)(this.ViewState[EnabledViewStateKey] ?? true); }
+ set { this.ViewState[EnabledViewStateKey] = value; }
}
/// <summary>
@@ -673,344 +497,42 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
set { ViewState[EnableRequestProfileViewStateKey] = value; }
}
- /// <summary>
- /// Gets or sets a value indicating whether to enforce on high security mode,
- /// which requires the full authentication pipeline to be protected by SSL.
- /// </summary>
- [Bindable(true), DefaultValue(RequireSslDefault), Category(BehaviorCategory)]
- [Description("Turns on high security mode, requiring the full authentication pipeline to be protected by SSL.")]
- public bool RequireSsl {
- get { return (bool)(ViewState[RequireSslViewStateKey] ?? RequireSslDefault); }
- set { ViewState[RequireSslViewStateKey] = value; }
- }
-
- /// <summary>
- /// Gets or sets the type of the custom application store to use, or <c>null</c> to use the default.
- /// </summary>
- /// <remarks>
- /// If set, this property must be set in each Page Load event
- /// as it is not persisted across postbacks.
- /// </remarks>
- public IRelyingPartyApplicationStore CustomApplicationStore { get; set; }
-
#endregion
- #region Properties to hide
-
- /// <summary>
- /// Gets or sets the foreground color (typically the color of the text) of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the foreground color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color ForeColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the background color of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the background color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>, which indicates that this property is not set.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color BackColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border color of the Web control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Drawing.Color"/> that represents the border color of the control. The default is <see cref="F:System.Drawing.Color.Empty"/>, which indicates that this property is not set.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override System.Drawing.Color BorderColor {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border width of the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the border width of a Web server control. The default value is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>, which indicates that this property is not set.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The specified border width is a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit BorderWidth {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets the border style of the Web server control.
- /// </summary>
- /// <returns>
- /// One of the <see cref="T:System.Web.UI.WebControls.BorderStyle"/> enumeration values. The default is NotSet.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override BorderStyle BorderStyle {
- get { return BorderStyle.None; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets the font properties associated with the Web server control.
- /// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.FontInfo"/> that represents the font properties of the Web server control.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override FontInfo Font {
- get { return null; }
- }
+ #region IPostBackDataHandler Members
/// <summary>
- /// Gets or sets the height of the Web server control.
+ /// When implemented by a class, processes postback data for an ASP.NET server control.
/// </summary>
+ /// <param name="postDataKey">The key identifier for the control.</param>
+ /// <param name="postCollection">The collection of all incoming name values.</param>
/// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the height of the control. The default is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>.
+ /// true if the server control's state changes as a result of the postback; otherwise, false.
/// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The height was set to a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit Height {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
+ bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) {
+ return this.LoadPostData(postDataKey, postCollection);
}
/// <summary>
- /// Gets or sets the width of the Web server control.
+ /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
/// </summary>
- /// <returns>
- /// A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the width of the control. The default is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>.
- /// </returns>
- /// <exception cref="T:System.ArgumentException">
- /// The width of the Web server control was set to a negative value.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override Unit Width {
- get { return Unit.Empty; }
- set { throw new NotSupportedException(); }
+ void IPostBackDataHandler.RaisePostDataChangedEvent() {
+ this.RaisePostDataChangedEvent();
}
- /// <summary>
- /// Gets or sets the text displayed when the mouse pointer hovers over the Web server control.
- /// </summary>
- /// <returns>
- /// The text displayed when the mouse pointer hovers over the Web server control. The default is <see cref="F:System.String.Empty"/>.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override string ToolTip {
- get { return string.Empty; }
- set { throw new NotSupportedException(); }
- }
+ #endregion
/// <summary>
- /// Gets or sets the skin to apply to the control.
+ /// Creates the authentication requests for a given user-supplied Identifier.
/// </summary>
/// <returns>
- /// The name of the skin to apply to the control. The default is <see cref="F:System.String.Empty"/>.
+ /// 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>
- /// <exception cref="T:System.ArgumentException">
- /// The skin specified in the <see cref="P:System.Web.UI.WebControls.WebControl.SkinID"/> property does not exist in the theme.
- /// </exception>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override string SkinID {
- get { return string.Empty; }
- set { throw new NotSupportedException(); }
- }
-
- /// <summary>
- /// Gets or sets a value indicating whether themes apply to this control.
- /// </summary>
- /// <returns>true to use themes; otherwise, false. The default is false.
- /// </returns>
- [Obsolete("This property does not do anything."), Browsable(false), Bindable(false)]
- public override bool EnableTheming {
- get { return false; }
- set { throw new NotSupportedException(); }
- }
-
- #endregion
-
- /// <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 OpenIdRelyingParty RelyingParty {
- get {
- if (this.relyingParty == null) {
- this.relyingParty = this.CreateRelyingParty();
- }
- return this.relyingParty;
- }
-
- set {
- this.relyingParty = value;
- }
- }
-
- /// <summary>
- /// Gets the <see cref="TextBox"/> control that this control wraps.
- /// </summary>
- protected TextBox WrappedTextBox {
- get { return this.wrappedTextBox; }
- }
-
- /// <summary>
- /// Gets or sets a value indicating whether the text box should
- /// receive input focus when the web page appears.
- /// </summary>
- protected bool ShouldBeFocused { get; set; }
-
- /// <summary>
- /// Gets or sets the OpenID authentication request that is about to be sent.
- /// </summary>
- protected IAuthenticationRequest Request { get; set; }
-
- /// <summary>
- /// Sets the input focus to start on the text box when the page appears
- /// in the user's browser.
- /// </summary>
- public override void Focus() {
- if (Controls.Count == 0) {
- this.ShouldBeFocused = true;
- } else {
- this.WrappedTextBox.Focus();
- }
- }
-
- /// <summary>
- /// Constructs the authentication request and returns it.
- /// </summary>
- /// <returns>The instantiated authentication request.</returns>
- /// <remarks>
- /// <para>This method need not be called before calling the <see cref="LogOn"/> method,
- /// but is offered in the event that adding extensions to the request is desired.</para>
- /// <para>The Simple Registration extension arguments are added to the request
- /// before returning if <see cref="EnableRequestProfile"/> is set to true.</para>
- /// </remarks>
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")]
- public IAuthenticationRequest CreateRequest() {
- Contract.Requires<InvalidOperationException>(this.Request == null, OpenIdStrings.CreateRequestAlreadyCalled);
- Contract.Requires<InvalidOperationException>(!string.IsNullOrEmpty(this.Text), OpenIdStrings.OpenIdTextBoxEmpty);
-
- try {
- // Approximate the returnTo (either based on the customize property or the page URL)
- // so we can use it to help with Realm resolution.
- var requestContext = this.RelyingParty.Channel.GetRequestFromContext();
- Uri returnToApproximation = this.ReturnToUrl != null ? new Uri(requestContext.UrlBeforeRewriting, this.ReturnToUrl) : this.Page.Request.Url;
-
- // Resolve the trust root, and swap out the scheme and port if necessary to match the
- // return_to URL, since this match is required by OpenId, and the consumer app
- // may be using HTTP at some times and HTTPS at others.
- UriBuilder realm = OpenIdUtilities.GetResolvedRealm(this.Page, this.RealmUrl, this.RelyingParty.Channel.GetRequestFromContext());
- realm.Scheme = returnToApproximation.Scheme;
- realm.Port = returnToApproximation.Port;
-
- // Initiate openid request
- // We use TryParse here to avoid throwing an exception which
- // might slip through our validator control if it is disabled.
- Identifier userSuppliedIdentifier;
- if (Identifier.TryParse(this.Text, out userSuppliedIdentifier)) {
- Realm typedRealm = new Realm(realm);
- if (string.IsNullOrEmpty(this.ReturnToUrl)) {
- this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm);
- } else {
- // Since the user actually gave us a return_to value,
- // the "approximation" is exactly what we want.
- this.Request = this.RelyingParty.CreateRequest(userSuppliedIdentifier, typedRealm, returnToApproximation);
- }
-
- if (this.EnableRequestProfile) {
- this.AddProfileArgs(this.Request);
- }
-
- if (this.IsPopupAppropriate()) {
- // Inform the OP that it will appear in a popup window.
- this.Request.AddExtension(new UIRequest());
- }
-
- // Add state that needs to survive across the redirect.
- if (!this.Stateless) {
- this.Request.AddCallbackArguments(UsePersistentCookieCallbackKey, this.UsePersistentCookie.ToString(CultureInfo.InvariantCulture));
- }
- } else {
- Logger.OpenId.WarnFormat("An invalid identifier was entered ({0}), but not caught by any validation routine.", this.Text);
- this.Request = null;
- }
- } catch (ProtocolException ex) {
- this.OnFailed(new FailedAuthenticationResponse(ex));
- }
-
- return this.Request;
- }
-
- /// <summary>
- /// Immediately redirects to the OpenID Provider to verify the Identifier
- /// provided in the text box.
- /// </summary>
- public void LogOn() {
- if (this.Request == null) {
- this.CreateRequest(); // sets this.Request
- }
-
- if (this.Request != null) {
- if (this.IsPopupAppropriate()) {
- this.ScriptPopupWindow();
- } else {
- this.Request.RedirectToProvider();
- }
- }
- }
-
- /// <summary>
- /// Enables a server control to perform final clean up before it is released from memory.
- /// </summary>
- [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
- public sealed override void Dispose() {
- this.Dispose(true);
- base.Dispose();
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Creates the text box control.
- /// </summary>
- protected override void CreateChildControls() {
- base.CreateChildControls();
-
- this.Controls.Add(this.wrappedTextBox);
- if (this.ShouldBeFocused) {
- this.WrappedTextBox.Focus();
- }
- }
-
- /// <summary>
- /// Initializes the text box control.
- /// </summary>
- protected virtual void InitializeControls() {
- this.wrappedTextBox = new TextBox();
- this.wrappedTextBox.ID = "wrappedTextBox";
- this.wrappedTextBox.CssClass = CssClassDefault;
- this.wrappedTextBox.Columns = ColumnsDefault;
- this.wrappedTextBox.Text = this.text;
- this.wrappedTextBox.TabIndex = TabIndexDefault;
+ protected override IEnumerable<IAuthenticationRequest> CreateRequests() {
+ // 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());
}
/// <summary>
@@ -1018,156 +540,110 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"/> object that contains the event data.</param>
protected override void OnLoad(EventArgs e) {
- base.OnLoad(e);
-
- if (!Enabled || Page.IsPostBack) {
+ if (!this.Enabled) {
return;
}
- // Take an unreliable sneek peek to see if we're in a popup and an OpenID
- // assertion is coming in. We shouldn't process assertions in a popup window.
- if (this.Page.Request.QueryString[UIPopupCallbackKey] == "1" && this.Page.Request.QueryString[UIPopupCallbackParentKey] == null) {
- // We're in a popup window. We need to close it and pass the
- // message back to the parent window for processing.
- this.ScriptClosingPopup();
- return; // don't do any more processing on it now
- }
-
- var response = this.RelyingParty.GetResponse();
- if (response != null) {
- string persistentString = response.GetCallbackArgument(UsePersistentCookieCallbackKey);
- bool persistentBool;
- if (persistentString != null && bool.TryParse(persistentString, out persistentBool)) {
- this.UsePersistentCookie = persistentBool;
- }
-
- switch (response.Status) {
- case AuthenticationStatus.Canceled:
- this.OnCanceled(response);
- break;
- case AuthenticationStatus.Authenticated:
- this.OnLoggedIn(response);
- break;
- case AuthenticationStatus.SetupRequired:
- this.OnSetupRequired(response);
- break;
- case AuthenticationStatus.Failed:
- this.OnFailed(response);
- break;
- case AuthenticationStatus.ExtensionsOnly:
- default:
- // The NotApplicable (extension-only assertion) is NOT one that we support
- // in this control because that scenario is primarily interesting to RPs
- // that are asking a specific OP, and it is not user-initiated as this textbox
- // is designed for.
- throw new InvalidOperationException(MessagingStrings.UnexpectedMessageReceivedOfMany);
- }
- }
+ this.Page.RegisterRequiresPostBack(this);
+ base.OnLoad(e);
}
/// <summary>
- /// Prepares the text box to be rendered.
+ /// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
/// </summary>
- /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
- protected override void OnPreRender(EventArgs e) {
- base.OnPreRender(e);
-
+ /// <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) {
if (this.ShowLogo) {
string logoUrl = Page.ClientScript.GetWebResourceUrl(
typeof(OpenIdTextBox), EmbeddedLogoResourceName);
- this.WrappedTextBox.Style[HtmlTextWriterStyle.BackgroundImage] = string.Format(
- CultureInfo.InvariantCulture, "url({0})", HttpUtility.HtmlEncode(logoUrl));
- this.WrappedTextBox.Style["background-repeat"] = "no-repeat";
- this.WrappedTextBox.Style["background-position"] = "0 50%";
- this.WrappedTextBox.Style[HtmlTextWriterStyle.PaddingLeft] = "18px";
+ writer.AddStyleAttribute(
+ HtmlTextWriterStyle.BackgroundImage,
+ string.Format(CultureInfo.InvariantCulture, "url({0})", HttpUtility.HtmlEncode(logoUrl)));
+ writer.AddStyleAttribute("background-repeat", "no-repeat");
+ writer.AddStyleAttribute("background-position", "0 50%");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.PaddingLeft, "18px");
}
if (this.PresetBorder) {
- this.WrappedTextBox.Style[HtmlTextWriterStyle.BorderStyle] = "solid";
- this.WrappedTextBox.Style[HtmlTextWriterStyle.BorderWidth] = "1px";
- this.WrappedTextBox.Style[HtmlTextWriterStyle.BorderColor] = "lightgray";
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px");
+ writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "lightgray");
}
- }
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources
- /// </summary>
- /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool disposing) {
- if (disposing) {
- if (this.relyingParty != null) {
- this.relyingParty.Dispose();
- this.relyingParty = null;
- }
+ if (!string.IsNullOrEmpty(this.CssClass)) {
+ writer.AddAttribute(HtmlTextWriterAttribute.Class, this.CssClass);
}
- }
- #region Events
+ writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
+ writer.AddAttribute(HtmlTextWriterAttribute.Name, HttpUtility.HtmlEncode(this.Name));
+ writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
+ writer.AddAttribute(HtmlTextWriterAttribute.Size, this.Columns.ToString(CultureInfo.InvariantCulture));
+ writer.AddAttribute(HtmlTextWriterAttribute.Value, HttpUtility.HtmlEncode(this.Text));
+ writer.AddAttribute(HtmlTextWriterAttribute.Tabindex, this.TabIndex.ToString(CultureInfo.CurrentCulture));
+
+ writer.RenderBeginTag(HtmlTextWriterTag.Input);
+ writer.RenderEndTag();
+ }
/// <summary>
- /// Fires the <see cref="LoggedIn"/> event.
+ /// When implemented by a class, processes postback data for an ASP.NET server control.
/// </summary>
- /// <param name="response">The response.</param>
- protected virtual void OnLoggedIn(IAuthenticationResponse response) {
- Contract.Requires<ArgumentNullException>(response != null);
- ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Authenticated, "Firing OnLoggedIn event without an authenticated response.");
-
- var loggedIn = this.LoggedIn;
- OpenIdEventArgs args = new OpenIdEventArgs(response);
- if (loggedIn != null) {
- loggedIn(this, args);
+ /// <param name="postDataKey">The key identifier for the control.</param>
+ /// <param name="postCollection">The collection of all incoming name values.</param>
+ /// <returns>
+ /// 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) {
+ // 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) {
+ Identifier identifier = postCollection[this.Name].Length == 0 ? null : postCollection[this.Name];
+ if (identifier != this.Identifier) {
+ this.Identifier = identifier;
+ return true;
+ }
}
- if (!args.Cancel) {
- FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie);
- }
+ return false;
}
/// <summary>
- /// Fires the <see cref="Failed"/> event.
+ /// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
/// </summary>
- /// <param name="response">The response.</param>
- protected virtual void OnFailed(IAuthenticationResponse response) {
- Contract.Requires<ArgumentNullException>(response != null);
- ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Failed, "Firing Failed event for the wrong response type.");
-
- var failed = this.Failed;
- if (failed != null) {
- failed(this, new OpenIdEventArgs(response));
- }
+ protected virtual void RaisePostDataChangedEvent() {
+ this.OnTextChanged();
}
/// <summary>
- /// Fires the <see cref="Canceled"/> event.
+ /// Called on a postback when the Text property has changed.
/// </summary>
- /// <param name="response">The response.</param>
- protected virtual void OnCanceled(IAuthenticationResponse response) {
- Contract.Requires<ArgumentNullException>(response != null);
- ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.Canceled, "Firing Canceled event for the wrong response type.");
-
- var canceled = this.Canceled;
- if (canceled != null) {
- canceled(this, new OpenIdEventArgs(response));
+ protected virtual void OnTextChanged() {
+ EventHandler textChanged = this.TextChanged;
+ if (textChanged != null) {
+ textChanged(this, EventArgs.Empty);
}
}
/// <summary>
- /// Fires the <see cref="SetupRequired"/> event.
+ /// Creates the authentication requests for a given user-supplied Identifier.
/// </summary>
- /// <param name="response">The response.</param>
- protected virtual void OnSetupRequired(IAuthenticationResponse response) {
- Contract.Requires<ArgumentNullException>(response != null);
- ErrorUtilities.VerifyInternal(response.Status == AuthenticationStatus.SetupRequired, "Firing SetupRequired event for the wrong response type.");
+ /// <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) {
+ Contract.Requires(requests != null);
- // Why are we firing Failed when we're OnSetupRequired? Backward compatibility.
- var setupRequired = this.SetupRequired;
- if (setupRequired != null) {
- setupRequired(this, new OpenIdEventArgs(response));
+ foreach (var request in requests) {
+ if (this.EnableRequestProfile) {
+ this.AddProfileArgs(request);
+ }
+
+ yield return request;
}
}
- #endregion
-
/// <summary>
/// Adds extensions to a given authentication request to ask the Provider
/// for user profile data.
@@ -1176,7 +652,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private void AddProfileArgs(IAuthenticationRequest request) {
Contract.Requires<ArgumentNullException>(request != null);
- request.AddExtension(new ClaimsRequest() {
+ var sreg = new ClaimsRequest() {
Nickname = this.RequestNickname,
Email = this.RequestEmail,
FullName = this.RequestFullName,
@@ -1188,75 +664,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
TimeZone = this.RequestTimeZone,
PolicyUrl = string.IsNullOrEmpty(this.PolicyUrl) ?
null : new Uri(this.RelyingParty.Channel.GetRequestFromContext().UrlBeforeRewriting, this.Page.ResolveUrl(this.PolicyUrl)),
- });
- }
+ };
- /// <summary>
- /// Creates the relying party instance used to generate authentication requests.
- /// </summary>
- /// <returns>The instantiated relying party.</returns>
- private OpenIdRelyingParty CreateRelyingParty() {
- // If we're in stateful mode, first use the explicitly given one on this control if there
- // is one. Then try the configuration file specified one. Finally, use the default
- // in-memory one that's built into OpenIdRelyingParty.
- 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;
+ // Only actually add the extension request if fields are actually being requested.
+ if (!sreg.Equals(EmptyClaimsRequest)) {
+ request.AddExtension(sreg);
}
- return rp;
- }
-
- /// <summary>
- /// Detects whether a popup window should be used to show the Provider's UI
- /// and applies the UI extension to the request when appropriate.
- /// </summary>
- /// <returns><c>true</c> if a popup should be used; <c>false</c> otherwise.</returns>
- private bool IsPopupAppropriate() {
- Contract.Requires<InvalidOperationException>(this.Request != null);
-
- return this.Popup == PopupBehavior.Always || this.Request.Provider.IsExtensionSupported<UIRequest>();
- }
-
- /// <summary>
- /// Wires the return page to immediately display a popup window with the Provider in it.
- /// </summary>
- private void ScriptPopupWindow() {
- Contract.Requires<InvalidOperationException>(this.Request != null);
- Contract.Requires<InvalidOperationException>(this.RelyingParty != null);
-
- this.Request.AddCallbackArguments(UIPopupCallbackKey, "1");
-
- StringBuilder startupScript = new StringBuilder();
-
- // Add a callback function that the popup window can call on this, the
- // parent window, to pass back the authentication result.
- startupScript.AppendLine("window.dnoa_internal = new Object();");
- startupScript.AppendLine("window.dnoa_internal.processAuthorizationResult = function(uri) { window.location = uri; };");
-
- // Open the popup window.
- startupScript.AppendFormat(
- @"var openidPopup = {0}",
- UIUtilities.GetWindowPopupScript(this.RelyingParty, this.Request, "openidPopup"));
-
- this.Page.ClientScript.RegisterStartupScript(this.GetType(), "loginPopup", startupScript.ToString(), true);
- }
-
- /// <summary>
- /// Wires the popup window to close itself and pass the authentication result to the parent window.
- /// </summary>
- private void ScriptClosingPopup() {
- StringBuilder startupScript = new StringBuilder();
- startupScript.AppendLine("window.opener.dnoa_internal.processAuthorizationResult(document.URL + '&" + UIPopupCallbackParentKey + "=1');");
- startupScript.AppendLine("window.close();");
-
- // We're referencing the OpenIdRelyingPartyControlBase type here to avoid double-registering this script
- // if the other control exists on the page.
- this.Page.ClientScript.RegisterStartupScript(typeof(OpenIdRelyingPartyControlBase), "loginPopupClose", startupScript.ToString(), true);
}
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index bd75d16..e809205 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -20,17 +20,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
[DebuggerDisplay("Status: {Status}, ClaimedIdentifier: {ClaimedIdentifier}")]
internal class PositiveAuthenticationResponse : PositiveAnonymousResponse {
/// <summary>
- /// The OpenID service endpoint reconstructed from the assertion message.
- /// </summary>
- /// <remarks>
- /// This information is straight from the Provider, and therefore must not
- /// be trusted until verified as matching the discovery information for
- /// the claimed identifier to avoid a Provider asserting an Identifier
- /// for which it has no authority.
- /// </remarks>
- private readonly ServiceEndpoint endpoint;
-
- /// <summary>
/// Initializes a new instance of the <see cref="PositiveAuthenticationResponse"/> class.
/// </summary>
/// <param name="response">The positive assertion response that was just received by the Relying Party.</param>
@@ -39,7 +28,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
: base(response) {
Contract.Requires<ArgumentNullException>(relyingParty != null);
- this.endpoint = ServiceEndpoint.CreateForClaimedIdentifier(
+ this.Endpoint = ServiceEndpoint.CreateForClaimedIdentifier(
this.Response.ClaimedIdentifier,
this.Response.GetReturnToArgument(AuthenticationRequest.UserSuppliedIdentifierParameterName),
this.Response.LocalIdentifier,
@@ -69,7 +58,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </para>
/// </remarks>
public override Identifier ClaimedIdentifier {
- get { return this.endpoint.ClaimedIdentifier; }
+ get { return this.Endpoint.ClaimedIdentifier; }
}
/// <summary>
@@ -102,7 +91,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </para>
/// </remarks>
public override string FriendlyIdentifierForDisplay {
- get { return this.endpoint.FriendlyIdentifierForDisplay; }
+ get { return this.Endpoint.FriendlyIdentifierForDisplay; }
}
/// <summary>
@@ -115,6 +104,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#endregion
/// <summary>
+ /// Gets the OpenID service endpoint reconstructed from the assertion message.
+ /// </summary>
+ /// <remarks>
+ /// This information is straight from the Provider, and therefore must not
+ /// be trusted until verified as matching the discovery information for
+ /// the claimed identifier to avoid a Provider asserting an Identifier
+ /// for which it has no authority.
+ /// </remarks>
+ internal ServiceEndpoint Endpoint { get; private set; }
+
+ /// <summary>
/// Gets the positive assertion response message.
/// </summary>
protected internal new PositiveAssertionResponse Response {
@@ -135,6 +135,15 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private void VerifyDiscoveryMatchesAssertion(OpenIdRelyingParty relyingParty) {
Logger.OpenId.Debug("Verifying assertion matches identifier discovery results...");
+ // Ensure that we abide by the RP's rules regarding RequireSsl for this discovery step.
+ Identifier claimedId = this.Response.ClaimedIdentifier;
+ if (relyingParty.SecuritySettings.RequireSsl) {
+ if (!claimedId.TryRequireSsl(out claimedId)) {
+ Logger.OpenId.ErrorFormat("This site is configured to accept only SSL-protected OpenIDs, but {0} was asserted and must be rejected.", this.Response.ClaimedIdentifier);
+ ErrorUtilities.ThrowProtocol(OpenIdStrings.RequireSslNotSatisfiedByAssertedClaimedId, this.Response.ClaimedIdentifier);
+ }
+ }
+
// 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
@@ -144,11 +153,11 @@ 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 = this.Response.ClaimedIdentifier.Discover(relyingParty.WebRequestHandler);
+ var discoveryResults = claimedId.Discover(relyingParty.WebRequestHandler);
ErrorUtilities.VerifyProtocol(
- discoveryResults.Contains(this.endpoint),
+ discoveryResults.Contains(this.Endpoint),
OpenIdStrings.IssuedAssertionFailsIdentifierDiscovery,
- this.endpoint,
+ this.Endpoint,
discoveryResults.ToStringDeferred(true));
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationResponseSnapshot.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
index a1b50d2..676d95f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationResponseSnapshot.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshot.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="AuthenticationResponseSnapshot.cs" company="Andrew Arnott">
+// <copyright file="PositiveAuthenticationResponseSnapshot.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -17,17 +17,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// A serializable snapshot of a verified authentication message.
/// </summary>
[Serializable]
- internal class AuthenticationResponseSnapshot : IAuthenticationResponse {
+ internal class PositiveAuthenticationResponseSnapshot : IAuthenticationResponse {
/// <summary>
/// The callback arguments that came with the authentication response.
/// </summary>
private IDictionary<string, string> callbackArguments;
/// <summary>
- /// Initializes a new instance of the <see cref="AuthenticationResponseSnapshot"/> class.
+ /// Initializes a new instance of the <see cref="PositiveAuthenticationResponseSnapshot"/> class.
/// </summary>
/// <param name="copyFrom">The authentication response to copy from.</param>
- internal AuthenticationResponseSnapshot(IAuthenticationResponse copyFrom) {
+ internal PositiveAuthenticationResponseSnapshot(IAuthenticationResponse copyFrom) {
Contract.Requires<ArgumentNullException>(copyFrom != null);
this.ClaimedIdentifier = copyFrom.ClaimedIdentifier;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs
index 2cfe1db..8cf445d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs
@@ -428,7 +428,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Creates a <see cref="ServiceEndpoint"/> instance to represent some OP Identifier.
/// </summary>
- /// <param name="providerIdentifier">The provider identifier.</param>
+ /// <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>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs
new file mode 100644
index 0000000..912b8f4
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/SimpleXrdsProviderEndpoint.cs
@@ -0,0 +1,115 @@
+//-----------------------------------------------------------------------
+// <copyright file="SimpleXrdsProviderEndpoint.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System;
+ using DotNetOpenAuth.OpenId.Messages;
+
+ /// <summary>
+ /// A very simple IXrdsProviderEndpoint implementation for verifying that all positive
+ /// assertions (particularly unsolicited ones) are received from OP endpoints that
+ /// are deemed permissible by the host RP.
+ /// </summary>
+ internal class SimpleXrdsProviderEndpoint : IXrdsProviderEndpoint {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SimpleXrdsProviderEndpoint"/> class.
+ /// </summary>
+ /// <param name="positiveAssertion">The positive assertion.</param>
+ internal SimpleXrdsProviderEndpoint(PositiveAssertionResponse positiveAssertion) {
+ this.Uri = positiveAssertion.ProviderEndpoint;
+ 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>
+ /// Gets the detected version of OpenID implemented by the Provider.
+ /// </summary>
+ public Version Version { get; private set; }
+
+ /// <summary>
+ /// Gets the URL that the OpenID Provider receives authentication requests at.
+ /// </summary>
+ /// <value></value>
+ public Uri Uri { get; private set; }
+
+ /// <summary>
+ /// Checks whether the OpenId Identifier claims support for a given extension.
+ /// </summary>
+ /// <typeparam name="T">The extension whose support is being queried.</typeparam>
+ /// <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<T>() where T : DotNetOpenAuth.OpenId.Messages.IOpenIdMessageExtension, new() {
+ throw new NotSupportedException();
+ }
+
+ /// <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) {
+ 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();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
index 3e0c8db..8499178 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
@@ -48,12 +48,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets the best association (the one with the longest remaining life) for a given key.
/// </summary>
/// <param name="distinguishingFactor">The Uri (for relying parties) or Smart/Dumb (for Providers).</param>
- /// <param name="securitySettings">The security settings.</param>
+ /// <param name="securityRequirements">The security settings.</param>
/// <returns>
/// The requested association, or null if no unexpired <see cref="Association"/>s exist for the given key.
/// </returns>
- public Association GetAssociation(Uri distinguishingFactor, SecuritySettings securitySettings) {
- return this.associationStore.GetAssociation(distinguishingFactor, securitySettings);
+ public Association GetAssociation(Uri distinguishingFactor, SecuritySettings securityRequirements) {
+ return this.associationStore.GetAssociation(distinguishingFactor, securityRequirements);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/WellKnownProviders.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/WellKnownProviders.cs
index bd45842..2e2ab61 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/WellKnownProviders.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/WellKnownProviders.cs
@@ -5,6 +5,8 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.RelyingParty {
+ using System.Diagnostics.CodeAnalysis;
+
/// <summary>
/// Common OpenID Provider Identifiers.
/// </summary>
@@ -12,16 +14,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// The Yahoo OP Identifier.
/// </summary>
+ [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")]
public static readonly Identifier Yahoo = "https://me.yahoo.com/";
/// <summary>
/// The Google OP Identifier.
/// </summary>
+ [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")]
public static readonly Identifier Google = "https://www.google.com/accounts/o8/id";
/// <summary>
/// The MyOpenID OP Identifier.
/// </summary>
+ [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Immutable type")]
public static readonly Identifier MyOpenId = "https://www.myopenid.com/";
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
index 112506b..6b82966 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using DotNetOpenAuth.Messaging;
/// <summary>
/// A description of some OpenID Relying Party endpoint.
@@ -25,6 +26,9 @@ namespace DotNetOpenAuth.OpenId {
/// The Type URIs of supported services advertised on a relying party's XRDS document.
/// </param>
internal RelyingPartyEndpointDescription(Uri returnTo, string[] supportedServiceTypeUris) {
+ ErrorUtilities.VerifyArgumentNotNull(returnTo, "returnTo");
+ ErrorUtilities.VerifyArgumentNotNull(supportedServiceTypeUris, "supportedServiceTypeUris");
+
this.ReturnToEndpoint = returnTo;
this.Protocol = GetProtocolFromServices(supportedServiceTypeUris);
}
diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
index baa9568..4339646 100644
--- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
@@ -12,6 +12,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.UI.HtmlControls;
+ using System.Xml;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.RelyingParty;
using DotNetOpenAuth.Xrds;
@@ -42,7 +43,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="uri">The value this identifier will represent.</param>
/// <param name="requireSslDiscovery">if set to <c>true</c> [require SSL discovery].</param>
internal UriIdentifier(string uri, bool requireSslDiscovery)
- : base(requireSslDiscovery) {
+ : base(uri, requireSslDiscovery) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(uri));
Uri canonicalUri;
bool schemePrepended;
@@ -69,7 +70,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="uri">The value this identifier will represent.</param>
/// <param name="requireSslDiscovery">if set to <c>true</c> [require SSL discovery].</param>
internal UriIdentifier(Uri uri, bool requireSslDiscovery)
- : base(requireSslDiscovery) {
+ : base(uri != null ? uri.OriginalString : null, requireSslDiscovery) {
Contract.Requires<ArgumentNullException>(uri != null);
if (!TryCanonicalize(new UriBuilder(uri), out uri)) {
throw new UriFormatException();
@@ -129,6 +130,9 @@ namespace DotNetOpenAuth.OpenId {
/// </exception>
public override bool Equals(object obj) {
UriIdentifier other = obj as UriIdentifier;
+ if (obj != null && other == null && Identifier.EqualityOnStrings) { // test hook to enable MockIdentifier comparison
+ other = Identifier.Parse(obj.ToString()) as UriIdentifier;
+ }
if (other == null) {
return false;
}
@@ -215,14 +219,18 @@ namespace DotNetOpenAuth.OpenId {
DiscoveryResult yadisResult = Yadis.Discover(requestHandler, this, IsDiscoverySecureEndToEnd);
if (yadisResult != null) {
if (yadisResult.IsXrds) {
- XrdsDocument xrds = new XrdsDocument(yadisResult.ResponseText);
- var xrdsEndpoints = xrds.CreateServiceEndpoints(yadisResult.NormalizedUri, this);
+ 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);
+ // 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);
}
- endpoints.AddRange(xrdsEndpoints);
}
// Failing YADIS discovery of an XRDS document, we try HTML discovery.
diff --git a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
index 48dbbb9..c61641e 100644
--- a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
@@ -74,7 +74,7 @@ namespace DotNetOpenAuth.OpenId {
/// only succeed if it can be done entirely using SSL.
/// </param>
internal XriIdentifier(string xri, bool requireSsl)
- : base(requireSsl) {
+ : base(xri, requireSsl) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(xri));
Contract.Requires<FormatException>(IsValidXri(xri), OpenIdStrings.InvalidXri);
Contract.Assume(xri != null); // Proven by IsValidXri
@@ -130,6 +130,9 @@ namespace DotNetOpenAuth.OpenId {
/// </exception>
public override bool Equals(object obj) {
XriIdentifier other = obj as XriIdentifier;
+ if (obj != null && other == null && Identifier.EqualityOnStrings) { // test hook to enable MockIdentifier comparison
+ other = Identifier.Parse(obj.ToString()) as XriIdentifier;
+ }
if (other == null) {
return false;
}
diff --git a/src/DotNetOpenAuth/Strings.sr.resx b/src/DotNetOpenAuth/Strings.sr.resx
new file mode 100644
index 0000000..5112265
--- /dev/null
+++ b/src/DotNetOpenAuth/Strings.sr.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="ConfigurationTypeMustBePublic" xml:space="preserve">
+ <value>Konfiguraciono zavisni tip {0} mora biti javan, a on to nije.</value>
+ </data>
+ <data name="ConfigurationXamlReferenceRequiresHttpContext" xml:space="preserve">
+ <value>Konfiguraciona XAML referenca na {0} zahteva da se trenutni HttpContext razreši.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Util.cs b/src/DotNetOpenAuth/Util.cs
index 603ed96..9f8b30c 100644
--- a/src/DotNetOpenAuth/Util.cs
+++ b/src/DotNetOpenAuth/Util.cs
@@ -75,6 +75,7 @@ namespace DotNetOpenAuth {
return new DelayedToString<IEnumerable<KeyValuePair<K, V>>>(
pairs,
p => {
+ ////Contract.Requires(pairs != null); // CC: anonymous method can't handle it
ErrorUtilities.VerifyArgumentNotNull(pairs, "pairs");
var dictionary = pairs as IDictionary<K, V>;
StringBuilder sb = new StringBuilder(dictionary != null ? dictionary.Count * 40 : 200);
@@ -103,6 +104,7 @@ namespace DotNetOpenAuth {
/// <param name="list">The list of elements.</param>
/// <param name="multiLineElements">if set to <c>true</c>, special formatting will be applied to the output to make it clear where one element ends and the next begins.</param>
/// <returns>An object whose ToString method will perform the actual work of generating the string.</returns>
+ [ContractVerification(false)]
internal static object ToStringDeferred<T>(this IEnumerable<T> list, bool multiLineElements) {
return new DelayedToString<IEnumerable<T>>(
list,
diff --git a/src/DotNetOpenAuth/Xrds/XrdsStrings.sr.resx b/src/DotNetOpenAuth/Xrds/XrdsStrings.sr.resx
new file mode 100644
index 0000000..8e2d09a
--- /dev/null
+++ b/src/DotNetOpenAuth/Xrds/XrdsStrings.sr.resx
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <data name="CIDVerificationFailed" xml:space="preserve">
+ <value>XRI CanonicalID provera neuspešna.</value>
+ </data>
+ <data name="InvalidXRDSDocument" xml:space="preserve">
+ <value>Greška u obradi XRDS dokumenta.</value>
+ </data>
+ <data name="MissingCanonicalIDElement" xml:space="preserve">
+ <value>XRDS dokumentu za XRI {0} nedostaje neophodni CanonicalID element.</value>
+ </data>
+ <data name="XriResolutionStatusMissing" xml:space="preserve">
+ <value>Ne može se pronaći XRI resolution Status tag ili je code attribute neispravan.</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/src/version.txt b/src/version.txt
index 944880f..15a2799 100644
--- a/src/version.txt
+++ b/src/version.txt
@@ -1 +1 @@
-3.2.0
+3.3.0
diff --git a/tools/DotNetOpenAuth.Versioning.targets b/tools/DotNetOpenAuth.Versioning.targets
index 2ffcb82..65d212c 100644
--- a/tools/DotNetOpenAuth.Versioning.targets
+++ b/tools/DotNetOpenAuth.Versioning.targets
@@ -7,8 +7,7 @@
<VersionCsFile>$(ProjectRoot)\obj\$(Configuration)\$(AssemblyName).Version.cs</VersionCsFile>
</PropertyGroup>
- <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="GetBuildVersion" />
- <UsingTask AssemblyFile="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.dll" TaskName="CompareFiles" />
+ <Import Project="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.targets" />
<UsingTask AssemblyFile="$(ProjectRoot)\lib\MSBuild.Community.Tasks.dll" TaskName="AssemblyInfo"/>
<Target Name="GetBuildVersion">
diff --git a/tools/Publish.targets b/tools/Publish.targets
new file mode 100644
index 0000000..036e751
--- /dev/null
+++ b/tools/Publish.targets
@@ -0,0 +1,122 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!-- Properties that must be set for these targets to function:
+ $(BranchName): The name of the branch being built. Used to determine the web subdirectory for publishing.
+
+ For creating web sites:
+ $(PublishSamplesWebSiteName): The name of the web site under which the sample web applications will be created/deleted.
+ $(PublishDocsWebSiteName): The name of the web site under which the documentation web applications will be created/deleted.
+
+ For creating or publishing to web sites:
+ $(SampleWebRoot): the full physical path to where samples should be copied to, excluding $(BranchName)
+ $(DocWebRoot): the full physical path to where documentation should be copied to, excluding $(BranchName)
+ -->
+
+ <Target Name="PrepareForIIS">
+ <Error Text="The BranchName property must be set." Condition=" '$(BranchName)' == '' " />
+
+ <PropertyGroup>
+ <PublishSamplesWebSiteVirtualPath>/$(BranchName)</PublishSamplesWebSiteVirtualPath>
+ <PublishDocsWebSiteVirtualPath>/$(BranchName)</PublishDocsWebSiteVirtualPath>
+ </PropertyGroup>
+ </Target>
+
+ <Target Name="PrepareForPublishSamples"
+ Condition=" '$(SampleWebRoot)' != '' "
+ DependsOnTargets="BuildSamples">
+ <Error Text="The BranchName property must be set." Condition=" '$(BranchName)' == '' " />
+
+ <ItemGroup>
+ <_SampleWebConfigs Include="$(ProjectRoot)\samples\*\web.config" />
+ <PublishableWebSamples Include="@(_SampleWebConfigs->'%(RootDir)%(Directory)')" />
+ <SampleSources Include="$(ProjectRoot)\samples\**\*" />
+ <SampleSources>
+ <PublishedLocation>$(SampleWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)</PublishedLocation>
+ </SampleSources>
+ </ItemGroup>
+
+ <!-- Trim the trailing slash on the web sample paths so we can just get the leaf directory name. -->
+ <Trim
+ Inputs="@(PublishableWebSamples)"
+ EndCharacters="\">
+ <Output TaskParameter="Outputs" ItemName="_PublishableWebSamplesNoTrailingSlash" />
+ </Trim>
+
+ <ItemGroup>
+ <PublishableWebSamplesVirtualPaths Include="@(_PublishableWebSamplesNoTrailingSlash->'$(PublishSamplesWebSiteVirtualPath)/%(Filename)')" />
+ <PublishableWebSamplesPhysicalPaths Include="@(_PublishableWebSamplesNoTrailingSlash->'$(SampleWebRoot)\$(BranchName)\%(Filename)')" />
+ </ItemGroup>
+
+ <FilterItems
+ InputItems="@(SampleSources)"
+ StartsWithAny="@(PublishableWebSamples)">
+ <Output TaskParameter="FilteredItems" ItemName="PublishableWebSampleSources" />
+ </FilterItems>
+
+ <ItemGroup>
+ <PublishableWebSampleTargets Include="@(PublishableWebSampleSources->'%(PublishedLocation)')" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="PublishSamples"
+ DependsOnTargets="PrepareForPublishSamples"
+ Inputs="@(PublishableWebSampleSources)"
+ Outputs="@(PublishableWebSampleTargets)"
+ Condition=" '$(SampleWebRoot)' != '' ">
+ <RemoveDir Directories="$(SampleWebRoot)\$(BranchName)" />
+ <MakeDir Directories="$(SampleWebRoot)\$(BranchName)" />
+ <Copy SourceFiles="@(PublishableWebSampleSources)" DestinationFiles="@(PublishableWebSampleTargets)" SkipUnchangedFiles="true" />
+ </Target>
+
+ <Target Name="PrepareForPublishDocumentation" DependsOnTargets="Documentation">
+ <ItemGroup>
+ <DocSources Include="$(ProjectRoot)\doc\api\**\*" />
+ <DocTargets Include="@(DocSources->'$(DocWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)')" />
+ </ItemGroup>
+ </Target>
+
+ <Target Name="PublishDocumentation"
+ DependsOnTargets="PrepareForPublishDocumentation"
+ Inputs="@(DocSources)"
+ Outputs="@(DocTargets)"
+ Condition=" '$(DocWebRoot)' != '' ">
+ <RemoveDir Directories="$(DocWebRoot)\$(BranchName)" />
+ <MakeDir Directories="$(DocWebRoot)\$(BranchName)" />
+ <Copy SourceFiles="@(DocSources)" DestinationFiles="@(DocTargets)" SkipUnchangedFiles="true" />
+ </Target>
+
+ <Target Name="CreateSampleSitesOnIis" DependsOnTargets="PrepareForIIS;PrepareForPublishSamples">
+ <Error Text="The PublishSamplesWebSiteName property must be set." Condition=" '$(PublishSamplesWebSiteName)' == '' "/>
+ <Error Text="The SampleWebRoot property must be set." Condition=" '$(SampleWebRoot)' == '' " />
+ <CreateWebApplication
+ WebSiteName="$(PublishSamplesWebSiteName)"
+ PhysicalPaths="@(PublishableWebSamplesPhysicalPaths)"
+ VirtualPaths="@(PublishableWebSamplesVirtualPaths)"
+ />
+ </Target>
+
+ <Target Name="DeleteSampleSitesOnIis" DependsOnTargets="PrepareForIIS">
+ <Error Text="The PublishSamplesWebSiteName property must be set." Condition=" '$(PublishSamplesWebSiteName)' == '' "/>
+ <DeleteWebApplication
+ WebSiteName="$(PublishSamplesWebSiteName)"
+ VirtualPaths="@(PublishableWebSamplesVirtualPaths)"
+ />
+ </Target>
+
+ <Target Name="CreateDocumentationSiteOnIis" DependsOnTargets="PrepareForIIS">
+ <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/>
+ <Error Text="The DocWebRoot property must be set." Condition=" '$(DocWebRoot)' == '' " />
+ <CreateWebApplication
+ WebSiteName="$(PublishDocsWebSiteName)"
+ PhysicalPaths="$(DocWebRoot)\$(BranchName)"
+ VirtualPaths="$(PublishDocsWebSiteVirtualPath)"
+ />
+ </Target>
+
+ <Target Name="DeleteDocumentationSiteOnIis" DependsOnTargets="PrepareForIIS">
+ <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/>
+ <DeleteWebApplication
+ WebSiteName="$(PublishDocsWebSiteName)"
+ VirtualPaths="$(PublishDocsWebSiteVirtualPath)"
+ />
+ </Target>
+</Project>
diff --git a/tools/Sandcastle/Presentation/vs2005/Content/feedBack_content.xml b/tools/Sandcastle/Presentation/vs2005/Content/feedBack_content.xml
index 48cfd43..6d3a068 100644
--- a/tools/Sandcastle/Presentation/vs2005/Content/feedBack_content.xml
+++ b/tools/Sandcastle/Presentation/vs2005/Content/feedBack_content.xml
@@ -1,6 +1,6 @@
<content xml:space="preserve">
- <item id="fb_alias">DotNetOAuth@googlegroups.com</item>
+ <item id="fb_alias">DotNetOpenId@googlegroups.com</item>
<item id="fb_product"></item>
<item id="fb_deliverable"></item>
diff --git a/tools/Sandcastle/Presentation/vs2005/Content/shared_content.xml b/tools/Sandcastle/Presentation/vs2005/Content/shared_content.xml
index 05ff277..f4a3d99 100644
--- a/tools/Sandcastle/Presentation/vs2005/Content/shared_content.xml
+++ b/tools/Sandcastle/Presentation/vs2005/Content/shared_content.xml
@@ -181,7 +181,7 @@
</includeAttribute>
feedback
</a>
- on this topic to the DotNetOAuth group.
+ on this topic to the DotNetOpenAuth group.
</span>
</item>