summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-04-15 17:07:03 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-04-15 17:07:03 -0700
commitef1c63fc17bd5ae7eda4444ded592574d437d309 (patch)
treef9101be9ffc1bffe79221097e3e1e4600128b9c2 /src
parent217ac4c345ff523715c638f2869ac5cb1b4eb195 (diff)
parentc925ab3d2c5697c9f5f6e57aa58a042f49cf8ecd (diff)
downloadDotNetOpenAuth-ef1c63fc17bd5ae7eda4444ded592574d437d309.zip
DotNetOpenAuth-ef1c63fc17bd5ae7eda4444ded592574d437d309.tar.gz
DotNetOpenAuth-ef1c63fc17bd5ae7eda4444ded592574d437d309.tar.bz2
Merge branch 'v3.0'
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs3
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/MockOpenIdExtension.cs2
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs12
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs12
-rw-r--r--src/DotNetOpenAuth.sln2
-rw-r--r--src/DotNetOpenAuth/Configuration/OpenIdElement.cs27
-rw-r--r--src/DotNetOpenAuth/Configuration/TypeConfigurationCollection.cs75
-rw-r--r--src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs20
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj4
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs5
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs5
-rw-r--r--src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/IOpenIdExtensionFactory.cs20
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs13
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactoryAggregator.cs81
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequest.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsResponse.cs4
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/StandardOpenIdExtensionFactory.cs (renamed from src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactory.cs)16
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs11
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx3
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs25
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs8
33 files changed, 363 insertions, 54 deletions
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs
index f611552..2e5a9ce 100644
--- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingHttpRequestInfo.cs
@@ -40,6 +40,9 @@ namespace DotNetOpenAuth.Test.Mocks {
/// <param name="recipient">The recipient.</param>
internal CoordinatingHttpRequestInfo(MessageReceivingEndpoint recipient) {
this.recipient = recipient;
+ if (recipient != null) {
+ this.Url = recipient.Location;
+ }
if (recipient == null || (recipient.AllowedMethods & HttpDeliveryMethods.GetRequest) != 0) {
this.HttpMethod = "GET";
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockOpenIdExtension.cs b/src/DotNetOpenAuth.Test/Mocks/MockOpenIdExtension.cs
index 86b77bc..f9d418f 100644
--- a/src/DotNetOpenAuth.Test/Mocks/MockOpenIdExtension.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/MockOpenIdExtension.cs
@@ -15,7 +15,7 @@ namespace DotNetOpenAuth.Test.Mocks {
internal class MockOpenIdExtension : IOpenIdMessageExtension {
internal const string MockTypeUri = "http://mockextension";
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
if (typeUri == MockTypeUri) {
return new MockOpenIdExtension();
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
index 24c62e1..5af1caf 100644
--- a/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/ChannelElements/ExtensionsBindingElementTests.cs
@@ -21,7 +21,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
[TestClass]
public class ExtensionsBindingElementTests : OpenIdTestBase {
- private OpenIdExtensionFactory factory;
+ private StandardOpenIdExtensionFactory factory;
private ExtensionsBindingElement rpElement;
private IProtocolMessageWithExtensions request;
@@ -29,7 +29,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
public override void SetUp() {
base.SetUp();
- this.factory = new OpenIdExtensionFactory();
+ this.factory = new StandardOpenIdExtensionFactory();
this.factory.RegisterExtension(MockOpenIdExtension.Factory);
this.rpElement = new ExtensionsBindingElement(this.factory, new RelyingPartySecuritySettings());
this.rpElement.Channel = new TestChannel(this.MessageDescriptions);
@@ -169,7 +169,7 @@ namespace DotNetOpenAuth.Test.OpenId.ChannelElements {
private static void RegisterMockExtension(Channel channel) {
ErrorUtilities.VerifyArgumentNotNull(channel, "channel");
- ((OpenIdExtensionFactory)channel.BindingElements.OfType<ExtensionsBindingElement>().Single().ExtensionFactory).RegisterExtension(MockOpenIdExtension.Factory);
+ ExtensionTestUtilities.RegisterExtension(channel, MockOpenIdExtension.Factory);
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
index 7792ad9..47c8ec4 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
@@ -70,11 +70,11 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
coordinator.Run();
}
- internal static void RegisterExtension(Channel channel, OpenIdExtensionFactory.CreateDelegate extensionFactory) {
+ internal static void RegisterExtension(Channel channel, StandardOpenIdExtensionFactory.CreateDelegate extensionFactory) {
ErrorUtilities.VerifyArgumentNotNull(channel, "channel");
- OpenIdExtensionFactory factory = (OpenIdExtensionFactory)channel.BindingElements.OfType<ExtensionsBindingElement>().Single().ExtensionFactory;
- factory.RegisterExtension(extensionFactory);
+ var factory = (OpenIdExtensionFactoryAggregator)channel.BindingElements.OfType<ExtensionsBindingElement>().Single().ExtensionFactory;
+ factory.Factories.OfType<StandardOpenIdExtensionFactory>().Single().RegisterExtension(extensionFactory);
}
}
}
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
index f1994d1..76a46d0 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/OpenIdProviderTests.cs
@@ -6,11 +6,9 @@
namespace DotNetOpenAuth.Test.OpenId.Provider {
using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
using DotNetOpenAuth.OpenId.RelyingParty;
@@ -54,6 +52,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
Assert.AreSame(newSettings, this.provider.SecuritySettings);
}
+ [TestMethod]
+ public void ExtensionFactories() {
+ var factories = this.provider.ExtensionFactories;
+ Assert.IsNotNull(factories);
+ Assert.AreEqual(1, factories.Count);
+ Assert.IsInstanceOfType(factories[0], typeof(StandardOpenIdExtensionFactory));
+ }
+
/// <summary>
/// Verifies the Channel property.
/// </summary>
diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
index d2a75de..68bbff3 100644
--- a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/OpenIdRelyingPartyTests.cs
@@ -8,9 +8,8 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
using System;
using System.Linq;
using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Extensions;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -38,6 +37,15 @@ namespace DotNetOpenAuth.Test.OpenId.RelyingParty {
}
[TestMethod]
+ public void ExtensionFactories() {
+ var rp = new OpenIdRelyingParty(null);
+ var factories = rp.ExtensionFactories;
+ Assert.IsNotNull(factories);
+ Assert.AreEqual(1, factories.Count);
+ Assert.IsInstanceOfType(factories[0], typeof(StandardOpenIdExtensionFactory));
+ }
+
+ [TestMethod]
public void CreateRequest() {
var rp = this.CreateRelyingParty();
StoreAssociation(rp, OPUri, HmacShaAssociation.Create("somehandle", new byte[20], TimeSpan.FromDays(1)));
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index cf830c6..f49cd4d 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -9,7 +9,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
DotNetOpenAuth.vsmdi = DotNetOpenAuth.vsmdi
LocalTestRun.testrunconfig = LocalTestRun.testrunconfig
+ ..\doc\README.Bin.html = ..\doc\README.Bin.html
..\doc\README.html = ..\doc\README.html
+ ..\samples\README.html = ..\samples\README.html
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
diff --git a/src/DotNetOpenAuth/Configuration/OpenIdElement.cs b/src/DotNetOpenAuth/Configuration/OpenIdElement.cs
index d5986c6..25e067e 100644
--- a/src/DotNetOpenAuth/Configuration/OpenIdElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OpenIdElement.cs
@@ -8,6 +8,8 @@ namespace DotNetOpenAuth.Configuration {
using System;
using System.Configuration;
using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Messages;
/// <summary>
/// Represents the &lt;openid&gt; element in the host's .config file.
@@ -15,21 +17,32 @@ namespace DotNetOpenAuth.Configuration {
[ContractVerification(true)]
internal class OpenIdElement : ConfigurationElement {
/// <summary>
- /// Gets the name of the &lt;relyingParty&gt; sub-element.
+ /// The name of the &lt;relyingParty&gt; sub-element.
/// </summary>
private const string RelyingPartyElementName = "relyingParty";
/// <summary>
- /// Gets the name of the &lt;provider&gt; sub-element.
+ /// The name of the &lt;provider&gt; sub-element.
/// </summary>
private const string ProviderElementName = "provider";
/// <summary>
+ /// The name of the &lt;extensions&gt; sub-element.
+ /// </summary>
+ private const string ExtensionFactoriesElementName = "extensionFactories";
+
+ /// <summary>
/// Gets the name of the @maxAuthenticationTime attribute.
/// </summary>
private const string MaxAuthenticationTimePropertyName = "maxAuthenticationTime";
/// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdElement"/> class.
+ /// </summary>
+ internal OpenIdElement() {
+ }
+
+ /// <summary>
/// Gets or sets the maximum time a user can take to complete authentication.
/// </summary>
/// <remarks>
@@ -61,5 +74,15 @@ namespace DotNetOpenAuth.Configuration {
get { return (OpenIdProviderElement)this[ProviderElementName] ?? new OpenIdProviderElement(); }
set { this[ProviderElementName] = value; }
}
+
+ /// <summary>
+ /// Gets or sets the registered OpenID extensions.
+ /// </summary>
+ [ConfigurationProperty(ExtensionFactoriesElementName, IsDefaultCollection = false)]
+ [ConfigurationCollection(typeof(TypeConfigurationCollection<IOpenIdMessageExtension>))]
+ internal TypeConfigurationCollection<IOpenIdExtensionFactory> ExtensionFactories {
+ get { return (TypeConfigurationCollection<IOpenIdExtensionFactory>)this[ExtensionFactoriesElementName] ?? new TypeConfigurationCollection<IOpenIdExtensionFactory>(); }
+ set { this[ExtensionFactoriesElementName] = value; }
+ }
}
}
diff --git a/src/DotNetOpenAuth/Configuration/TypeConfigurationCollection.cs b/src/DotNetOpenAuth/Configuration/TypeConfigurationCollection.cs
new file mode 100644
index 0000000..00eeb15
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/TypeConfigurationCollection.cs
@@ -0,0 +1,75 @@
+//-----------------------------------------------------------------------
+// <copyright file="TypeConfigurationCollection.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Configuration {
+ using System;
+ using System.Collections.Generic;
+ using System.Configuration;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A collection of <see cref="TypeConfigurationElement"/>.
+ /// </summary>
+ /// <typeparam name="T">The type that all types specified in the elements must derive from.</typeparam>
+ [ContractVerification(true)]
+ internal class TypeConfigurationCollection<T> : ConfigurationElementCollection {
+ /// <summary>
+ /// Initializes a new instance of the TypeConfigurationCollection class.
+ /// </summary>
+ internal TypeConfigurationCollection() {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the TypeConfigurationCollection class.
+ /// </summary>
+ /// <param name="elements">The elements that should be added to the collection initially.</param>
+ internal TypeConfigurationCollection(IEnumerable<Type> elements) {
+ Contract.Requires(elements != null);
+ ErrorUtilities.VerifyArgumentNotNull(elements, "elements");
+
+ foreach (Type element in elements) {
+ this.BaseAdd(new TypeConfigurationElement<T> { TypeName = element.FullName });
+ }
+ }
+
+ /// <summary>
+ /// Creates instances of all the types listed in the collection.
+ /// </summary>
+ /// <param name="allowInternals">if set to <c>true</c> then internal types may be instantiated.</param>
+ /// <returns>A sequence of instances generated from types in this collection. May be empty, but never null.</returns>
+ internal IEnumerable<T> CreateInstances(bool allowInternals) {
+ Contract.Ensures(Contract.Result<IEnumerable<T>>() != null);
+ return from element in this.Cast<TypeConfigurationElement<T>>()
+ where element.CustomType != null
+ select element.CreateInstance(default(T), allowInternals);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </summary>
+ /// <returns>
+ /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override ConfigurationElement CreateNewElement() {
+ return new TypeConfigurationElement<T>();
+ }
+
+ /// <summary>
+ /// Gets the element key for a specified configuration element when overridden in a derived class.
+ /// </summary>
+ /// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for.</param>
+ /// <returns>
+ /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override object GetElementKey(ConfigurationElement element) {
+ Contract.Assume(element != null); // this should be Contract.Requires in base class.
+ return ((TypeConfigurationElement<T>)element).TypeName;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
index 5375046..022ef40 100644
--- a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
+++ b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
@@ -51,11 +51,23 @@ namespace DotNetOpenAuth.Configuration {
/// <param name="defaultValue">The value to return if no type is given in the .config file.</param>
/// <returns>The newly instantiated type.</returns>
public T CreateInstance(T defaultValue) {
+ return this.CreateInstance(defaultValue, false);
+ }
+
+ /// <summary>
+ /// Creates an instance of the type described in the .config file.
+ /// </summary>
+ /// <param name="defaultValue">The value to return if no type is given in the .config file.</param>
+ /// <param name="allowInternals">if set to <c>true</c> then internal types may be instantiated.</param>
+ /// <returns>The newly instantiated type.</returns>
+ public T CreateInstance(T defaultValue, bool allowInternals) {
if (this.CustomType != null) {
- // Although .NET will usually prevent our instantiating non-public types,
- // it will allow our instantiation of internal types within this same assembly.
- // But we don't want the host site to be able to do this, so we check ourselves.
- ErrorUtilities.VerifyArgument((this.CustomType.Attributes & TypeAttributes.Public) != 0, Strings.ConfigurationTypeMustBePublic, this.CustomType.FullName);
+ if (!allowInternals) {
+ // Although .NET will usually prevent our instantiating non-public types,
+ // it will allow our instantiation of internal types within this same assembly.
+ // But we don't want the host site to be able to do this, so we check ourselves.
+ ErrorUtilities.VerifyArgument((this.CustomType.Attributes & TypeAttributes.Public) != 0, Strings.ConfigurationTypeMustBePublic, this.CustomType.FullName);
+ }
return (T)Activator.CreateInstance(this.CustomType);
} else {
return defaultValue;
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index a15b3a8..5c13092 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -181,6 +181,7 @@
<Compile Include="Configuration\OpenIdProviderSecuritySettingsElement.cs" />
<Compile Include="Configuration\OpenIdRelyingPartyElement.cs" />
<Compile Include="Configuration\OpenIdRelyingPartySecuritySettingsElement.cs" />
+ <Compile Include="Configuration\TypeConfigurationCollection.cs" />
<Compile Include="Configuration\TypeConfigurationElement.cs" />
<Compile Include="Configuration\UntrustedWebRequestElement.cs" />
<Compile Include="Configuration\HostNameOrRegexCollection.cs" />
@@ -328,7 +329,8 @@
<Compile Include="OpenId\Extensions\ExtensionBase.cs" />
<Compile Include="OpenId\Extensions\ExtensionArgumentsManager.cs" />
<Compile Include="OpenId\Extensions\IClientScriptExtensionResponse.cs" />
- <Compile Include="OpenId\Extensions\OpenIdExtensionFactory.cs" />
+ <Compile Include="OpenId\Extensions\OpenIdExtensionFactoryAggregator.cs" />
+ <Compile Include="OpenId\Extensions\StandardOpenIdExtensionFactory.cs" />
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\AuthenticationPolicies.cs" />
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\Constants.cs" />
<Compile Include="OpenId\Extensions\ProviderAuthenticationPolicy\DateTimeEncoder.cs" />
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index de6b5ec..c0a20ab 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -358,6 +358,11 @@ namespace DotNetOpenAuth.Messaging {
/// <returns>The deserialized message, if one is found. Null otherwise.</returns>
public IDirectedProtocolMessage ReadFromRequest(HttpRequestInfo httpRequest) {
Contract.Requires(httpRequest != null);
+ ErrorUtilities.VerifyArgumentNotNull(httpRequest, "httpRequest");
+
+ if (Logger.Channel.IsInfoEnabled && httpRequest.UrlBeforeRewriting != null) {
+ Logger.Channel.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.UrlBeforeRewriting.AbsoluteUri);
+ }
IDirectedProtocolMessage requestMessage = this.ReadFromRequestCore(httpRequest);
if (requestMessage != null) {
Logger.Channel.DebugFormat("Incoming request received: {0}", requestMessage.GetType().Name);
diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
index 418f6b2..367c14f 100644
--- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
+++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
@@ -194,8 +194,9 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
internal Uri UrlBeforeRewriting {
get {
- Contract.Requires(this.Url != null);
- Contract.Requires(this.RawUrl != null);
+ if (this.Url == null || this.RawUrl == null) {
+ return null;
+ }
// We use Request.Url for the full path to the server, and modify it
// with Request.RawUrl to capture both the cookieless session "directory" if it exists
diff --git a/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs b/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs
index 5f4936d..dee81dc 100644
--- a/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/IncomingWebResponse.cs
@@ -42,7 +42,11 @@ namespace DotNetOpenAuth.Messaging {
this.RequestUri = requestUri;
if (!string.IsNullOrEmpty(response.ContentType)) {
- this.ContentType = new ContentType(response.ContentType);
+ try {
+ this.ContentType = new ContentType(response.ContentType);
+ } catch (FormatException) {
+ Logger.Messaging.ErrorFormat("HTTP response to {0} included an invalid Content-Type header value: {1}", response.ResponseUri.AbsoluteUri, response.ContentType);
+ }
}
this.ContentEncoding = string.IsNullOrEmpty(response.ContentEncoding) ? DefaultContentEncoding : response.ContentEncoding;
this.FinalUri = response.ResponseUri;
@@ -64,7 +68,11 @@ namespace DotNetOpenAuth.Messaging {
this.RequestUri = requestUri;
this.Status = statusCode;
if (!string.IsNullOrEmpty(contentType)) {
- this.ContentType = new ContentType(contentType);
+ try {
+ this.ContentType = new ContentType(contentType);
+ } catch (FormatException) {
+ Logger.Messaging.ErrorFormat("HTTP response to {0} included an invalid Content-Type header value: {1}", responseUri.AbsoluteUri, contentType);
+ }
}
this.ContentEncoding = string.IsNullOrEmpty(contentEncoding) ? DefaultContentEncoding : contentEncoding;
this.Headers = headers;
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
index 3f72c48..cdb571b 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
@@ -191,6 +191,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// returned in the sequence. May be null.</param>
/// <returns>A sequence of extensions in the message.</returns>
private IEnumerable<IOpenIdMessageExtension> GetExtensions(IProtocolMessageWithExtensions message, bool ignoreUnsigned, Func<string, bool> extensionFilter) {
+ bool isAtProvider = message is SignedResponseRequest;
+
// We have a helper class that will do all the heavy-lifting of organizing
// all the extensions, their aliases, and their parameters.
var extensionManager = ExtensionArgumentsManager.CreateIncomingExtensions(this.GetExtensionsDictionary(message, ignoreUnsigned));
@@ -204,7 +206,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
var extensionData = extensionManager.GetExtensionArguments(typeUri);
// Initialize this particular extension.
- IOpenIdMessageExtension extension = this.ExtensionFactory.Create(typeUri, extensionData, message);
+ IOpenIdMessageExtension extension = this.ExtensionFactory.Create(typeUri, extensionData, message, isAtProvider);
if (extension != null) {
MessageDictionary extensionDictionary = this.Channel.MessageDescriptions.GetAccessor(extension);
foreach (var pair in extensionData) {
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/IOpenIdExtensionFactory.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/IOpenIdExtensionFactory.cs
index 4bae08f..31223a0 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/IOpenIdExtensionFactory.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/IOpenIdExtensionFactory.cs
@@ -12,13 +12,29 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// <summary>
/// OpenID extension factory class for creating extensions based on received Type URIs.
/// </summary>
- internal interface IOpenIdExtensionFactory {
+ /// <remarks>
+ /// OpenID extension factories must be registered with the library. This can be
+ /// done by adding a factory to <see cref="OpenIdRelyingParty.ExtensionFactories"/>
+ /// or <see cref="OpenIdProvider.ExtensionFactories"/>, or by adding a snippet
+ /// such as the following to your web.config file:
+ /// <example>
+ /// &lt;dotNetOpenAuth&gt;
+ /// &lt;openid&gt;
+ /// &lt;extensionFactories&gt;
+ /// &lt;add type="DotNetOpenAuth.ApplicationBlock.CustomExtensions.Acme, DotNetOpenAuth.ApplicationBlock" /&gt;
+ /// &lt;/extensionFactories&gt;
+ /// &lt;/openid&gt;
+ /// &lt;/dotNetOpenAuth&gt;
+ /// </example>
+ /// </remarks>
+ public interface IOpenIdExtensionFactory {
/// <summary>
/// Creates a new instance of some extension based on the received extension parameters.
/// </summary>
/// <param name="typeUri">The type URI of the extension.</param>
/// <param name="data">The parameters associated specifically with this extension.</param>
/// <param name="baseMessage">The OpenID message carrying this extension.</param>
+ /// <param name="isProviderRole">A value indicating whether this extension is being received at the OpenID Provider.</param>
/// <returns>
/// An instance of <see cref="IOpenIdMessageExtension"/> if the factory recognizes
/// the extension described in the input parameters; <c>null</c> otherwise.
@@ -27,6 +43,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// This factory method need only initialize properties in the instantiated extension object
/// that are not bound using <see cref="MessagePartAttribute"/>.
/// </remarks>
- IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage);
+ IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage, bool isProviderRole);
}
}
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
index d1c5db4..67fbcd4 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs
@@ -134,14 +134,17 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// A value indicating whether the channel is set up
/// with no functional security binding elements.
/// </summary>
+ /// <returns>A new <see cref="OpenIdChannel"/> instance that will not perform verification on incoming messages or apply any security to outgoing messages.</returns>
/// <remarks>
- /// <para>A value of <c>true</c> allows the relying party to preview incoming
+ /// <para>A value of <c>true</c> allows the relying party to preview incoming
/// messages without invalidating nonces or checking signatures.</para>
- /// <para>Setting this to <c>true</c> poses a great security risk and is only
+ /// <para>Setting this to <c>true</c> poses a great security risk and is only
/// present to support the <see cref="OpenIdAjaxTextBox"/> which needs to preview
/// messages, and will validate them later.</para>
/// </remarks>
internal static OpenIdChannel CreateNonVerifyingChannel() {
+ Contract.Ensures(Contract.Result<OpenIdChannel>() != null);
+
return new OpenIdChannel(null, null, new OpenIdMessageFactory(), new RelyingPartySecuritySettings(), true);
}
@@ -333,9 +336,11 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
signingElement = new SigningBindingElement(opAssociationStore, opSecuritySettings);
}
+ var extensionFactory = OpenIdExtensionFactoryAggregator.LoadFromConfiguration();
+
List<IChannelBindingElement> elements = new List<IChannelBindingElement>(7);
if (isRelyingPartyRole) {
- elements.Add(new ExtensionsBindingElement(new OpenIdExtensionFactory(), rpSecuritySettings));
+ elements.Add(new ExtensionsBindingElement(extensionFactory, rpSecuritySettings));
elements.Add(new BackwardCompatibilityBindingElement());
if (associationStore != null) {
@@ -351,7 +356,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
elements.Add(new ReturnToSignatureBindingElement(rpAssociationStore, rpSecuritySettings));
}
} else {
- elements.Add(new ExtensionsBindingElement(new OpenIdExtensionFactory(), opSecuritySettings));
+ elements.Add(new ExtensionsBindingElement(extensionFactory, opSecuritySettings));
// Providers must always have a nonce store.
ErrorUtilities.VerifyArgumentNotNull(nonceStore, "nonceStore");
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
index 5ea04aa..a69e226 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
@@ -21,8 +21,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is SignedResponseRequest) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && isProviderRole) {
string mode;
if (data.TryGetValue("mode", out mode) && mode == Mode) {
return new FetchRequest();
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
index 7f4bd77..9413e2f 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
@@ -19,8 +19,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is IndirectSignedResponse) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && !isProviderRole) {
string mode;
if (data.TryGetValue("mode", out mode) && mode == Mode) {
return new FetchResponse();
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
index e3743e4..641b17a 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
@@ -19,8 +19,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is SignedResponseRequest) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && isProviderRole) {
string mode;
if (data.TryGetValue("mode", out mode) && mode == Mode) {
return new StoreRequest();
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
index b6761b5..ba7f091 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
@@ -17,8 +17,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is IndirectSignedResponse) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && !isProviderRole) {
string mode;
if (data.TryGetValue("mode", out mode) && (mode == SuccessMode || mode == FailureMode)) {
return new StoreResponse();
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactoryAggregator.cs b/src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactoryAggregator.cs
new file mode 100644
index 0000000..05e6687
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactoryAggregator.cs
@@ -0,0 +1,81 @@
+//-----------------------------------------------------------------------
+// <copyright file="OpenIdExtensionFactoryAggregator.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions {
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Messages;
+
+ /// <summary>
+ /// An OpenID extension factory that only delegates extension
+ /// instantiation requests to other factories.
+ /// </summary>
+ internal class OpenIdExtensionFactoryAggregator : IOpenIdExtensionFactory {
+ /// <summary>
+ /// The list of factories this factory delegates to.
+ /// </summary>
+ private List<IOpenIdExtensionFactory> factories = new List<IOpenIdExtensionFactory>(2);
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdExtensionFactoryAggregator"/> class.
+ /// </summary>
+ internal OpenIdExtensionFactoryAggregator() {
+ }
+
+ /// <summary>
+ /// Gets the extension factories that this aggregating factory delegates to.
+ /// </summary>
+ /// <value>A list of factories. May be empty, but never null.</value>
+ internal IList<IOpenIdExtensionFactory> Factories {
+ get { return this.factories; }
+ }
+
+ #region IOpenIdExtensionFactory Members
+
+ /// <summary>
+ /// Creates a new instance of some extension based on the received extension parameters.
+ /// </summary>
+ /// <param name="typeUri">The type URI of the extension.</param>
+ /// <param name="data">The parameters associated specifically with this extension.</param>
+ /// <param name="baseMessage">The OpenID message carrying this extension.</param>
+ /// <param name="isProviderRole">A value indicating whether this extension is being received at the OpenID Provider.</param>
+ /// <returns>
+ /// An instance of <see cref="IOpenIdMessageExtension"/> if the factory recognizes
+ /// the extension described in the input parameters; <c>null</c> otherwise.
+ /// </returns>
+ /// <remarks>
+ /// This factory method need only initialize properties in the instantiated extension object
+ /// that are not bound using <see cref="MessagePartAttribute"/>.
+ /// </remarks>
+ public IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage, bool isProviderRole) {
+ foreach (var factory in this.factories) {
+ IOpenIdMessageExtension result = factory.Create(typeUri, data, baseMessage, isProviderRole);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Loads the default factory and additional ones given by the configuration.
+ /// </summary>
+ /// <returns>A new instance of <see cref="OpenIdExtensionFactoryAggregator"/>.</returns>
+ internal static OpenIdExtensionFactoryAggregator LoadFromConfiguration() {
+ Contract.Ensures(Contract.Result<OpenIdExtensionFactoryAggregator>() != null);
+ var factoriesElement = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OpenId.ExtensionFactories;
+ var aggregator = new OpenIdExtensionFactoryAggregator();
+ aggregator.Factories.Add(new StandardOpenIdExtensionFactory());
+ aggregator.factories.AddRange(factoriesElement.CreateInstances(false));
+ return aggregator;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequest.cs
index 5b319be..84589dc 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyRequest.cs
@@ -18,8 +18,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is SignedResponseRequest) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && isProviderRole) {
return new PolicyRequest();
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
index 75965e3..4b2bcc9 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ProviderAuthenticationPolicy/PolicyResponse.cs
@@ -20,8 +20,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.TypeUri && baseMessage is IndirectSignedResponse) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.TypeUri && !isProviderRole) {
return new PolicyResponse();
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
index 300827c..800a2ff 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
@@ -22,8 +22,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.sreg_ns && baseMessage is SignedResponseRequest) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.sreg_ns && isProviderRole) {
return new ClaimsRequest(typeUri);
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsResponse.cs
index 5696d43..a58c754 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsResponse.cs
@@ -25,8 +25,8 @@ namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
- internal static readonly OpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage) => {
- if (typeUri == Constants.sreg_ns && baseMessage is IndirectSignedResponse) {
+ internal static readonly StandardOpenIdExtensionFactory.CreateDelegate Factory = (typeUri, data, baseMessage, isProviderRole) => {
+ if (typeUri == Constants.sreg_ns && !isProviderRole) {
return new ClaimsResponse(typeUri);
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactory.cs b/src/DotNetOpenAuth/OpenId/Extensions/StandardOpenIdExtensionFactory.cs
index 1c44282..9dda6ad 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/OpenIdExtensionFactory.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/StandardOpenIdExtensionFactory.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="OpenIdExtensionFactory.cs" company="Andrew Arnott">
+// <copyright file="StandardOpenIdExtensionFactory.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -17,16 +17,16 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// An OpenID extension factory that supports registration so that third-party
/// extensions can add themselves to this library's supported extension list.
/// </summary>
- internal class OpenIdExtensionFactory : IOpenIdExtensionFactory {
+ internal class StandardOpenIdExtensionFactory : IOpenIdExtensionFactory {
/// <summary>
/// A collection of the registered OpenID extensions.
/// </summary>
private List<CreateDelegate> registeredExtensions = new List<CreateDelegate>();
/// <summary>
- /// Initializes a new instance of the <see cref="OpenIdExtensionFactory"/> class.
+ /// Initializes a new instance of the <see cref="StandardOpenIdExtensionFactory"/> class.
/// </summary>
- internal OpenIdExtensionFactory() {
+ internal StandardOpenIdExtensionFactory() {
this.RegisterExtension(ClaimsRequest.Factory);
this.RegisterExtension(ClaimsResponse.Factory);
this.RegisterExtension(FetchRequest.Factory);
@@ -43,11 +43,12 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// <param name="typeUri">The type URI of the extension.</param>
/// <param name="data">The parameters associated specifically with this extension.</param>
/// <param name="baseMessage">The OpenID message carrying this extension.</param>
+ /// <param name="isProviderRole">A value indicating whether this extension is being received at the OpenID Provider.</param>
/// <returns>
/// An instance of <see cref="IOpenIdMessageExtension"/> if the factory recognizes
/// the extension described in the input parameters; <c>null</c> otherwise.
/// </returns>
- internal delegate IOpenIdMessageExtension CreateDelegate(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage);
+ internal delegate IOpenIdMessageExtension CreateDelegate(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage, bool isProviderRole);
#region IOpenIdExtensionFactory Members
@@ -57,6 +58,7 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// <param name="typeUri">The type URI of the extension.</param>
/// <param name="data">The parameters associated specifically with this extension.</param>
/// <param name="baseMessage">The OpenID message carrying this extension.</param>
+ /// <param name="isProviderRole">A value indicating whether this extension is being received at the OpenID Provider.</param>
/// <returns>
/// An instance of <see cref="IOpenIdMessageExtension"/> if the factory recognizes
/// the extension described in the input parameters; <c>null</c> otherwise.
@@ -65,9 +67,9 @@ namespace DotNetOpenAuth.OpenId.Extensions {
/// This factory method need only initialize properties in the instantiated extension object
/// that are not bound using <see cref="MessagePartAttribute"/>.
/// </remarks>
- public IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage) {
+ public IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage, bool isProviderRole) {
foreach (var factoryMethod in this.registeredExtensions) {
- IOpenIdMessageExtension result = factoryMethod(typeUri, data, baseMessage);
+ IOpenIdMessageExtension result = factoryMethod(typeUri, data, baseMessage, isProviderRole);
if (result != null) {
return result;
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs b/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs
index 8a1a8e5..131b4ea 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IOpenIdMessageExtension.cs
@@ -14,6 +14,11 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <summary>
/// The contract any OpenID extension for DotNetOpenAuth must implement.
/// </summary>
+ /// <remarks>
+ /// Classes that implement this interface should be marked as
+ /// [<see cref="Serializable"/>] to allow serializing state servers
+ /// to cache messages, particularly responses.
+ /// </remarks>
public interface IOpenIdMessageExtension : IExtensionMessage {
/// <summary>
/// Gets the TypeURI the extension uses in the OpenID protocol and in XRDS advertisements.
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index d948073..3c4116a 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.3521
+// Runtime Version:2.0.50727.4912
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -578,6 +578,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to This feature is unavailable due to an unrecognized channel configuration..
+ /// </summary>
+ internal static string UnsupportedChannelConfiguration {
+ get {
+ return ResourceManager.GetString("UnsupportedChannelConfiguration", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests..
/// </summary>
internal static string UserSetupUrlRequiredInImmediateNegativeResponse {
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index 16b1780..7356c10 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -298,4 +298,7 @@ Discovered endpoint info:
<data name="ResponseNotReady" xml:space="preserve">
<value>The response is not ready. Use IsResponseReady to check whether a response is ready first.</value>
</data>
+ <data name="UnsupportedChannelConfiguration" xml:space="preserve">
+ <value>This feature is unavailable due to an unrecognized channel configuration.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs b/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
index 4271eab..3c5f00d 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdUtilities.cs
@@ -15,6 +15,7 @@ namespace DotNetOpenAuth.OpenId {
using System.Web.UI;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Extensions;
/// <summary>
/// A set of utilities especially useful to OpenID.
@@ -126,5 +127,29 @@ namespace DotNetOpenAuth.OpenId {
return fullyQualifiedRealm;
}
+
+ /// <summary>
+ /// Gets the extension factories from the extension aggregator on an OpenID channel.
+ /// </summary>
+ /// <param name="channel">The channel.</param>
+ /// <returns>The list of factories that will be used to generate extension instances.</returns>
+ /// <remarks>
+ /// This is an extension method on <see cref="Channel"/> rather than an instance
+ /// method on <see cref="OpenIdChannel"/> because the <see cref="OpenIdRelyingParty"/>
+ /// and <see cref="OpenIdProvider"/> classes don't strong-type to <see cref="OpenIdChannel"/>
+ /// to allow flexibility in the specific type of channel the user (or tests)
+ /// can plug in.
+ /// </remarks>
+ internal static IList<IOpenIdExtensionFactory> GetExtensionFactories(this Channel channel) {
+ Contract.Requires(channel != null);
+ ErrorUtilities.VerifyArgumentNotNull(channel, "channel");
+
+ var extensionsBindingElement = channel.BindingElements.OfType<ExtensionsBindingElement>().SingleOrDefault();
+ ErrorUtilities.VerifyOperation(extensionsBindingElement != null, OpenIdStrings.UnsupportedChannelConfiguration);
+ IOpenIdExtensionFactory factory = extensionsBindingElement.ExtensionFactory;
+ var aggregator = factory as OpenIdExtensionFactoryAggregator;
+ ErrorUtilities.VerifyOperation(aggregator != null, OpenIdStrings.UnsupportedChannelConfiguration);
+ return aggregator.Factories;
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index ee4d6cb..c3780a9 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OpenId.Provider {
using System;
+ using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
@@ -124,6 +125,13 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
/// <summary>
+ /// Gets the extension factories.
+ /// </summary>
+ public IList<IOpenIdExtensionFactory> ExtensionFactories {
+ get { return this.Channel.GetExtensionFactories(); }
+ }
+
+ /// <summary>
/// Gets or sets the mechanism a host site can use to receive
/// notifications of errors when communicating with remote parties.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index a78c2e9..4bcaf10 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -16,6 +16,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Extensions;
using DotNetOpenAuth.OpenId.Messages;
/// <summary>
@@ -201,6 +202,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Gets the extension factories.
+ /// </summary>
+ public IList<IOpenIdExtensionFactory> ExtensionFactories {
+ get { return this.Channel.GetExtensionFactories(); }
+ }
+
+ /// <summary>
/// Gets a value indicating whether this Relying Party can sign its return_to
/// parameter in outgoing authentication requests.
/// </summary>