summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-06-19 23:13:22 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-06-20 08:43:09 -0700
commit8eed943f4bd72d54d52ce9088ee968e354d4fd0a (patch)
tree491e655ce6ccb57b4870a54930a504b34618017e /src
parent0d3741fe631df59b30a7808a29294167f45cad39 (diff)
downloadDotNetOpenAuth-8eed943f4bd72d54d52ce9088ee968e354d4fd0a.zip
DotNetOpenAuth-8eed943f4bd72d54d52ce9088ee968e354d4fd0a.tar.gz
DotNetOpenAuth-8eed943f4bd72d54d52ce9088ee968e354d4fd0a.tar.bz2
Added the AXFetchAsSregTransform OpenID behavior that allows RPs and OPs to deal strictly with Sreg and yet be compatible with all known formats of AX requests and responses.
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperTests.cs132
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs24
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs11
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj4
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs126
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs45
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs364
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/InteropHelper.cs201
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/Request.cs2
-rw-r--r--src/DotNetOpenAuth/Settings.StyleCop7
12 files changed, 699 insertions, 229 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index fa768a8..8a834dd 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -98,6 +98,10 @@
<HintPath>..\..\lib\Microsoft.Contracts.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+ <Reference Include="Moq, Version=3.1.416.3, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\Moq.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core">
@@ -196,7 +200,7 @@
<Compile Include="OpenId\Extensions\SimpleRegistration\ClaimsRequestTests.cs" />
<Compile Include="OpenId\Extensions\UI\UIRequestTests.cs" />
<Compile Include="OpenId\IdentifierTests.cs" />
- <Compile Include="OpenId\InteropHelperTests.cs" />
+ <Compile Include="OpenId\Extensions\ExtensionsInteropHelperTests.cs" />
<Compile Include="OpenId\Messages\AssociateDiffieHellmanRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateUnsuccessfulResponseTests.cs" />
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperTests.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperTests.cs
new file mode 100644
index 0000000..ee6aded
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionsInteropHelperTests.cs
@@ -0,0 +1,132 @@
+//-----------------------------------------------------------------------
+// <copyright file="InteropHelperTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.OpenId {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.OpenId;
+ using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+ using Moq;
+ using DotNetOpenAuth.OpenId.Extensions;
+
+ [TestClass]
+ public class ExtensionsInteropHelperTests : OpenIdTestBase {
+ private AuthenticationRequest authReq;
+ private ClaimsRequest sreg;
+
+ [TestInitialize]
+ public override void SetUp() {
+ base.SetUp();
+
+ var rp = CreateRelyingParty(true);
+ Identifier identifier = this.GetMockIdentifier(ProtocolVersion.V20);
+ this.authReq = (AuthenticationRequest)rp.CreateRequest(identifier, RPRealmUri, RPUri);
+ this.sreg = new ClaimsRequest {
+ Nickname = DemandLevel.Request,
+ FullName = DemandLevel.Request,
+ BirthDate = DemandLevel.Request,
+ Email = DemandLevel.Require,
+ Country = DemandLevel.Request,
+ PostalCode = DemandLevel.Request,
+ Gender = DemandLevel.Request,
+ Language = DemandLevel.Request,
+ TimeZone = DemandLevel.Request,
+ };
+ }
+
+ /// <summary>
+ /// Verifies that without an Sreg extension to copy from, no AX extension request is added.
+ /// </summary>
+ [TestMethod]
+ public void SpreadSregToAXNoExtensions() {
+ ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg);
+ Assert.AreEqual(0, this.authReq.AppliedExtensions.Count());
+ }
+
+ /// <summary>
+ /// Verifies that Sreg requests are correctly copied to axschema.org AX requests.
+ /// </summary>
+ [TestMethod]
+ public void SpreadSregToAXBasic() {
+ this.authReq.AddExtension(this.sreg);
+ ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg);
+ var ax = this.authReq.AppliedExtensions.OfType<FetchRequest>().Single();
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Name.Alias].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Name.FullName].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.BirthDate.WholeBirthDate].IsRequired);
+ Assert.IsTrue(ax.Attributes[WellKnownAttributes.Contact.Email].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Contact.HomeAddress.Country].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Contact.HomeAddress.PostalCode].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Person.Gender].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Preferences.Language].IsRequired);
+ Assert.IsFalse(ax.Attributes[WellKnownAttributes.Preferences.TimeZone].IsRequired);
+ }
+
+ /// <summary>
+ /// Verifies that sreg can spread to multiple AX schemas.
+ /// </summary>
+ [TestMethod]
+ public void SpreadSregToAxMultipleSchemas() {
+ this.authReq.AddExtension(this.sreg);
+ ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.AXSchemaOrg | AXAttributeFormats.SchemaOpenIdNet);
+ var ax = this.authReq.AppliedExtensions.OfType<FetchRequest>().Single();
+ Assert.IsTrue(ax.Attributes.Contains(WellKnownAttributes.Name.Alias));
+ Assert.IsTrue(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet)));
+ Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema)));
+ }
+
+ /// <summary>
+ /// Verifies no spread if the OP advertises sreg support.
+ /// </summary>
+ [TestMethod]
+ public void SpreadSregToAxNoOpIfOPSupportsSreg() {
+ this.authReq.AddExtension(this.sreg);
+ this.InjectAdvertisedTypeUri(DotNetOpenAuth.OpenId.Extensions.SimpleRegistration.Constants.sreg_ns);
+ ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.All);
+ Assert.IsFalse(this.authReq.AppliedExtensions.OfType<FetchRequest>().Any());
+ }
+
+ /// <summary>
+ /// Verifies a targeted AX request if the OP advertises a recognized type URI format.
+ /// </summary>
+ [TestMethod]
+ public void SpreadSregToAxTargetedAtOPFormat() {
+ this.authReq.AddExtension(this.sreg);
+ this.InjectAdvertisedTypeUri(WellKnownAttributes.Name.FullName);
+ ExtensionsInteropHelper.SpreadSregToAX(this.authReq, AXAttributeFormats.OpenIdNetSchema);
+ var ax = this.authReq.AppliedExtensions.OfType<FetchRequest>().Single();
+ Assert.IsFalse(ax.Attributes.Contains(ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Contact.Email, AXAttributeFormats.OpenIdNetSchema)));
+ Assert.IsTrue(ax.Attributes.Contains(WellKnownAttributes.Contact.Email));
+ }
+
+ /// <summary>
+ /// Verifies that TransformAXFormat correctly translates AX schema Type URIs.
+ /// </summary>
+ [TestMethod]
+ public void TransformAXFormatTest() {
+ Assert.AreEqual(WellKnownAttributes.Name.Alias, ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.AXSchemaOrg));
+ Assert.AreEqual("http://schema.openid.net/namePerson/friendly", ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.SchemaOpenIdNet));
+ Assert.AreEqual("http://openid.net/schema/namePerson/friendly", ExtensionsInteropHelper_Accessor.TransformAXFormat(WellKnownAttributes.Name.Alias, AXAttributeFormats.OpenIdNetSchema));
+ }
+
+ /// <summary>
+ /// Injects the advertised type URI into the list of advertised services for the authentication request.
+ /// </summary>
+ /// <param name="typeUri">The type URI.</param>
+ private void InjectAdvertisedTypeUri(string typeUri) {
+ var serviceEndpoint = ServiceEndpoint_Accessor.AttachShadow(((ServiceEndpoint)this.authReq.Provider));
+ serviceEndpoint.ProviderDescription = ProviderEndpointDescription_Accessor.AttachShadow(
+ new ProviderEndpointDescription(
+ serviceEndpoint.ProviderDescription.Endpoint,
+ serviceEndpoint.ProviderDescription.Capabilities.Concat(new[] { typeUri })));
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs b/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs
deleted file mode 100644
index cf34c72..0000000
--- a/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="InteropHelperTests.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.OpenId {
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- [TestClass]
- public class InteropHelperTests {
- /// <summary>
- /// Verifies that Sreg requests are correctly copied to axschema.org AX requests.
- /// </summary>
- [TestMethod]
- public void SpreadSregToAX() {
- Assert.Inconclusive("Not yet implemented.");
- }
- }
-}
diff --git a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
index 8fa5580..59c818c 100644
--- a/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/OpenIdTestBase.cs
@@ -187,7 +187,16 @@ namespace DotNetOpenAuth.Test.OpenId {
/// </summary>
/// <returns>The new instance.</returns>
protected OpenIdRelyingParty CreateRelyingParty() {
- var rp = new OpenIdRelyingParty(new StandardRelyingPartyApplicationStore());
+ return this.CreateRelyingParty(false);
+ }
+
+ /// <summary>
+ /// Creates a standard <see cref="OpenIdRelyingParty"/> instance for general testing.
+ /// </summary>
+ /// <param name="stateless">if set to <c>true</c> a stateless RP is created.</param>
+ /// <returns>The new instance.</returns>
+ protected OpenIdRelyingParty CreateRelyingParty(bool stateless) {
+ var rp = new OpenIdRelyingParty(stateless ? null : new StandardRelyingPartyApplicationStore());
rp.Channel.WebRequestHandler = this.MockResponder.MockWebRequestHandler;
return rp;
}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index e29aa6d..d3eb5e2 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -330,6 +330,7 @@
<Compile Include="OpenId\Association.cs" />
<Compile Include="OpenId\AssociationMemoryStore.cs" />
<Compile Include="OpenId\Associations.cs" />
+ <Compile Include="OpenId\Behaviors\AXFetchAsSregTransform.cs" />
<Compile Include="OpenId\Behaviors\BehaviorStrings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@@ -352,6 +353,7 @@
<Compile Include="OpenId\Extensions\AliasManager.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeRequest.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeValues.cs" />
+ <Compile Include="OpenId\Extensions\AttributeExchange\AXAttributeFormats.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AXUtilities.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\Constants.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchRequest.cs" />
@@ -386,7 +388,7 @@
<Compile Include="OpenId\Extensions\UI\UIRequest.cs" />
<Compile Include="OpenId\Identifier.cs" />
<Compile Include="OpenId\IdentifierContract.cs" />
- <Compile Include="OpenId\InteropHelper.cs" />
+ <Compile Include="OpenId\Extensions\ExtensionsInteropHelper.cs" />
<Compile Include="OpenId\Interop\AuthenticationResponseShim.cs" />
<Compile Include="OpenId\Interop\ClaimsResponseShim.cs" />
<Compile Include="OpenId\Interop\OpenIdRelyingPartyShim.cs" />
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
new file mode 100644
index 0000000..f895a27
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
@@ -0,0 +1,126 @@
+//-----------------------------------------------------------------------
+// <copyright file="AXFetchAsSregTransform.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Behaviors {
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions;
+ using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.Provider;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ /// <summary>
+ /// An Attribute Exchange and Simple Registration filter to make all incoming attribute
+ /// requests look like Simple Registration requests, and to convert the response
+ /// to the originally requested extension and format.
+ /// </summary>
+ public class AXFetchAsSregTransform : IRelyingPartyBehavior, IProviderBehavior {
+ /// <summary>
+ /// Initializes static members of the <see cref="AXFetchAsSregTransform"/> class.
+ /// </summary>
+ static AXFetchAsSregTransform() {
+ AXFormats = AXAttributeFormats.Common;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AXFetchAsSregTransform"/> class.
+ /// </summary>
+ public AXFetchAsSregTransform() {
+ }
+
+ /// <summary>
+ /// Gets or sets the AX attribute type URI formats this transform is willing to work with.
+ /// </summary>
+ public static AXAttributeFormats AXFormats { get; set; }
+
+ #region IRelyingPartyBehavior Members
+
+ /// <summary>
+ /// Applies a well known set of security requirements to a default set of security settings.
+ /// </summary>
+ /// <param name="securitySettings">The security settings to enhance with the requirements of this profile.</param>
+ /// <remarks>
+ /// Care should be taken to never decrease security when applying a profile.
+ /// Profiles should only enhance security requirements to avoid being
+ /// incompatible with each other.
+ /// </remarks>
+ void IRelyingPartyBehavior.ApplySecuritySettings(RelyingPartySecuritySettings securitySettings) {
+ }
+
+ /// <summary>
+ /// Called when an authentication request is about to be sent.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <remarks>
+ /// Implementations should be prepared to be called multiple times on the same outgoing message
+ /// without malfunctioning.
+ /// </remarks>
+ void IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(RelyingParty.IAuthenticationRequest request) {
+ request.SpreadSregToAX(AXFormats);
+ }
+
+ /// <summary>
+ /// Called when an incoming positive assertion is received.
+ /// </summary>
+ /// <param name="assertion">The positive assertion.</param>
+ void IRelyingPartyBehavior.OnIncomingPositiveAssertion(IAuthenticationResponse assertion) {
+ if (assertion.GetExtension<ClaimsResponse>() == null) {
+ ClaimsResponse sreg = assertion.UnifyExtensionsAsSreg(true);
+ ((PositiveAnonymousResponse)assertion).Response.Extensions.Add(sreg);
+ }
+ }
+
+ #endregion
+
+ #region IProviderBehavior Members
+
+ /// <summary>
+ /// Called when a request is received by the Provider.
+ /// </summary>
+ /// <param name="request">The incoming request.</param>
+ /// <returns>
+ /// <c>true</c> if this behavior owns this request and wants to stop other behaviors
+ /// from handling it; <c>false</c> to allow other behaviors to process this request.
+ /// </returns>
+ /// <remarks>
+ /// Implementations may set a new value to <see cref="IRequest.SecuritySettings"/> but
+ /// should not change the properties on the instance of <see cref="ProviderSecuritySettings"/>
+ /// itself as that instance may be shared across many requests.
+ /// </remarks>
+ bool IProviderBehavior.OnIncomingRequest(IRequest request) {
+ var extensionRequest = request as Provider.HostProcessedRequest;
+ if (extensionRequest != null) {
+ if (extensionRequest.GetExtension<ClaimsRequest>() == null) {
+ ClaimsRequest sreg = extensionRequest.UnifyExtensionsAsSreg();
+ if (sreg != null) {
+ ((IProtocolMessageWithExtensions)extensionRequest.RequestMessage).Extensions.Add(sreg);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Called when the Provider is preparing to send a response to an authentication request.
+ /// </summary>
+ /// <param name="request">The request that is configured to generate the outgoing response.</param>
+ /// <returns>
+ /// <c>true</c> if this behavior owns this request and wants to stop other behaviors
+ /// from handling it; <c>false</c> to allow other behaviors to process this request.
+ /// </returns>
+ bool IProviderBehavior.OnOutgoingResponse(Provider.IAuthenticationRequest request) {
+ request.ConvertSregToMatchRequest();
+ return false;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs
new file mode 100644
index 0000000..7e4ed73
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXAttributeFormats.cs
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+// <copyright file="AXAttributeFormats.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
+ using System;
+
+ /// <summary>
+ /// The various Type URI formats an AX attribute may use by various remote parties.
+ /// </summary>
+ [Flags]
+ public enum AXAttributeFormats {
+ /// <summary>
+ /// No attribute format.
+ /// </summary>
+ None = 0x0,
+
+ /// <summary>
+ /// AX attributes should use the Type URI format starting with <c>http://axschema.org/</c>.
+ /// </summary>
+ AXSchemaOrg = 0x1,
+
+ /// <summary>
+ /// AX attributes should use the Type URI format starting with <c>http://schema.openid.net/</c>.
+ /// </summary>
+ SchemaOpenIdNet = 0x2,
+
+ /// <summary>
+ /// AX attributes should use the Type URI format starting with <c>http://openid.net/schema/</c>.
+ /// </summary>
+ OpenIdNetSchema = 0x4,
+
+ /// <summary>
+ /// All known schemas.
+ /// </summary>
+ All = 0xff,
+
+ /// <summary>
+ /// The most common schemas.
+ /// </summary>
+ Common = AXSchemaOrg | SchemaOpenIdNet,
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
new file mode 100644
index 0000000..eee75e2
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/ExtensionsInteropHelper.cs
@@ -0,0 +1,364 @@
+//-----------------------------------------------------------------------
+// <copyright file="InteropHelper.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+ using DotNetOpenAuth.OpenId.Messages;
+
+ /// <summary>
+ /// A set of methods designed to assist in improving interop across different
+ /// OpenID implementations and their extensions.
+ /// </summary>
+ public static class ExtensionsInteropHelper {
+ /// <summary>
+ /// The gender decoder to translate AX genders to Sreg.
+ /// </summary>
+ private static GenderEncoder genderEncoder = new GenderEncoder();
+
+ /// <summary>
+ /// Adds an Attribute Exchange (AX) extension to the authentication request
+ /// that asks for the same attributes as the Simple Registration (sreg) extension
+ /// that is already applied.
+ /// </summary>
+ /// <param name="request">The authentication request.</param>
+ /// <param name="attributeFormats">The attribute formats to use in the AX request.</param>
+ /// <remarks>
+ /// <para>If discovery on the user-supplied identifier yields hints regarding which
+ /// extensions and attribute formats the Provider supports, this method MAY ignore the
+ /// <paramref name="attributeFormat"/> argument and accomodate the Provider to minimize
+ /// the size of the request.</para>
+ /// <para>If the request does not carry an sreg extension, the method logs a warning but
+ /// otherwise quietly returns doing nothing.</para>
+ /// </remarks>
+ public static void SpreadSregToAX(this RelyingParty.IAuthenticationRequest request, AXAttributeFormats attributeFormats) {
+ Contract.Requires(request != null);
+ ErrorUtilities.VerifyArgumentNotNull(request, "request");
+
+ var req = (RelyingParty.AuthenticationRequest)request;
+ var sreg = req.AppliedExtensions.OfType<ClaimsRequest>().SingleOrDefault();
+ if (sreg == null) {
+ Logger.OpenId.Warn("No Simple Registration (ClaimsRequest) extension present in the request to spread to AX.");
+ return;
+ }
+
+ if (req.Provider.IsExtensionSupported<ClaimsRequest>()) {
+ Logger.OpenId.Info("Skipping generation of AX request because the Identifier advertises the Provider supports the Sreg extension.");
+ return;
+ }
+
+ var ax = req.AppliedExtensions.OfType<FetchRequest>().SingleOrDefault();
+ if (ax == null) {
+ ax = new FetchRequest();
+ req.AddExtension(ax);
+ }
+
+ // Try to use just one AX Type URI format if we can figure out which type the OP accepts.
+ attributeFormats = FocusAttributeFormat(request, attributeFormats);
+
+ foreach (AXAttributeFormats format in ForEachFormat(attributeFormats)) {
+ FetchAttribute(ax, format, WellKnownAttributes.BirthDate.WholeBirthDate, sreg.BirthDate);
+ FetchAttribute(ax, format, WellKnownAttributes.Contact.HomeAddress.Country, sreg.Country);
+ FetchAttribute(ax, format, WellKnownAttributes.Contact.Email, sreg.Email);
+ FetchAttribute(ax, format, WellKnownAttributes.Name.FullName, sreg.FullName);
+ FetchAttribute(ax, format, WellKnownAttributes.Person.Gender, sreg.Gender);
+ FetchAttribute(ax, format, WellKnownAttributes.Preferences.Language, sreg.Language);
+ FetchAttribute(ax, format, WellKnownAttributes.Name.Alias, sreg.Nickname);
+ FetchAttribute(ax, format, WellKnownAttributes.Contact.HomeAddress.PostalCode, sreg.PostalCode);
+ FetchAttribute(ax, format, WellKnownAttributes.Preferences.TimeZone, sreg.TimeZone);
+ }
+ }
+
+ /// <summary>
+ /// Looks for Simple Registration and Attribute Exchange (all known formats)
+ /// response extensions and returns them as a Simple Registration extension.
+ /// </summary>
+ /// <param name="response">The authentication response.</param>
+ /// <param name="allowUnsigned">if set to <c>true</c> unsigned extensions will be included in the search.</param>
+ /// <returns>
+ /// The Simple Registration response if found,
+ /// 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>
+ public static ClaimsResponse UnifyExtensionsAsSreg(this RelyingParty.IAuthenticationResponse response, bool allowUnsigned) {
+ Contract.Requires(response != null);
+ ErrorUtilities.VerifyArgumentNotNull(response, "response");
+
+ var resp = (RelyingParty.IAuthenticationResponse)response;
+ var sreg = allowUnsigned ? resp.GetUntrustedExtension<ClaimsResponse>() : resp.GetExtension<ClaimsResponse>();
+ if (sreg != null) {
+ return sreg;
+ }
+
+ sreg = new ClaimsResponse();
+ var fetchResponse = allowUnsigned ? resp.GetUntrustedExtension<FetchResponse>() : resp.GetExtension<FetchResponse>();
+ if (fetchResponse != null) {
+ ((IOpenIdMessageExtension)sreg).IsSignedByRemoteParty = fetchResponse.IsSignedByProvider;
+ sreg.BirthDateRaw = fetchResponse.GetAttributeValue(WellKnownAttributes.BirthDate.WholeBirthDate, AXAttributeFormats.All);
+ sreg.Country = fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.Country);
+ sreg.PostalCode = fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.HomeAddress.PostalCode);
+ sreg.Email = fetchResponse.GetAttributeValue(WellKnownAttributes.Contact.Email);
+ sreg.FullName = fetchResponse.GetAttributeValue(WellKnownAttributes.Name.FullName);
+ sreg.Language = fetchResponse.GetAttributeValue(WellKnownAttributes.Preferences.Language);
+ sreg.Nickname = fetchResponse.GetAttributeValue(WellKnownAttributes.Name.Alias);
+ sreg.TimeZone = fetchResponse.GetAttributeValue(WellKnownAttributes.Preferences.TimeZone);
+ string gender = fetchResponse.GetAttributeValue(WellKnownAttributes.Person.Gender);
+ if (gender != null) {
+ sreg.Gender = (Gender)genderEncoder.Decode(gender);
+ }
+ }
+
+ return sreg;
+ }
+
+ /// <summary>
+ /// Looks for Simple Registration and Attribute Exchange (all known formats)
+ /// request extensions and returns them as a Simple Registration extension.
+ /// </summary>
+ /// <param name="request">The authentication request.</param>
+ /// <returns>
+ /// The Simple Registration request if found,
+ /// or a fabricated one based on the Attribute Exchange extension if found,
+ /// or <c>null</c> if no attribute extension request is found.</returns>
+ internal static ClaimsRequest UnifyExtensionsAsSreg(this Provider.IHostProcessedRequest request) {
+ Contract.Requires(request != null);
+ ErrorUtilities.VerifyArgumentNotNull(request, "request");
+
+ var req = (Provider.AuthenticationRequest)request;
+ var sreg = req.GetExtension<ClaimsRequest>();
+ if (sreg != null) {
+ return sreg;
+ }
+
+ var ax = req.GetExtension<FetchRequest>();
+ if (ax != null) {
+ sreg = new ClaimsRequest();
+ sreg.Synthesized = true;
+ sreg.BirthDate = GetDemandLevelFor(ax, WellKnownAttributes.BirthDate.WholeBirthDate);
+ sreg.Country = GetDemandLevelFor(ax, WellKnownAttributes.Contact.HomeAddress.Country);
+ sreg.Email = GetDemandLevelFor(ax, WellKnownAttributes.Contact.Email);
+ sreg.FullName = GetDemandLevelFor(ax, WellKnownAttributes.Name.FullName);
+ sreg.Gender = GetDemandLevelFor(ax, WellKnownAttributes.Person.Gender);
+ sreg.Language = GetDemandLevelFor(ax, WellKnownAttributes.Preferences.Language);
+ sreg.Nickname = GetDemandLevelFor(ax, WellKnownAttributes.Name.Alias);
+ sreg.PostalCode = GetDemandLevelFor(ax, WellKnownAttributes.Contact.HomeAddress.PostalCode);
+ sreg.TimeZone = GetDemandLevelFor(ax, WellKnownAttributes.Preferences.TimeZone);
+ }
+
+ return sreg;
+ }
+
+ /// <summary>
+ /// Converts the Simple Registration extension response to whatever format the original
+ /// attribute request extension came in.
+ /// </summary>
+ /// <param name="request">The authentication request with the response extensions already added.</param>
+ /// <remarks>
+ /// If the original attribute request came in as AX, the Simple Registration extension is converted
+ /// to an AX response and then the Simple Registration extension is removed from the response.
+ /// </remarks>
+ internal static void ConvertSregToMatchRequest(this Provider.IHostProcessedRequest request) {
+ var req = (Provider.HostProcessedRequest)request;
+ var response = (IProtocolMessageWithExtensions)req.Response;
+ var sregRequest = request.GetExtension<ClaimsRequest>();
+ if (sregRequest != null) {
+ if (sregRequest.Synthesized) {
+ var axRequest = request.GetExtension<FetchRequest>();
+ ErrorUtilities.VerifyInternal(axRequest != null, "How do we have a synthesized Sreg request without an AX request?");
+
+ var sregResponse = response.Extensions.OfType<ClaimsResponse>().SingleOrDefault();
+ if (sregResponse == null) {
+ // No Sreg response to copy from.
+ return;
+ }
+
+ // Remove the sreg response since the RP didn't ask for it.
+ response.Extensions.Remove(sregResponse);
+
+ AXAttributeFormats format = DetectAXFormat(axRequest.Attributes.Select(att => att.TypeUri));
+ if (format == AXAttributeFormats.None) {
+ // No recognized AX attributes were requested.
+ return;
+ }
+
+ var axResponse = response.Extensions.OfType<FetchResponse>().SingleOrDefault();
+ if (axResponse == null) {
+ axResponse = new FetchResponse();
+ response.Extensions.Add(axResponse);
+ }
+
+ AddAXAttributeValue(axResponse, WellKnownAttributes.BirthDate.WholeBirthDate, format, sregResponse.BirthDateRaw);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Contact.HomeAddress.Country, format, sregResponse.Country);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Contact.HomeAddress.PostalCode, format, sregResponse.PostalCode);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Contact.Email, format, sregResponse.Email);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Name.FullName, format, sregResponse.FullName);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Name.Alias, format, sregResponse.Nickname);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Preferences.TimeZone, format, sregResponse.TimeZone);
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Preferences.Language, format, sregResponse.Language);
+ if (sregResponse.Gender.HasValue) {
+ AddAXAttributeValue(axResponse, WellKnownAttributes.Person.Gender, format, genderEncoder.Encode(sregResponse.Gender));
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the attribute value if available.
+ /// </summary>
+ /// <param name="fetchResponse">The AX fetch response extension to look for the attribute value.</param>
+ /// <param name="typeUri">The type URI of the attribute, using the axschema.org format of <see cref="WellKnownAttributes"/>.</param>
+ /// <param name="formats">The AX type URI formats to search.</param>
+ /// <returns>
+ /// The first value of the attribute, if available.
+ /// </returns>
+ internal static string GetAttributeValue(this FetchResponse fetchResponse, string typeUri, AXAttributeFormats formats) {
+ return ForEachFormat(formats).Select(format => fetchResponse.GetAttributeValue(TransformAXFormat(typeUri, format))).FirstOrDefault(s => s != null);
+ }
+
+ /// <summary>
+ /// Adds the AX attribute value to the response if it is non-empty.
+ /// </summary>
+ /// <param name="ax">The AX Fetch response to add the attribute value to.</param>
+ /// <param name="typeUri">The attribute type URI in axschema.org format.</param>
+ /// <param name="format">The target format of the actual attribute to write out.</param>
+ /// <param name="value">The value of the attribute.</param>
+ private static void AddAXAttributeValue(FetchResponse ax, string typeUri, AXAttributeFormats format, string value) {
+ if (!string.IsNullOrEmpty(value)) {
+ string targetTypeUri = TransformAXFormat(typeUri, format);
+ if (ax.Attributes.Contains(targetTypeUri)) {
+ ax.Attributes.Add(targetTypeUri, value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the demand level for an AX attribute.
+ /// </summary>
+ /// <param name="ax">The AX fetch request to search for the attribute.</param>
+ /// <param name="typeUri">The type URI of the attribute in axschema.org format.</param>
+ /// <returns>The demand level for the attribute.</returns>
+ private static DemandLevel GetDemandLevelFor(FetchRequest ax, string typeUri) {
+ Contract.Requires(ax != null);
+ Contract.Requires(!String.IsNullOrEmpty(typeUri));
+
+ foreach (AXAttributeFormats format in ForEachFormat(AXAttributeFormats.All)) {
+ string typeUriInFormat = TransformAXFormat(typeUri, format);
+ if (ax.Attributes.Contains(typeUriInFormat)) {
+ return ax.Attributes[typeUriInFormat].IsRequired ? DemandLevel.Require : DemandLevel.Request;
+ }
+ }
+
+ return DemandLevel.NoRequest;
+ }
+
+ /// <summary>
+ /// Tries to find the exact format of AX attribute Type URI supported by the Provider.
+ /// </summary>
+ /// <param name="request">The authentication request.</param>
+ /// <param name="attributeFormat">The attribute formats the RP will try if this discovery fails.</param>
+ /// <returns>The AX format(s) to use based on the Provider's advertised AX support.</returns>
+ private static AXAttributeFormats FocusAttributeFormat(RelyingParty.IAuthenticationRequest request, AXAttributeFormats attributeFormat) {
+ Contract.Requires(request != null);
+ var provider = (RelyingParty.ServiceEndpoint)request.Provider;
+ AXAttributeFormats detected = DetectAXFormat(provider.ProviderDescription.Capabilities);
+ return detected != AXAttributeFormats.None ? detected : attributeFormat;
+ }
+
+ /// <summary>
+ /// Detects the AX attribute type URI format from a given sample.
+ /// </summary>
+ /// <param name="typeURIs">The type URIs to scan for recognized formats.</param>
+ /// <returns>The first AX type URI format recognized in the list.</returns>
+ private static AXAttributeFormats DetectAXFormat(IEnumerable<string> typeURIs) {
+ Contract.Requires(typeURIs != null);
+
+ if (typeURIs.Any(uri => uri.StartsWith("http://axschema.org/", StringComparison.Ordinal))) {
+ return AXAttributeFormats.AXSchemaOrg;
+ }
+
+ if (typeURIs.Any(uri => uri.StartsWith("http://schema.openid.net/", StringComparison.Ordinal))) {
+ return AXAttributeFormats.SchemaOpenIdNet;
+ }
+
+ if (typeURIs.Any(uri => uri.StartsWith("http://openid.net/schema/", StringComparison.Ordinal))) {
+ return AXAttributeFormats.OpenIdNetSchema;
+ }
+
+ return AXAttributeFormats.None;
+ }
+
+ /// <summary>
+ /// Transforms an AX attribute type URI from the axschema.org format into a given format.
+ /// </summary>
+ /// <param name="axSchemaOrgFormatTypeUri">The ax schema org format type URI.</param>
+ /// <param name="targetFormat">The target format. Only one flag should be set.</param>
+ /// <returns>The AX attribute type URI in the target format.</returns>
+ private static string TransformAXFormat(string axSchemaOrgFormatTypeUri, AXAttributeFormats targetFormat) {
+ Contract.Requires(!String.IsNullOrEmpty(axSchemaOrgFormatTypeUri));
+
+ switch (targetFormat) {
+ case AXAttributeFormats.AXSchemaOrg:
+ return axSchemaOrgFormatTypeUri;
+ case AXAttributeFormats.SchemaOpenIdNet:
+ return axSchemaOrgFormatTypeUri.Replace("axschema.org", "schema.openid.net");
+ case AXAttributeFormats.OpenIdNetSchema:
+ return axSchemaOrgFormatTypeUri.Replace("axschema.org", "openid.net/schema");
+ default:
+ throw new ArgumentOutOfRangeException("targetFormat");
+ }
+ }
+
+ /// <summary>
+ /// Splits the AX attribute format flags into individual values for processing.
+ /// </summary>
+ /// <param name="formats">The formats to split up into individual flags.</param>
+ /// <returns>A sequence of individual flags.</returns>
+ private static IEnumerable<AXAttributeFormats> ForEachFormat(AXAttributeFormats formats) {
+ if ((formats & AXAttributeFormats.AXSchemaOrg) != 0) {
+ yield return AXAttributeFormats.AXSchemaOrg;
+ }
+
+ if ((formats & AXAttributeFormats.OpenIdNetSchema) != 0) {
+ yield return AXAttributeFormats.OpenIdNetSchema;
+ }
+
+ if ((formats & AXAttributeFormats.SchemaOpenIdNet) != 0) {
+ yield return AXAttributeFormats.SchemaOpenIdNet;
+ }
+ }
+
+ /// <summary>
+ /// Adds an attribute fetch request if it is not already present in the AX request.
+ /// </summary>
+ /// <param name="ax">The AX request to add the attribute request to.</param>
+ /// <param name="format">The format of the attribute's Type URI to use.</param>
+ /// <param name="axSchemaOrgFormatAttribute">The attribute in axschema.org format.</param>
+ /// <param name="demandLevel">The demand level.</param>
+ private static void FetchAttribute(FetchRequest ax, AXAttributeFormats format, string axSchemaOrgFormatAttribute, DemandLevel demandLevel) {
+ Contract.Requires(ax != null);
+ Contract.Requires(!String.IsNullOrEmpty(axSchemaOrgFormatAttribute));
+
+ string typeUri = TransformAXFormat(axSchemaOrgFormatAttribute, format);
+ if (!ax.Attributes.Contains(typeUri)) {
+ switch (demandLevel) {
+ case DemandLevel.Request:
+ ax.Attributes.AddOptional(typeUri);
+ break;
+ case DemandLevel.Require:
+ ax.Attributes.AddRequired(typeUri);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
index 800a2ff..df88ed0 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
@@ -116,6 +116,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.SimpleRegistration {
public DemandLevel TimeZone { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether this <see cref="ClaimsRequest"/> instance
+ /// is synthesized from an AX request at the Provider.
+ /// </summary>
+ internal bool Synthesized { get; set; }
+
+ /// <summary>
/// Gets or sets the value of the sreg.required parameter.
/// </summary>
/// <value>A comma-delimited list of sreg fields.</value>
diff --git a/src/DotNetOpenAuth/OpenId/InteropHelper.cs b/src/DotNetOpenAuth/OpenId/InteropHelper.cs
deleted file mode 100644
index e92bc5e..0000000
--- a/src/DotNetOpenAuth/OpenId/InteropHelper.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="InteropHelper.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.OpenId {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics.Contracts;
- using System.Linq;
- using System.Text;
- using DotNetOpenAuth.Messaging;
- using DotNetOpenAuth.OpenId;
- using DotNetOpenAuth.OpenId.Extensions.AttributeExchange;
- using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
-
- public static class InteropHelper {
- /// <summary>
- /// The various Type URI formats an AX attribute may use by various remote parties.
- /// </summary>
- [Flags]
- public enum AXAttributeFormats {
- /// <summary>
- /// AX attributes should use the Type URI format starting with <c>http://axschema.org/</c>.
- /// </summary>
- AXSchemaOrg,
-
- /// <summary>
- /// AX attributes should use the Type URI format starting with <c>http://schema.openid.net/</c>.
- /// </summary>
- SchemaOpenIdNet,
-
- /// <summary>
- /// AX attributes should use the Type URI format starting with <c>http://openid.net/schema/</c>.
- /// </summary>
- OpenIdNetSchema,
- }
-
- /// <summary>
- /// Adds an Attribute Exchange (AX) extension to the authentication request
- /// that asks for the same attributes as the Simple Registration (sreg) extension
- /// that is already applied.
- /// </summary>
- /// <param name="request">The authentication request.</param>
- /// <param name="attributeFormat">The attribute formats to include in the request.</param>
- /// <remarks>
- /// <para>If discovery on the user-supplied identifier yields hints regarding which
- /// extensions and attribute formats the Provider supports, this method MAY ignore the
- /// <paramref name="attributeFormat"/> argument and accomodate the Provider to minimize
- /// the size of the request.</para>
- /// <para>If the request does not carry an sreg extension, the method logs a warning but
- /// otherwise quietly returns doing nothing.</para>
- /// </remarks>
- public static void SpreadSregToAX(this RelyingParty.IAuthenticationRequest request, AXAttributeFormats attributeFormats) {
- Contract.Requires(request != null);
- ErrorUtilities.VerifyArgumentNotNull(request, "request");
-
- var req = (RelyingParty.AuthenticationRequest)request;
- var sreg = req.AppliedExtensions.OfType<ClaimsRequest>().SingleOrDefault();
- if (sreg == null) {
- Logger.OpenId.Warn("No Simple Registration (ClaimsRequest) extension present in the request to spread to AX.");
- return;
- }
-
- var ax = req.AppliedExtensions.OfType<FetchRequest>().SingleOrDefault();
- if (ax == null) {
- ax = new FetchRequest();
- req.AddExtension(ax);
- }
-
- if (req.Provider.IsExtensionSupported<ClaimsRequest>()) {
- Logger.OpenId.Info("Skipping generation of AX request because the Identifier advertises the Provider supports the Sreg extension.");
- return;
- }
-
- // Try to use just one AX Type URI format if we can figure out which type the OP accepts.
- attributeFormats = FocusAttributeFormat(request, attributeFormats);
-
- foreach (AXAttributeFormats format in ForEachFormat(attributeFormats)) {
- FetchAttribute(ax, format, WellKnownAttributes.BirthDate.WholeBirthDate, sreg.BirthDate);
- FetchAttribute(ax, format, WellKnownAttributes.Contact.HomeAddress.Country, sreg.Country);
- FetchAttribute(ax, format, WellKnownAttributes.Contact.Email, sreg.Email);
- FetchAttribute(ax, format, WellKnownAttributes.Name.FullName, sreg.FullName);
- FetchAttribute(ax, format, WellKnownAttributes.Person.Gender, sreg.Gender);
- FetchAttribute(ax, format, WellKnownAttributes.Preferences.Language, sreg.Language);
- FetchAttribute(ax, format, WellKnownAttributes.Name.Alias, sreg.Nickname);
- FetchAttribute(ax, format, WellKnownAttributes.Contact.HomeAddress.PostalCode, sreg.PostalCode);
- FetchAttribute(ax, format, WellKnownAttributes.Preferences.TimeZone, sreg.TimeZone);
- }
- }
-
- public static void UnifyExtensions(this RelyingParty.IAuthenticationResponse response) {
- Contract.Requires(response != null);
- ErrorUtilities.VerifyArgumentNotNull(response, "response");
-
- var resp = (RelyingParty.IAuthenticationResponse)response;
- throw new NotImplementedException();
- }
-
- public static void UnifyExtensions(this Provider.IAuthenticationRequest request) {
- Contract.Requires(request != null);
- ErrorUtilities.VerifyArgumentNotNull(request, "request");
-
- var req = (Provider.AuthenticationRequest)request;
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Tries to find the exact format of AX attribute Type URI supported by the Provider.
- /// </summary>
- /// <param name="request">The authentication request.</param>
- /// <param name="attributeFormat">The attribute formats the RP will try if this discovery fails.</param>
- /// <returns>The AX format(s) to use based on the Provider's advertised AX support.</returns>
- private static AXAttributeFormats FocusAttributeFormat(RelyingParty.IAuthenticationRequest request, AXAttributeFormats attributeFormat) {
- Contract.Requires(request != null);
-
- var provider = (RelyingParty.ServiceEndpoint)request.Provider;
-
- if (provider.ProviderDescription.Capabilities.Any(uri => uri.StartsWith("http://axschema.org/", StringComparison.Ordinal))) {
- return AXAttributeFormats.AXSchemaOrg;
- }
-
- if (provider.ProviderDescription.Capabilities.Any(uri => uri.StartsWith("http://schema.openid.net/", StringComparison.Ordinal))) {
- return AXAttributeFormats.SchemaOpenIdNet;
- }
-
- if (provider.ProviderDescription.Capabilities.Any(uri => uri.StartsWith("http://openid.net/schema/", StringComparison.Ordinal))) {
- return AXAttributeFormats.OpenIdNetSchema;
- }
-
- return attributeFormat;
- }
-
- /// <summary>
- /// Transforms an AX attribute type URI from the axschema.org format into a given format.
- /// </summary>
- /// <param name="axSchemaOrgFormatTypeUri">The ax schema org format type URI.</param>
- /// <param name="targetFormat">The target format. Only one flag should be set.</param>
- /// <returns>The AX attribute type URI in the target format.</returns>
- private static string TransformAXFormat(string axSchemaOrgFormatTypeUri, AXAttributeFormats targetFormat) {
- Contract.Requires(!String.IsNullOrEmpty(axSchemaOrgFormatTypeUri));
-
- switch (targetFormat) {
- case AXAttributeFormats.AXSchemaOrg:
- return axSchemaOrgFormatTypeUri;
- case AXAttributeFormats.SchemaOpenIdNet:
- return axSchemaOrgFormatTypeUri.Replace("axschema.org", "schema.openid.net");
- case AXAttributeFormats.OpenIdNetSchema:
- return axSchemaOrgFormatTypeUri.Replace("axschema.org", "openid.net/schema");
- default:
- throw new ArgumentOutOfRangeException("targetFormat");
- }
- }
-
- /// <summary>
- /// Splits the AX attribute format flags into individual values for processing.
- /// </summary>
- /// <param name="formats">The formats to split up into individual flags.</param>
- /// <returns>A sequence of individual flags.</returns>
- private static IEnumerable<AXAttributeFormats> ForEachFormat(AXAttributeFormats formats) {
- if ((formats & AXAttributeFormats.AXSchemaOrg) != 0) {
- yield return AXAttributeFormats.AXSchemaOrg;
- }
-
- if ((formats & AXAttributeFormats.OpenIdNetSchema) != 0) {
- yield return AXAttributeFormats.OpenIdNetSchema;
- }
-
- if ((formats & AXAttributeFormats.SchemaOpenIdNet) != 0) {
- yield return AXAttributeFormats.SchemaOpenIdNet;
- }
- }
-
- /// <summary>
- /// Adds an attribute fetch request if it is not already present in the AX request.
- /// </summary>
- /// <param name="ax">The ax.</param>
- /// <param name="format">The format.</param>
- /// <param name="axSchemaOrgFormatAttribute">The ax schema org format attribute.</param>
- /// <param name="demandLevel">The demand level.</param>
- private static void FetchAttribute(FetchRequest ax, AXAttributeFormats format, string axSchemaOrgFormatAttribute, DemandLevel demandLevel) {
- Contract.Requires(ax != null);
- Contract.Requires(!String.IsNullOrEmpty(axSchemaOrgFormatAttribute));
-
- string typeUri = TransformAXFormat(axSchemaOrgFormatAttribute, format);
- if (!ax.Attributes.Contains(typeUri)) {
- switch (demandLevel) {
- case DemandLevel.Request:
- ax.Attributes.AddOptional(typeUri);
- break;
- case DemandLevel.Require:
- ax.Attributes.AddRequired(typeUri);
- break;
- default:
- break;
- }
- }
- }
- }
-}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/Request.cs b/src/DotNetOpenAuth/OpenId/Provider/Request.cs
index 4c2ee98..43697b2 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/Request.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/Request.cs
@@ -132,7 +132,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// Gets the original request message.
/// </summary>
/// <value>This may be null in the case of an unrecognizable message.</value>
- protected IDirectedProtocolMessage RequestMessage {
+ protected internal IDirectedProtocolMessage RequestMessage {
get { return this.request; }
}
diff --git a/src/DotNetOpenAuth/Settings.StyleCop b/src/DotNetOpenAuth/Settings.StyleCop
index 017d610..a4295eb 100644
--- a/src/DotNetOpenAuth/Settings.StyleCop
+++ b/src/DotNetOpenAuth/Settings.StyleCop
@@ -30,5 +30,12 @@
</Rules>
<AnalyzerSettings />
</Analyzer>
+ <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.NamingRules">
+ <AnalyzerSettings>
+ <CollectionProperty Name="Hungarian">
+ <Value>ax</Value>
+ </CollectionProperty>
+ </AnalyzerSettings>
+ </Analyzer>
</Analyzers>
</StyleCopSettings> \ No newline at end of file