diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-06-19 17:08:30 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-06-20 08:43:08 -0700 |
commit | 0d3741fe631df59b30a7808a29294167f45cad39 (patch) | |
tree | a1a8922b9ac6efa7abd6c2a5c4bce364e3879d83 /src | |
parent | 0b5fd389ccc28193e0d014b123e23545a1bc5e2d (diff) | |
download | DotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.zip DotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.tar.gz DotNetOpenAuth-0d3741fe631df59b30a7808a29294167f45cad39.tar.bz2 |
Implemented InteropHelper.SpreadSregToAX.
Diffstat (limited to 'src')
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; } } |