summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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