diff --git a/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationAuthenticationContextExtensions.cs b/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationAuthenticationContextExtensions.cs
new file mode 100644
index 0000000..1001d11
--- /dev/null
+++ b/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationAuthenticationContextExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Owin.Security.Providers.OpenID.Extensions
+{
+ ///
+ /// Contains an extension method that makes reading the SREG fields easier.
+ ///
+ public static class OpenIDSimpleRegistrationAuthenticationContextExtensions
+ {
+ public static OpenIDSimpleRegistrationResult GetSimpleRegistrationResult(this OpenIDAuthenticatedContext context)
+ {
+ if (!context.ProtocolExtensionData.ContainsKey(typeof (OpenIDSimpleRegistrationExtension)))
+ {
+ return new OpenIDSimpleRegistrationResult();
+ }
+ else
+ {
+ return context.ProtocolExtensionData[typeof (OpenIDSimpleRegistrationExtension)] as OpenIDSimpleRegistrationResult;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationExtension.cs b/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationExtension.cs
new file mode 100644
index 0000000..5593ea7
--- /dev/null
+++ b/Owin.Security.Providers/OpenID/Extensions/OpenIDSimpleRegistrationExtension.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+
+namespace Owin.Security.Providers.OpenID.Extensions
+{
+ ///
+ /// Implements the OpenID Simple Registration Extension http://openid.net/specs/openid-simple-registration-extension-1_0.html
+ ///
+ public class OpenIDSimpleRegistrationExtension : IOpenIDProtocolExtension
+ {
+
+ private static readonly Dictionary claimsMap = new Dictionary()
+ {
+ { OpenIDSimpleRegistrationField.NickName, "nickname" },
+ { OpenIDSimpleRegistrationField.FullName, "fullname" },
+ { OpenIDSimpleRegistrationField.Email, "email" },
+ { OpenIDSimpleRegistrationField.DayOfBirth, "dob" },
+ { OpenIDSimpleRegistrationField.Gender, "gender" },
+ { OpenIDSimpleRegistrationField.PostCode, "postcode" },
+ { OpenIDSimpleRegistrationField.Country, "country" },
+ { OpenIDSimpleRegistrationField.Language, "language" },
+ { OpenIDSimpleRegistrationField.Timezone, "timezone" }
+ };
+
+ private const string sregNamespace = "http://openid.net/extensions/sreg/1.1";
+
+
+ ///
+ /// Gets or sets a list of comma-separated SREG fields that are required.
+ ///
+ public HashSet RequiredFields { get; private set; }
+
+ ///
+ /// Gets or sets a list of comma-separated SREG fields that are optional.
+ ///
+ public HashSet OptionalFields { get; private set; }
+
+ ///
+ /// Gets or sets the SREG policy URL.
+ ///
+ public string PolicyUrl { get; set; }
+
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OpenIDSimpleRegistrationExtension()
+ {
+ RequiredFields = new HashSet() { OpenIDSimpleRegistrationField.Email, OpenIDSimpleRegistrationField.FullName };
+ OptionalFields = new HashSet();
+ PolicyUrl = string.Empty;
+ }
+
+
+ ///
+ /// Appends the SREG required attributes to the request URL constructed on challenge.
+ ///
+ public Task OnChallengeAsync(Microsoft.Owin.Security.AuthenticationResponseChallenge challenge, OpenIDAuthorizationEndpointInfo endpoint)
+ {
+ endpoint.Url += "&openid.ns.sreg=" + Uri.EscapeDataString(sregNamespace);
+
+ var requiredClaims = string.Join(",", RequiredFields.Select(f => claimsMap[f]));
+ endpoint.Url += "&openid.sreg.required=" + Uri.EscapeDataString(requiredClaims);
+
+ if (OptionalFields.Any())
+ {
+ var optionalClaims = string.Join(",", OptionalFields.Select(f => claimsMap[f]));
+ endpoint.Url += "&openid.sreg.optional=" + Uri.EscapeDataString(optionalClaims);
+ }
+
+ if (!string.IsNullOrEmpty(PolicyUrl))
+ {
+ endpoint.Url += "&openid.sreg.policy_url=" + Uri.EscapeDataString(PolicyUrl);
+ }
+
+ return Task.FromResult(0);
+ }
+
+ ///
+ /// Validates the authentication response message.
+ ///
+ public Task OnValidateMessageAsync(Infrastructure.Message message)
+ {
+ // no additional checks needed
+ return Task.FromResult(true);
+ }
+
+ ///
+ /// Extracts SREG attributes and returns the results.
+ ///
+ public Task