summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-06-19 17:08:30 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-06-20 08:43:08 -0700
commit0d3741fe631df59b30a7808a29294167f45cad39 (patch)
treea1a8922b9ac6efa7abd6c2a5c4bce364e3879d83 /src
parent0b5fd389ccc28193e0d014b123e23545a1bc5e2d (diff)
downloadDotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.zip
DotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.tar.gz
DotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.tar.bz2
Implemented InteropHelper.SpreadSregToAX.
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj1
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs24
-rw-r--r--src/DotNetOpenAuth/OpenId/InteropHelper.cs175
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs2
4 files changed, 199 insertions, 3 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 64b53f7..fa768a8 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -196,6 +196,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\Messages\AssociateDiffieHellmanRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateRequestTests.cs" />
<Compile Include="OpenId\Messages\AssociateUnsuccessfulResponseTests.cs" />
diff --git a/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs b/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs
new file mode 100644
index 0000000..cf34c72
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OpenId/InteropHelperTests.cs
@@ -0,0 +1,24 @@
+//-----------------------------------------------------------------------
+// <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/OpenId/InteropHelper.cs b/src/DotNetOpenAuth/OpenId/InteropHelper.cs
index 7fb69cb..e92bc5e 100644
--- a/src/DotNetOpenAuth/OpenId/InteropHelper.cs
+++ b/src/DotNetOpenAuth/OpenId/InteropHelper.cs
@@ -7,24 +7,195 @@
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 {
- public static void SpreadExtensions(this RelyingParty.IAuthenticationRequest request) {
+ /// <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;
- throw new NotImplementedException();
+ 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/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index 19db0fa..cc924e9 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -153,7 +153,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// OpenId discovery documents found at the <see cref="ClaimedIdentifier"/>
/// location.
/// </summary>
- IProviderEndpoint IAuthenticationRequest.Provider {
+ public IProviderEndpoint Provider {
get { return this.endpoint; }
}