summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth')
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj2
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.resx3
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs26
-rw-r--r--src/DotNetOpenAuth/Messaging/ProtocolException.cs9
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs17
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/DirectResponseBase.cs12
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IErrorMessage.cs32
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectErrorResponse.cs21
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/IErrorReporting.cs43
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs122
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/Request.cs19
15 files changed, 303 insertions, 40 deletions
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 7686ff6..0feb900 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -219,6 +219,7 @@
<Compile Include="OpenId\Messages\CheckAuthenticationRequest.cs" />
<Compile Include="OpenId\Messages\CheckAuthenticationResponse.cs" />
<Compile Include="OpenId\Messages\CheckIdRequest.cs" />
+ <Compile Include="OpenId\Messages\IErrorMessage.cs" />
<Compile Include="OpenId\Messages\IndirectResponseBase.cs" />
<Compile Include="OpenId\Messages\IndirectSignedResponse.cs" />
<Compile Include="OpenId\Messages\IOpenIdMessageExtension.cs" />
@@ -234,6 +235,7 @@
<Compile Include="OpenId\Provider\IAuthenticationRequest.cs" />
<Compile Include="OpenId\Provider\IdentityEndpoint.cs" />
<Compile Include="OpenId\Provider\IdentityEndpointNormalizationEventArgs.cs" />
+ <Compile Include="OpenId\Provider\IErrorReporting.cs" />
<Compile Include="OpenId\Provider\IProviderApplicationStore.cs" />
<Compile Include="OpenId\Provider\IRequest.cs" />
<Compile Include="OpenId\Provider\ProviderEndpoint.cs" />
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
index d9fddcc..b1931dc 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
@@ -151,6 +151,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to This exception must be instantiated with a recipient that will receive the error message, or a direct request message instance that this exception will respond to..
+ /// </summary>
+ internal static string ExceptionUndeliverable {
+ get {
+ return ResourceManager.GetString("ExceptionUndeliverable", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Expected {0} message but received no recognizable message..
/// </summary>
internal static string ExpectedMessageNotReceived {
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
index aa5419f..a17988a 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
@@ -279,4 +279,7 @@
<data name="WebRequestFailed" xml:space="preserve">
<value>Web request to '{0}' failed.</value>
</data>
+ <data name="ExceptionUndeliverable" xml:space="preserve">
+ <value>This exception must be instantiated with a recipient that will receive the error message, or a direct request message instance that this exception will respond to.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 1861c41..0292107 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -13,6 +13,7 @@ namespace DotNetOpenAuth.Messaging {
using System.IO;
using System.Linq;
using System.Net;
+ using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Web;
@@ -136,6 +137,31 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Assemblies a message comprised of the message on a given exception and all inner exceptions.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ /// <returns>The assembled message.</returns>
+ internal static string GetAllMessages(this Exception exception) {
+ // The input being null is probably bad, but since this method is called
+ // from a catch block, we don't really want to throw a new exception and
+ // hide the details of this one.
+ if (exception == null) {
+ Logger.Error("MessagingUtilities.GetAllMessages called with null input.");
+ }
+
+ StringBuilder message = new StringBuilder();
+ while (exception != null) {
+ message.Append(exception.Message);
+ exception = exception.InnerException;
+ if (exception != null) {
+ message.Append(" ");
+ }
+ }
+
+ return message.ToString();
+ }
+
+ /// <summary>
/// Gets a cryptographically strong random sequence of values.
/// </summary>
/// <param name="length">The length of the sequence to generate.</param>
diff --git a/src/DotNetOpenAuth/Messaging/ProtocolException.cs b/src/DotNetOpenAuth/Messaging/ProtocolException.cs
index e9f4ab7..daf13d7 100644
--- a/src/DotNetOpenAuth/Messaging/ProtocolException.cs
+++ b/src/DotNetOpenAuth/Messaging/ProtocolException.cs
@@ -40,13 +40,10 @@ namespace DotNetOpenAuth.Messaging {
/// such that it can be sent as a protocol message response to a remote caller.
/// </summary>
/// <param name="message">The human-readable exception message.</param>
- /// <param name="faultedMessage">The message that was the cause of the exception. May not be null.</param>
- internal ProtocolException(string message, IProtocolMessage faultedMessage)
+ /// <param name="faultedMessage">The message that was the cause of the exception. Must not be null.</param>
+ protected internal ProtocolException(string message, IProtocolMessage faultedMessage)
: base(message) {
- if (faultedMessage == null) {
- throw new ArgumentNullException("faultedMessage");
- }
-
+ ErrorUtilities.VerifyArgumentNotNull(faultedMessage, "faultedMessage");
this.FaultedMessage = faultedMessage;
}
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs
index 1b2e46d..e0c3a1b 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdMessageFactory.cs
@@ -70,6 +70,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
} else if (string.Equals(mode, protocol.Args.Mode.check_authentication)) {
message = new CheckAuthenticationRequest(protocol.Version, recipient.Location);
+ } else if (string.Equals(mode, protocol.Args.Mode.error)) {
+ message = new IndirectErrorResponse(protocol.Version, recipient.Location);
} else {
ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessagePartValue, protocol.openid.mode, mode);
}
@@ -106,11 +108,17 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
protocol = Protocol.V20;
}
+ // Handle error messages generally.
+ if (fields.ContainsKey(protocol.openidnp.error)) {
+ message = new DirectErrorResponse(request);
+ }
+
var associateRequest = request as AssociateRequest;
if (associateRequest != null) {
if (protocol.Version.Major >= 2 && fields.ContainsKey(protocol.openidnp.error_code)) {
+ // This is a special recognized error case that we create a special message for.
message = new AssociateUnsuccessfulResponse(associateRequest);
- } else {
+ } else if (message == null) {
var associateDiffieHellmanRequest = request as AssociateDiffieHellmanRequest;
var associateUnencryptedRequest = request as AssociateUnencryptedRequest;
@@ -125,7 +133,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
}
var checkAuthenticationRequest = request as CheckAuthenticationRequest;
- if (checkAuthenticationRequest != null) {
+ if (checkAuthenticationRequest != null && message == null) {
message = new CheckAuthenticationResponse(checkAuthenticationRequest);
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
index ed272d3..9731e43 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/DirectErrorResponse.cs
@@ -5,6 +5,7 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Messages {
+ using System;
using DotNetOpenAuth.Messaging;
/// <summary>
@@ -14,7 +15,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// This message must be sent with an HTTP status code of 400.
/// This class satisfies OpenID 2.0 section 5.1.2.2.
/// </remarks>
- internal class DirectErrorResponse : DirectResponseBase, IHttpDirectResponse {
+ internal class DirectErrorResponse : DirectResponseBase, IErrorMessage, IHttpDirectResponse {
/// <summary>
/// Initializes a new instance of the <see cref="DirectErrorResponse"/> class.
/// </summary>
@@ -23,6 +24,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
: base(originatingRequest) {
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DirectErrorResponse"/> class.
+ /// </summary>
+ /// <param name="version">The OpenID version this message should comply with.</param>
+ internal DirectErrorResponse(Version version)
+ : base(version) {
+ }
+
#region IHttpDirectResponse Members
/// <summary>
@@ -39,19 +48,19 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// Gets or sets a human-readable message indicating why the request failed.
/// </summary>
[MessagePart("error", IsRequired = true, AllowEmpty = true)]
- internal string ErrorMessage { get; set; }
+ public string ErrorMessage { get; set; }
/// <summary>
/// Gets or sets the contact address for the administrator of the server.
/// </summary>
/// <value>The contact address may take any form, as it is intended to be displayed to a person. </value>
[MessagePart("contact", IsRequired = false, AllowEmpty = true)]
- internal string Contact { get; set; }
+ public string Contact { get; set; }
/// <summary>
/// Gets or sets a reference token, such as a support ticket number or a URL to a news blog, etc.
/// </summary>
[MessagePart("reference", IsRequired = false, AllowEmpty = true)]
- internal string Reference { get; set; }
+ public string Reference { get; set; }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/DirectResponseBase.cs b/src/DotNetOpenAuth/OpenId/Messages/DirectResponseBase.cs
index 141669c..bf357d3 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/DirectResponseBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/DirectResponseBase.cs
@@ -58,6 +58,15 @@ namespace DotNetOpenAuth.OpenId.Messages {
this.Version = originatingRequest.Version;
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DirectResponseBase"/> class.
+ /// </summary>
+ /// <param name="version">The OpenID version to comply with.</param>
+ protected DirectResponseBase(Version version) {
+ ErrorUtilities.VerifyArgumentNotNull(version, "version");
+ this.Version = version;
+ }
+
#region IProtocolMessage Properties
/// <summary>
@@ -96,6 +105,9 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <summary>
/// Gets the originating request message that caused this response to be formed.
/// </summary>
+ /// <remarks>
+ /// This property may be null if the request message was undecipherable.
+ /// </remarks>
IDirectedProtocolMessage IDirectResponseProtocolMessage.OriginatingRequest {
get { return this.originatingRequest; }
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IErrorMessage.cs b/src/DotNetOpenAuth/OpenId/Messages/IErrorMessage.cs
new file mode 100644
index 0000000..549b327
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Messages/IErrorMessage.cs
@@ -0,0 +1,32 @@
+//-----------------------------------------------------------------------
+// <copyright file="IErrorMessage.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Messages {
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// Members found on error response messages sent from a Provider
+ /// to a Relying Party in response to direct and indirect message
+ /// requests that result in an error.
+ /// </summary>
+ internal interface IErrorMessage : IProtocolMessage {
+ /// <summary>
+ /// Gets or sets a human-readable message indicating why the request failed.
+ /// </summary>
+ string ErrorMessage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the contact address for the administrator of the server.
+ /// </summary>
+ /// <value>The contact address may take any form, as it is intended to be displayed to a person. </value>
+ string Contact { get; set; }
+
+ /// <summary>
+ /// Gets or sets a reference token, such as a support ticket number or a URL to a news blog, etc.
+ /// </summary>
+ string Reference { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectErrorResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectErrorResponse.cs
index ffc73f8..eb006db 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectErrorResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectErrorResponse.cs
@@ -17,32 +17,41 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// <remarks>
/// This class satisfies OpenID 2.0 section 5.2.3.
/// </remarks>
- internal class IndirectErrorResponse : IndirectResponseBase {
+ internal class IndirectErrorResponse : IndirectResponseBase, IErrorMessage {
/// <summary>
/// Initializes a new instance of the <see cref="IndirectErrorResponse"/> class.
/// </summary>
/// <param name="request">The request that resulted in this error on the Provider.</param>
- internal IndirectErrorResponse(CheckIdRequest request)
- : base(request, "error") {
+ internal IndirectErrorResponse(SignedResponseRequest request)
+ : base(request, Protocol.Lookup(GetVersion(request)).openidnp.error) {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="IndirectErrorResponse"/> class.
+ /// </summary>
+ /// <param name="version">The OpenID version this message should comply with.</param>
+ /// <param name="recipient">The recipient of this message.</param>
+ internal IndirectErrorResponse(Version version, Uri recipient)
+ : base(version, recipient, Protocol.Lookup(version).openidnp.error) {
}
/// <summary>
/// Gets or sets a human-readable message indicating why the request failed.
/// </summary>
[MessagePart("openid.error", IsRequired = true, AllowEmpty = true)]
- internal string ErrorMessage { get; set; }
+ public string ErrorMessage { get; set; }
/// <summary>
/// Gets or sets the contact address for the administrator of the server.
/// </summary>
/// <value>The contact address may take any form, as it is intended to be displayed to a person. </value>
[MessagePart("openid.contact", IsRequired = false, AllowEmpty = true)]
- internal string Contact { get; set; }
+ public string Contact { get; set; }
/// <summary>
/// Gets or sets a reference token, such as a support ticket number or a URL to a news blog, etc.
/// </summary>
[MessagePart("openid.reference", IsRequired = false, AllowEmpty = true)]
- internal string Reference { get; set; }
+ public string Reference { get; set; }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
index 3c5bd6a..322ec60 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
@@ -54,7 +54,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// This method can be used by a constructor to throw an <see cref="ArgumentNullException"/>
/// instead of a <see cref="NullReferenceException"/>.
/// </remarks>
- protected static Version GetVersion(IProtocolMessage message) {
+ internal static Version GetVersion(IProtocolMessage message) {
ErrorUtilities.VerifyArgumentNotNull(message, "message");
return message.Version;
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs
index 53998dc..e2f3992 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AutoResponsiveRequest.cs
@@ -10,6 +10,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.Messages;
/// <summary>
/// Handles messages coming into an OpenID Provider for which the entire
@@ -36,6 +37,19 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
/// <summary>
+ /// Initializes a new instance of the <see cref="AutoResponsiveRequest"/> class
+ /// for a response to an unrecognizable request.
+ /// </summary>
+ /// <param name="provider">The provider that received the request message.</param>
+ /// <param name="response">The response that is ready for transmittal.</param>
+ internal AutoResponsiveRequest(OpenIdProvider provider, IProtocolMessage response)
+ : base(provider, IndirectResponseBase.GetVersion(response)) {
+ ErrorUtilities.VerifyArgumentNotNull(response, "response");
+
+ this.response = response;
+ }
+
+ /// <summary>
/// Gets a value indicating whether the response is ready to be sent to the user agent.
/// </summary>
/// <remarks>
diff --git a/src/DotNetOpenAuth/OpenId/Provider/IErrorReporting.cs b/src/DotNetOpenAuth/OpenId/Provider/IErrorReporting.cs
new file mode 100644
index 0000000..7221e94
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Provider/IErrorReporting.cs
@@ -0,0 +1,43 @@
+//-----------------------------------------------------------------------
+// <copyright file="IErrorReporting.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Provider {
+ using System;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// An interface that a Provider site may implement in order to better
+ /// control error reporting.
+ /// </summary>
+ public interface IErrorReporting {
+ /// <summary>
+ /// Gets the message that can be sent in an error response
+ /// with information on who the remote party can contact
+ /// for help resolving the error.
+ /// </summary>
+ /// <value>
+ /// The contact address may take any form, as it is intended to be displayed to a person.
+ /// </value>
+ string Contact { get; }
+
+ /// <summary>
+ /// Logs the details of an exception for later reference in diagnosing the problem.
+ /// </summary>
+ /// <param name="error">The exception that was generated from the error.</param>
+ /// <returns>
+ /// A unique identifier for this particular error that the remote party can
+ /// reference when contacting <see cref="Contact"/> for help with this error.
+ /// May be null.
+ /// </returns>
+ /// <remarks>
+ /// The implementation of this method should never throw an unhandled exception
+ /// as that would preclude the ability to send the error response to the remote
+ /// party. When this method is not implemented, it should return null rather
+ /// than throwing <see cref="NotImplementedException"/>.
+ /// </remarks>
+ string LogError(ProtocolException error);
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index 2bea543..4ed0fb1 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -104,6 +104,12 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
/// <summary>
+ /// Gets or sets the mechanism a host site can use to receive
+ /// notifications of errors when communicating with remote parties.
+ /// </summary>
+ public IErrorReporting ErrorReporting { get; set; }
+
+ /// <summary>
/// Gets the association store.
/// </summary>
internal IAssociationStore<AssociationRelyingPartyType> AssociationStore { get; private set; }
@@ -145,31 +151,49 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// be authentication requests where the Provider site has to make decisions based
/// on its own user database and policies.
/// </remarks>
- /// <exception cref="ProtocolException">Thrown if the incoming message is recognized but deviates from the protocol specification irrecoverably.</exception>
+ /// <exception cref="ProtocolException">Thrown if the incoming message is recognized
+ /// but deviates from the protocol specification irrecoverably.</exception>
public IRequest GetRequest(HttpRequestInfo httpRequestInfo) {
ErrorUtilities.VerifyArgumentNotNull(httpRequestInfo, "httpRequestInfo");
+ IDirectedProtocolMessage incomingMessage = null;
- IDirectedProtocolMessage incomingMessage = this.Channel.ReadFromRequest(httpRequestInfo);
- if (incomingMessage == null) {
- return null;
- }
+ try {
+ incomingMessage = this.Channel.ReadFromRequest(httpRequestInfo);
+ if (incomingMessage == null) {
+ // If the incoming request does not resemble an OpenID message at all,
+ // it's probably a user who just navigated to this URL, and we should
+ // just return null so the host can display a message to the user.
+ if (httpRequestInfo.HttpMethod == "GET" && !httpRequestInfo.Url.QueryStringContainPrefixedParameters(Protocol.Default.openid.Prefix)) {
+ return null;
+ }
- var checkIdMessage = incomingMessage as CheckIdRequest;
- if (checkIdMessage != null) {
- return new AuthenticationRequest(this, checkIdMessage);
- }
+ ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessageReceivedOfMany);
+ }
- var checkAuthMessage = incomingMessage as CheckAuthenticationRequest;
- if (checkAuthMessage != null) {
- return new AutoResponsiveRequest(this, incomingMessage, new CheckAuthenticationResponse(checkAuthMessage, this));
- }
+ var checkIdMessage = incomingMessage as CheckIdRequest;
+ if (checkIdMessage != null) {
+ return new AuthenticationRequest(this, checkIdMessage);
+ }
- var associateMessage = incomingMessage as AssociateRequest;
- if (associateMessage != null) {
- return new AutoResponsiveRequest(this, incomingMessage, associateMessage.CreateResponse(this.AssociationStore, this.SecuritySettings));
- }
+ var checkAuthMessage = incomingMessage as CheckAuthenticationRequest;
+ if (checkAuthMessage != null) {
+ return new AutoResponsiveRequest(this, incomingMessage, new CheckAuthenticationResponse(checkAuthMessage, this));
+ }
- throw ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessageReceivedOfMany);
+ var associateMessage = incomingMessage as AssociateRequest;
+ if (associateMessage != null) {
+ return new AutoResponsiveRequest(this, incomingMessage, associateMessage.CreateResponse(this.AssociationStore, this.SecuritySettings));
+ }
+
+ throw ErrorUtilities.ThrowProtocol(MessagingStrings.UnexpectedMessageReceivedOfMany);
+ } catch (ProtocolException ex) {
+ IRequest errorResponse = this.GetErrorResponse(ex, httpRequestInfo, incomingMessage);
+ if (errorResponse == null) {
+ throw;
+ }
+
+ return errorResponse;
+ }
}
/// <summary>
@@ -258,5 +282,67 @@ namespace DotNetOpenAuth.OpenId.Provider {
}
#endregion
+
+ /// <summary>
+ /// Prepares the return value for the GetRequest method in the event of an exception.
+ /// </summary>
+ /// <param name="ex">The exception that forms the basis of the error response. Must not be null.</param>
+ /// <param name="httpRequestInfo">The incoming HTTP request. Must not be null.</param>
+ /// <param name="incomingMessage">The incoming message. May be null in the case that it was malformed.</param>
+ /// <returns>
+ /// Either the <see cref="IRequest"/> to return to the host site or null to indicate no response could be reasonably created and that the caller should rethrow the exception.
+ /// </returns>
+ private IRequest GetErrorResponse(ProtocolException ex, HttpRequestInfo httpRequestInfo, IDirectedProtocolMessage incomingMessage) {
+ ErrorUtilities.VerifyArgumentNotNull(ex, "ex");
+ ErrorUtilities.VerifyArgumentNotNull(httpRequestInfo, "httpRequestInfo");
+
+ Logger.Error("An exception was generated while processing an incoming OpenID request.", ex);
+ IErrorMessage errorMessage;
+
+ // We must create the appropriate error message type (direct vs. indirect)
+ // based on what we see in the request.
+ if (httpRequestInfo.QueryString[Protocol.Default.openid.return_to] != null) {
+ // An indirect request message from the RP
+ // We need to return an indirect response error message so the RP can consume it.
+ // Consistent with OpenID 2.0 section 5.2.3.
+ var indirectRequest = incomingMessage as SignedResponseRequest;
+ if (indirectRequest != null) {
+ errorMessage = new IndirectErrorResponse(indirectRequest);
+ } else {
+ errorMessage = new IndirectErrorResponse(Protocol.Default.Version, new Uri(httpRequestInfo.QueryString[Protocol.Default.openid.return_to]));
+ }
+ } else if (httpRequestInfo.HttpMethod == "POST") {
+ // A direct request message from the RP
+ // We need to return a direct response error message so the RP can consume it.
+ // Consistent with OpenID 2.0 section 5.1.2.2.
+ if (incomingMessage != null) {
+ errorMessage = new DirectErrorResponse(incomingMessage);
+ } else {
+ errorMessage = new DirectErrorResponse(Protocol.Default.Version);
+ }
+ } else {
+ // This may be an indirect request from an RP that was so badly
+ // formed that we cannot even return an error to the RP.
+ // The best we can do is display an error to the user.
+ // Returning null cues the caller to "throw;"
+ return null;
+ }
+
+ errorMessage.ErrorMessage = ex.GetAllMessages();
+
+ // Allow host to log this error and issue a ticket #.
+ // We tear off the field to a local var for thread safety.
+ IErrorReporting hostErrorHandler = this.ErrorReporting;
+ if (hostErrorHandler != null) {
+ errorMessage.Contact = hostErrorHandler.Contact;
+ errorMessage.Reference = hostErrorHandler.LogError(ex);
+ }
+
+ if (incomingMessage != null) {
+ return new AutoResponsiveRequest(this, incomingMessage, errorMessage);
+ } else {
+ return new AutoResponsiveRequest(this, errorMessage);
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Provider/Request.cs b/src/DotNetOpenAuth/OpenId/Provider/Request.cs
index 6546e38..e1ccce1 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/Request.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/Request.cs
@@ -55,9 +55,23 @@ namespace DotNetOpenAuth.OpenId.Provider {
this.provider = provider;
this.request = request;
+ this.Protocol = Protocol.Lookup(this.request.Version);
this.extensibleMessage = request as IProtocolMessageWithExtensions;
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Request"/> class.
+ /// </summary>
+ /// <param name="provider">The provider.</param>
+ /// <param name="version">The version.</param>
+ protected Request(OpenIdProvider provider, Version version) {
+ ErrorUtilities.VerifyArgumentNotNull(provider, "provider");
+ ErrorUtilities.VerifyArgumentNotNull(version, "version");
+
+ this.provider = provider;
+ this.Protocol = Protocol.Lookup(version);
+ }
+
#region IRequest Members
/// <summary>
@@ -110,6 +124,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// Gets the original request message.
/// </summary>
+ /// <value>This may be null in the case of an unrecognizable message.</value>
protected IDirectedProtocolMessage RequestMessage {
get { return this.request; }
}
@@ -122,9 +137,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// Gets the protocol version used in the request..
/// </summary>
- protected Protocol Protocol {
- get { return Protocol.Lookup(this.RequestMessage.Version); }
- }
+ protected Protocol Protocol { get; private set; }
#region IRequest Methods