summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-03-11 20:22:40 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-03-11 20:22:40 -0700
commit0b7f0bf7f67d1d80c8a8d4ed9ee3ddae50b89e70 (patch)
tree0498754c0d9959b05d98d274e65f6ef266fcff94 /src
parent6b055f20dd61a845c4486066601a7f820905ff64 (diff)
downloadDotNetOpenAuth-0b7f0bf7f67d1d80c8a8d4ed9ee3ddae50b89e70.zip
DotNetOpenAuth-0b7f0bf7f67d1d80c8a8d4ed9ee3ddae50b89e70.tar.gz
DotNetOpenAuth-0b7f0bf7f67d1d80c8a8d4ed9ee3ddae50b89e70.tar.bz2
Added support for classic ASP RPs to use the sreg extension.
Diffstat (limited to 'src')
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs7
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj3
-rw-r--r--src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs25
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/Interop/AuthenticationResponseShim.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Interop/ClaimsResponseShim.cs109
-rw-r--r--src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs64
-rw-r--r--src/DotNetOpenAuth/Yadis/DiscoveryResult.cs4
-rw-r--r--src/DotNetOpenAuth/Yadis/Yadis.cs5
9 files changed, 209 insertions, 27 deletions
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
index 3444192..7fd3476 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -246,7 +246,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
HttpMethods = scheme,
};
- DirectWebResponse rawResponse = null;
+ CachedDirectWebResponse rawResponse = null;
this.webRequestHandler.Callback = (req) => {
Assert.IsNotNull(req);
HttpRequestInfo reqInfo = ConvertToRequestInfo(req, this.webRequestHandler.RequestEntityStream);
@@ -264,9 +264,8 @@ namespace DotNetOpenAuth.Test.ChannelElements {
{ "Location", request.Location.AbsoluteUri },
{ "Timestamp", XmlConvert.ToString(request.Timestamp, XmlDateTimeSerializationMode.Utc) },
};
- rawResponse = new CachedDirectWebResponse {
- Body = MessagingUtilities.CreateQueryString(responseFields),
- };
+ rawResponse = new CachedDirectWebResponse();
+ rawResponse.SetResponse(MessagingUtilities.CreateQueryString(responseFields));
return rawResponse;
};
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 0750cc0..e3e6c0c 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -296,6 +296,7 @@
<Compile Include="OpenId\Identifier.cs" />
<Compile Include="OpenId\IdentifierContract.cs" />
<Compile Include="OpenId\Interop\AuthenticationResponseShim.cs" />
+ <Compile Include="OpenId\Interop\ClaimsResponseShim.cs" />
<Compile Include="OpenId\Interop\OpenIdRelyingPartyShim.cs" />
<Compile Include="OpenId\Messages\CheckAuthenticationRequest.cs" />
<Compile Include="OpenId\Messages\CheckAuthenticationResponse.cs" />
@@ -460,4 +461,4 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
index c1d2d76..4cf9639 100644
--- a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
@@ -15,7 +15,7 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Cached details on the response from a direct web request to a remote party.
/// </summary>
- [DebuggerDisplay("{Status} {ContentType.MediaType}: {Body.Substring(4,50)}")]
+ [DebuggerDisplay("{Status} {ContentType.MediaType}, length: {ResponseStream.Length}")]
internal class CachedDirectWebResponse : DirectWebResponse {
/// <summary>
/// A seekable, repeatable response stream.
@@ -60,14 +60,6 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Gets or sets the body of the response as a string.
- /// </summary>
- public string Body {
- get { return this.ResponseStream != null ? this.GetResponseReader().ReadToEnd() : null; }
- set { this.SetResponse(value); }
- }
-
- /// <summary>
/// Gets a value indicating whether the cached response stream was
/// truncated to a maximum allowable length.
/// </summary>
@@ -103,6 +95,21 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Gets the body of the response as a string.
+ /// </summary>
+ /// <returns>The entire body of the response.</returns>
+ internal string GetResponseString() {
+ if (this.ResponseStream != null) {
+ StreamReader reader = this.GetResponseReader();
+ string value = this.GetResponseReader().ReadToEnd();
+ this.ResponseStream.Seek(0, SeekOrigin.Begin);
+ return value;
+ } else {
+ return null;
+ }
+ }
+
+ /// <summary>
/// Gets an offline snapshot version of this instance.
/// </summary>
/// <param name="maximumBytesToCache">The maximum bytes from the response stream to cache.</param>
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
index 827bca2..c8100cf 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/SimpleRegistration/ClaimsRequest.cs
@@ -244,8 +244,7 @@ TimeZone = '{8}'";
/// the OpenId specification for field names, omitting the 'openid.sreg' prefix.
/// </param>
/// <param name="requestLevel">The none/request/require state of the listed fields.</param>
- [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by messaging framework via reflection.")]
- private void SetProfileRequestFromList(ICollection<string> fieldNames, DemandLevel requestLevel) {
+ internal void SetProfileRequestFromList(IEnumerable<string> fieldNames, DemandLevel requestLevel) {
foreach (string field in fieldNames) {
switch (field) {
case Constants.nickname:
@@ -276,7 +275,7 @@ TimeZone = '{8}'";
this.TimeZone = requestLevel;
break;
default:
- Logger.WarnFormat("OpenIdProfileRequest.SetProfileRequestFromList: Unrecognized field name '{0}'.", field);
+ Logger.WarnFormat("ClaimsRequest.SetProfileRequestFromList: Unrecognized field name '{0}'.", field);
break;
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Interop/AuthenticationResponseShim.cs b/src/DotNetOpenAuth/OpenId/Interop/AuthenticationResponseShim.cs
index 79dbdb6..a5926d9 100644
--- a/src/DotNetOpenAuth/OpenId/Interop/AuthenticationResponseShim.cs
+++ b/src/DotNetOpenAuth/OpenId/Interop/AuthenticationResponseShim.cs
@@ -7,9 +7,11 @@
namespace DotNetOpenAuth.OpenId.Interop {
using System;
using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using System.Web;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
@@ -17,7 +19,7 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// </summary>
[SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "It's only creatable on the inside. It must be ComVisible for ASP to see it.")]
[ComVisible(true), Obsolete("This class acts as a COM Server and should not be called directly from .NET code.")]
- public class AuthenticationResponseShim {
+ public sealed class AuthenticationResponseShim {
/// <summary>
/// The response read in by the Relying Party.
/// </summary>
@@ -28,9 +30,14 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// </summary>
/// <param name="response">The response.</param>
internal AuthenticationResponseShim(IAuthenticationResponse response) {
+ Contract.Requires(response != null);
ErrorUtilities.VerifyArgumentNotNull(response, "response");
this.response = response;
+ var claimsResponse = this.response.GetExtension<ClaimsResponse>();
+ if (claimsResponse != null) {
+ this.ClaimsResponse = new ClaimsResponseShim(claimsResponse);
+ }
}
/// <summary>
@@ -93,6 +100,11 @@ namespace DotNetOpenAuth.OpenId.Interop {
}
/// <summary>
+ /// Gets the Simple Registration response.
+ /// </summary>
+ public ClaimsResponseShim ClaimsResponse { get; private set; }
+
+ /// <summary>
/// Gets details regarding a failed authentication attempt, if available.
/// </summary>
public string ExceptionMessage {
diff --git a/src/DotNetOpenAuth/OpenId/Interop/ClaimsResponseShim.cs b/src/DotNetOpenAuth/OpenId/Interop/ClaimsResponseShim.cs
new file mode 100644
index 0000000..ef5e79d
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Interop/ClaimsResponseShim.cs
@@ -0,0 +1,109 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClaimsResponseShim.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Interop {
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
+
+ /// <summary>
+ /// A struct storing Simple Registration field values describing an
+ /// authenticating user.
+ /// </summary>
+ [SuppressMessage("Microsoft.Interoperability", "CA1409:ComVisibleTypesShouldBeCreatable", Justification = "It's only creatable on the inside. It must be ComVisible for ASP to see it.")]
+ [ComVisible(true), Obsolete("This class acts as a COM Server and should not be called directly from .NET code.")]
+ [ContractVerification(true)]
+ public sealed class ClaimsResponseShim {
+ /// <summary>
+ /// The Simple Registration claims response message that this shim wraps.
+ /// </summary>
+ private readonly ClaimsResponse response;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ClaimsResponseShim"/> class.
+ /// </summary>
+ /// <param name="response">The Simple Registration response to wrap.</param>
+ internal ClaimsResponseShim(ClaimsResponse response)
+ {
+ Contract.Requires(response != null);
+ ErrorUtilities.VerifyArgumentNotNull(response, "response");
+
+ this.response = response;
+ }
+
+ /// <summary>
+ /// Gets the nickname the user goes by.
+ /// </summary>
+ public string Nickname {
+ get { return this.response.Nickname; }
+ }
+
+ /// <summary>
+ /// Gets the user's email address.
+ /// </summary>
+ public string Email {
+ get { return this.response.Email; }
+ }
+
+ /// <summary>
+ /// Gets the full name of a user as a single string.
+ /// </summary>
+ public string FullName {
+ get { return this.response.FullName; }
+ }
+
+ /// <summary>
+ /// Gets the raw birth date string given by the extension.
+ /// </summary>
+ /// <value>A string in the format yyyy-MM-dd.</value>
+ public string BirthDate {
+ get { return this.response.BirthDateRaw; }
+ }
+
+ /// <summary>
+ /// Gets the gender of the user.
+ /// </summary>
+ public string Gender {
+ get {
+ if (this.response.Gender.HasValue) {
+ return this.response.Gender.Value == Extensions.SimpleRegistration.Gender.Male ? Constants.Genders.Male : Constants.Genders.Female;
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the zip code / postal code of the user.
+ /// </summary>
+ public string PostalCode {
+ get { return this.response.PostalCode; }
+ }
+
+ /// <summary>
+ /// Gets the country of the user.
+ /// </summary>
+ public string Country {
+ get { return this.response.Country; }
+ }
+
+ /// <summary>
+ /// Gets the primary/preferred language of the user.
+ /// </summary>
+ public string Language {
+ get { return this.response.Language; }
+ }
+
+ /// <summary>
+ /// Gets the user's timezone.
+ /// </summary>
+ public string TimeZone {
+ get { return this.response.TimeZone; }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
index 2a76ea5..0f05318 100644
--- a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
+++ b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs
@@ -12,13 +12,14 @@ namespace DotNetOpenAuth.OpenId.Interop {
using System.Text;
using System.Web;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration;
using DotNetOpenAuth.OpenId.RelyingParty;
/// <summary>
/// The COM interface describing the DotNetOpenId functionality available to
/// COM client relying parties.
/// </summary>
- [Guid("00462F34-21BE-456c-B986-B6DDE4DC5CA8")]
+ [Guid("56BD3DB0-EE0D-4191-ADFC-1F3705CD2636")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IOpenIdRelyingParty {
/// <summary>
@@ -45,6 +46,26 @@ namespace DotNetOpenAuth.OpenId.Interop {
string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl);
/// <summary>
+ /// Creates an authentication request to verify that a user controls
+ /// some given Identifier.
+ /// </summary>
+ /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param>
+ /// <param name="realm">The shorest URL that describes this relying party web site's address.
+ /// For example, if your login page is found at https://www.example.com/login.aspx,
+ /// your realm would typically be https://www.example.com/.</param>
+ /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication
+ /// responses from the OpenID Provider.</param>
+ /// <param name="optionalSreg">A comma-delimited list of simple registration fields to request as optional.</param>
+ /// <param name="requiredSreg">A comma-delimited list of simple registration fields to request as required.</param>
+ /// <returns>
+ /// An authentication request object that describes the HTTP response to
+ /// send to the user agent to initiate the authentication.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Accepted acronym")]
+ string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg);
+
+ /// <summary>
/// Gets the result of a user agent's visit to his OpenId provider in an
/// authentication attempt. Null if no response is available.
/// </summary>
@@ -60,11 +81,11 @@ namespace DotNetOpenAuth.OpenId.Interop {
/// Implementation of <see cref="IOpenIdRelyingParty"/>, providing a subset of the
/// functionality available to .NET clients.
/// </summary>
- [Guid("4D6FB236-1D66-4311-B761-972C12BB85E8")]
+ [Guid("8F97A798-B4C5-4da5-9727-EE7DD96A8CD9")]
[ProgId("DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty")]
[ComVisible(true), Obsolete("This class acts as a COM Server and should not be called directly from .NET code.", true)]
[ClassInterface(ClassInterfaceType.None)]
- public class OpenIdRelyingPartyShim : IOpenIdRelyingParty {
+ public sealed class OpenIdRelyingPartyShim : IOpenIdRelyingParty {
/// <summary>
/// Creates an authentication request to verify that a user controls
/// some given Identifier.
@@ -89,8 +110,41 @@ namespace DotNetOpenAuth.OpenId.Interop {
[SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
public string CreateRequest(string userSuppliedIdentifier, string realm, string returnToUrl) {
OpenIdRelyingParty rp = new OpenIdRelyingParty(null);
- UserAgentResponse response = rp.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl)).RedirectingResponse;
- return response.DirectUriRequest.AbsoluteUri;
+ var request = rp.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
+ return request.RedirectingResponse.DirectUriRequest.AbsoluteUri;
+ }
+
+ /// <summary>
+ /// Creates an authentication request to verify that a user controls
+ /// some given Identifier.
+ /// </summary>
+ /// <param name="userSuppliedIdentifier">The Identifier supplied by the user. This may be a URL, an XRI or i-name.</param>
+ /// <param name="realm">The shorest URL that describes this relying party web site's address.
+ /// For example, if your login page is found at https://www.example.com/login.aspx,
+ /// your realm would typically be https://www.example.com/.</param>
+ /// <param name="returnToUrl">The URL of the login page, or the page prepared to receive authentication
+ /// responses from the OpenID Provider.</param>
+ /// <param name="optionalSreg">A comma-delimited list of simple registration fields to request as optional.</param>
+ /// <param name="requiredSreg">A comma-delimited list of simple registration fields to request as required.</param>
+ /// <returns>
+ /// An authentication request object that describes the HTTP response to
+ /// send to the user agent to initiate the authentication.
+ /// </returns>
+ /// <exception cref="ProtocolException">Thrown if no OpenID endpoint could be found.</exception>
+ [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "COM requires primitive types")]
+ public string CreateRequestWithSimpleRegistration(string userSuppliedIdentifier, string realm, string returnToUrl, string optionalSreg, string requiredSreg) {
+ OpenIdRelyingParty rp = new OpenIdRelyingParty(null);
+ var request = rp.CreateRequest(userSuppliedIdentifier, realm, new Uri(returnToUrl));
+
+ ClaimsRequest sreg = new ClaimsRequest();
+ if (!string.IsNullOrEmpty(optionalSreg)) {
+ sreg.SetProfileRequestFromList(optionalSreg.Split(','), DemandLevel.Request);
+ }
+ if (!string.IsNullOrEmpty(requiredSreg)) {
+ sreg.SetProfileRequestFromList(requiredSreg.Split(','), DemandLevel.Require);
+ }
+ request.AddExtension(sreg);
+ return request.RedirectingResponse.DirectUriRequest.AbsoluteUri;
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs b/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
index 9b77215..90495e2 100644
--- a/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
+++ b/src/DotNetOpenAuth/Yadis/DiscoveryResult.cs
@@ -27,11 +27,11 @@ namespace DotNetOpenAuth.Yadis {
this.NormalizedUri = initialResponse.FinalUri;
if (finalResponse == null) {
this.ContentType = initialResponse.ContentType;
- this.ResponseText = initialResponse.Body;
+ this.ResponseText = initialResponse.GetResponseString();
this.IsXrds = ContentType.MediaType == ContentTypes.Xrds;
} else {
this.ContentType = finalResponse.ContentType;
- this.ResponseText = finalResponse.Body;
+ this.ResponseText = finalResponse.GetResponseString();
this.IsXrds = true;
if (initialResponse != finalResponse) {
this.YadisLocation = finalResponse.RequestUri;
diff --git a/src/DotNetOpenAuth/Yadis/Yadis.cs b/src/DotNetOpenAuth/Yadis/Yadis.cs
index 6253aa0..b7d1482 100644
--- a/src/DotNetOpenAuth/Yadis/Yadis.cs
+++ b/src/DotNetOpenAuth/Yadis/Yadis.cs
@@ -77,7 +77,7 @@ namespace DotNetOpenAuth.Yadis {
}
}
if (url == null && response.ContentType.MediaType == ContentTypes.Html) {
- url = FindYadisDocumentLocationInHtmlMetaTags(response.Body);
+ url = FindYadisDocumentLocationInHtmlMetaTags(response.GetResponseString());
if (url != null) {
Logger.DebugFormat("{0} found in HTML Http-Equiv tag. Preparing to pull XRDS from {1}", HeaderName, url);
}
@@ -158,7 +158,8 @@ namespace DotNetOpenAuth.Yadis {
if (response.ContentType.MediaType == ContentTypes.Xml) {
// This COULD be an XRDS document with an imprecise content-type.
- XmlReader reader = XmlReader.Create(new StringReader(response.Body));
+ response.ResponseStream.Seek(0, SeekOrigin.Begin);
+ XmlReader reader = XmlReader.Create(response.ResponseStream);
while (reader.Read() && reader.NodeType != XmlNodeType.Element) {
// intentionally blank
}