summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-12-31 10:45:24 -0700
committerAndrew <andrewarnott@gmail.com>2009-01-03 19:24:47 -0800
commit3c3232d6eccf9804fe1e0ce5c751b35ab752df40 (patch)
tree3abaa7eee21cc2c48369ec6c86d7c668725f475e
parent49aaed61a5c029c0fc98fcd5ab252902601bad5b (diff)
downloadDotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.zip
DotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.tar.gz
DotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.tar.bz2
StyleCop work
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs161
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs99
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs29
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs152
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs46
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs111
-rw-r--r--src/DotNetOpenAuth/Settings.StyleCop10
10 files changed, 584 insertions, 49 deletions
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index aa80f96..49b99b9 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -60,6 +60,7 @@ namespace DotNetOpenAuth.Messaging {
}
HttpRequest request = HttpContext.Current.Request;
+
// This request URL may have been rewritten by the host site.
// For openid protocol purposes, we really need to look at
// the original query parameters before any rewriting took place.
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
index 56dc38e..166b90a 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
@@ -322,6 +322,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
return value;
}
+ /// <summary>
+ /// Gets the names of the callback parameters added to the original authentication request.
+ /// </summary>
+ /// <returns>A sequence of the callback parameter names.</returns>
+ /// <remarks>
+ /// Callback parameters are only available if they are complete and untampered with
+ /// since the original request message (as proven by a signature).
+ /// </remarks>
internal IEnumerable<string> GetReturnToParameterNames() {
return this.ReturnToParameters.Keys;
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index e2e959c..0eab4c7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -14,12 +14,41 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
+ /// <summary>
+ /// Facilitates customization and creation and an authentication request
+ /// that a Relying Party is preparing to send.
+ /// </summary>
internal class AuthenticationRequest : IAuthenticationRequest {
- internal OpenIdRelyingParty RelyingParty;
- internal AssociationPreference associationPreference = AssociationPreference.IfPossible;
+ /// <summary>
+ /// The name of the internal callback parameter to use to store the user-supplied identifier.
+ /// </summary>
internal const string UserSuppliedIdentifierParameterName = "dnoi.userSuppliedIdentifier";
+
+ /// <summary>
+ /// The relying party that created this request object.
+ /// </summary>
+ private readonly OpenIdRelyingParty RelyingParty;
+
+ /// <summary>
+ /// The endpoint that describes the particular OpenID Identifier and Provider that
+ /// will be used to create the authentication request.
+ /// </summary>
private readonly ServiceEndpoint endpoint;
+
+ /// <summary>
+ /// The protocol version used at the Provider.
+ /// </summary>
private readonly Protocol protocol;
+
+ /// <summary>
+ /// How an association may or should be created or used in the formulation of the
+ /// authentication request.
+ /// </summary>
+ private AssociationPreference associationPreference = AssociationPreference.IfPossible;
+
+ /// <summary>
+ /// The extensions that have been added to this authentication request.
+ /// </summary>
private List<IOpenIdMessageExtension> extensions = new List<IOpenIdMessageExtension>();
/// <summary>
@@ -28,6 +57,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
private Dictionary<string, string> returnToArgs = new Dictionary<string, string>();
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthenticationRequest"/> class.
+ /// </summary>
+ /// <param name="endpoint">The endpoint that describes the OpenID Identifier and Provider that will complete the authentication.</param>
+ /// <param name="realm">The realm, or root URL, of the host web site.</param>
+ /// <param name="returnToUrl">The base return_to URL that the Provider should return the user to to complete authentication. This should not include callback parameters as these should be added using the <see cref="AddCallbackArguments(string, string)"/> method.</param>
+ /// <param name="relyingParty">The relying party that created this instance.</param>
private AuthenticationRequest(ServiceEndpoint endpoint, Realm realm, Uri returnToUrl, OpenIdRelyingParty relyingParty) {
ErrorUtilities.VerifyArgumentNotNull(endpoint, "endpoint");
ErrorUtilities.VerifyArgumentNotNull(realm, "realm");
@@ -45,32 +81,93 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region IAuthenticationRequest Members
+ /// <summary>
+ /// Gets or sets the mode the Provider should use during authentication.
+ /// </summary>
+ /// <value></value>
public AuthenticationRequestMode Mode { get; set; }
+ /// <summary>
+ /// Gets the HTTP response the relying party should send to the user agent
+ /// to redirect it to the OpenID Provider to start the OpenID authentication process.
+ /// </summary>
+ /// <value></value>
public UserAgentResponse RedirectingResponse {
get { return this.RelyingParty.Channel.Send(this.CreateRequestMessage()); }
}
+ /// <summary>
+ /// Gets the URL that the user agent will return to after authentication
+ /// completes or fails at the Provider.
+ /// </summary>
+ /// <value></value>
public Uri ReturnToUrl { get; private set; }
+ /// <summary>
+ /// Gets the URL that identifies this consumer web application that
+ /// the Provider will display to the end user.
+ /// </summary>
public Realm Realm { get; private set; }
+ /// <summary>
+ /// Gets the Claimed Identifier that the User Supplied Identifier
+ /// resolved to. Null if the user provided an OP Identifier
+ /// (directed identity).
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Null is returned if the user is using the directed identity feature
+ /// of OpenID 2.0 to make it nearly impossible for a relying party site
+ /// to improperly store the reserved OpenID URL used for directed identity
+ /// as a user's own Identifier.
+ /// However, to test for the Directed Identity feature, please test the
+ /// <see cref="IsDirectedIdentity"/> property rather than testing this
+ /// property for a null value.
+ /// </remarks>
public Identifier ClaimedIdentifier {
get { return this.IsDirectedIdentity ? null : this.endpoint.ClaimedIdentifier; }
}
+ /// <summary>
+ /// Gets a value indicating whether the authenticating user has chosen to let the Provider
+ /// determine and send the ClaimedIdentifier after authentication.
+ /// </summary>
+ /// <value></value>
public bool IsDirectedIdentity {
get { return this.endpoint.ClaimedIdentifier == this.endpoint.Protocol.ClaimedIdentifierForOPIdentifier; }
}
+ /// <summary>
+ /// Gets information about the OpenId Provider, as advertised by the
+ /// OpenId discovery documents found at the <see cref="ClaimedIdentifier"/>
+ /// location.
+ /// </summary>
+ /// <value></value>
IProviderEndpoint IAuthenticationRequest.Provider {
get { return this.endpoint; }
}
+ /// <summary>
+ /// Gets the detected version of OpenID implemented by the Provider.
+ /// </summary>
+ /// <value></value>
public Version ProviderVersion {
get { return this.endpoint.Protocol.Version; }
}
+ /// <summary>
+ /// Makes a dictionary of key/value pairs available when the authentication is completed.
+ /// </summary>
+ /// <param name="arguments">The arguments to add to the request's return_to URI.</param>
+ /// <remarks>
+ /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// security-sensitive data should be stored using this method.</para>
+ /// <para>The values stored here can be retrieved using
+ /// <see cref="IAuthenticationResponse.GetCallbackArguments"/>.</para>
+ /// <para>Since the data set here is sent in the querystring of the request and some
+ /// servers place limits on the size of a request URL, this data should be kept relatively
+ /// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
+ /// </remarks>
public void AddCallbackArguments(IDictionary<string, string> arguments) {
ErrorUtilities.VerifyArgumentNotNull(arguments, "arguments");
@@ -79,15 +176,40 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
+ /// <summary>
+ /// Makes a key/value pair available when the authentication is completed.
+ /// </summary>
+ /// <param name="key">The parameter name.</param>
+ /// <param name="value">The value of the argument.</param>
+ /// <remarks>
+ /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// security-sensitive data should be stored using this method.</para>
+ /// <para>The value stored here can be retrieved using
+ /// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
+ /// <para>Since the data set here is sent in the querystring of the request and some
+ /// servers place limits on the size of a request URL, this data should be kept relatively
+ /// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
+ /// </remarks>
public void AddCallbackArguments(string key, string value) {
this.returnToArgs.Add(key, value);
}
+ /// <summary>
+ /// Adds an OpenID extension to the request directed at the OpenID provider.
+ /// </summary>
+ /// <param name="extension">The initialized extension to add to the request.</param>
public void AddExtension(IOpenIdMessageExtension extension) {
ErrorUtilities.VerifyArgumentNotNull(extension, "extension");
this.extensions.Add(extension);
}
+ /// <summary>
+ /// Redirects the user agent to the provider for authentication.
+ /// Execution of the current page terminates after this call.
+ /// </summary>
+ /// <remarks>
+ /// This method requires an ASP.NET HttpContext.
+ /// </remarks>
public void RedirectToProvider() {
this.RedirectingResponse.Send();
}
@@ -98,6 +220,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Performs identifier discovery, creates associations and generates authentication requests
/// on-demand for as long as new ones can be generated based on the results of Identifier discovery.
/// </summary>
+ /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
+ /// <param name="relyingParty">The relying party.</param>
+ /// <param name="realm">The realm.</param>
+ /// <param name="returnToUrl">The return_to base URL.</param>
+ /// <param name="createNewAssociationsAsNeeded">if set to <c>true</c>, associations that do not exist between this Relying Party and the asserting Providers are created before the authentication request is created.</param>
+ /// <returns>A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier.</returns>
internal static IEnumerable<AuthenticationRequest> Create(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, bool createNewAssociationsAsNeeded) {
// We have a long data validation and preparation process
ErrorUtilities.VerifyArgumentNotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
@@ -134,9 +262,21 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Performs request generation for the <see cref="Create"/> method.
- /// All data validation and cleansing steps must have ALREADY taken place.
+ /// Performs deferred request generation for the <see cref="Create"/> method.
/// </summary>
+ /// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
+ /// <param name="relyingParty">The relying party.</param>
+ /// <param name="realm">The realm.</param>
+ /// <param name="returnToUrl">The return_to base URL.</param>
+ /// <param name="serviceEndpoints">The discovered service endpoints on the Claimed Identifier.</param>
+ /// <param name="createNewAssociationsAsNeeded">if set to <c>true</c>, associations that do not exist between this Relying Party and the asserting Providers are created before the authentication request is created.</param>
+ /// <returns>
+ /// A sequence of authentication requests, any of which constitutes a valid identity assertion on the Claimed Identifier.
+ /// </returns>
+ /// <remarks>
+ /// All data validation and cleansing steps must have ALREADY taken place
+ /// before calling this method.
+ /// </remarks>
private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<ServiceEndpoint> serviceEndpoints, bool createNewAssociationsAsNeeded) {
Logger.InfoFormat("Performing discovery on user-supplied identifier: {0}", userSuppliedIdentifier);
IEnumerable<ServiceEndpoint> endpoints = FilterAndSortEndpoints(serviceEndpoints, relyingParty);
@@ -160,6 +300,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
association = createNewAssociationsAsNeeded ? relyingParty.GetOrCreateAssociation(endpoint.ProviderDescription) : relyingParty.GetExistingAssociation(endpoint.ProviderDescription);
if (association == null && createNewAssociationsAsNeeded) {
Logger.WarnFormat("Failed to create association with {0}. Skipping to next endpoint.", endpoint.ProviderEndpoint);
+
// No association could be created. Add it to the list of failed association
// endpoints and skip to the next available endpoint.
failedAssociationEndpoints.Add(endpoint);
@@ -193,6 +334,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Returns a filtered and sorted list of the available OP endpoints for a discovered Identifier.
/// </summary>
+ /// <param name="endpoints">The endpoints.</param>
+ /// <param name="relyingParty">The relying party.</param>
+ /// <returns>A filtered and sorted list of endpoints; may be empty if the input was empty or the filter removed all endpoints.</returns>
private static List<ServiceEndpoint> FilterAndSortEndpoints(IEnumerable<ServiceEndpoint> endpoints, OpenIdRelyingParty relyingParty) {
ErrorUtilities.VerifyArgumentNotNull(endpoints, "endpoints");
ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty");
@@ -234,6 +378,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return endpointList;
}
+ /// <summary>
+ /// Creates the authentication request message to send to the Provider,
+ /// based on the properties in this instance.
+ /// </summary>
+ /// <returns>The message to send to the Provider.</returns>
private CheckIdRequest CreateRequestMessage() {
Association association = this.GetAssociation();
@@ -252,6 +401,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return request;
}
+ /// <summary>
+ /// Gets the association to use for this authentication request.
+ /// </summary>
+ /// <returns>The association to use; <c>null</c> to use 'dumb mode'.</returns>
private Association GetAssociation() {
Association association = null;
switch (this.associationPreference) {
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
index 92fd532..d69e7e7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/FailedAuthenticationResponse.cs
@@ -15,6 +15,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.RelyingParty;
+ /// <summary>
+ /// Wraps a failed authentication response in an <see cref="IAuthenticationResponse"/> instance
+ /// for public consumption by the host web site.
+ /// </summary>
[DebuggerDisplay("{Exception.Message}")]
internal class FailedAuthenticationResponse : IAuthenticationResponse {
/// <summary>
@@ -27,32 +31,127 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region IAuthenticationResponse Members
+ /// <summary>
+ /// Gets the Identifier that the end user claims to own. For use with user database storage and lookup.
+ /// May be null for some failed authentications (i.e. failed directed identity authentications).
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This is the secure identifier that should be used for database storage and lookup.
+ /// It is not always friendly (i.e. =Arnott becomes =!9B72.7DD1.50A9.5CCD), but it protects
+ /// user identities against spoofing and other attacks.
+ /// </para>
+ /// <para>
+ /// For user-friendly identifiers to display, use the
+ /// <see cref="FriendlyIdentifierForDisplay"/> property.
+ /// </para>
+ /// </remarks>
public Identifier ClaimedIdentifier {
get { return null; }
}
+ /// <summary>
+ /// Gets a user-friendly OpenID Identifier for display purposes ONLY.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This <i>should</i> be put through <see cref="HttpUtility.HtmlEncode(string)"/> before
+ /// sending to a browser to secure against javascript injection attacks.
+ /// </para>
+ /// <para>
+ /// This property retains some aspects of the user-supplied identifier that get lost
+ /// in the <see cref="ClaimedIdentifier"/>. For example, XRIs used as user-supplied
+ /// identifiers (i.e. =Arnott) become unfriendly unique strings (i.e. =!9B72.7DD1.50A9.5CCD).
+ /// For display purposes, such as text on a web page that says "You're logged in as ...",
+ /// this property serves to provide the =Arnott string, or whatever else is the most friendly
+ /// string close to what the user originally typed in.
+ /// </para>
+ /// <para>
+ /// If the user-supplied identifier is a URI, this property will be the URI after all
+ /// redirects, and with the protocol and fragment trimmed off.
+ /// If the user-supplied identifier is an XRI, this property will be the original XRI.
+ /// If the user-supplied identifier is an OpenID Provider identifier (i.e. yahoo.com),
+ /// this property will be the Claimed Identifier, with the protocol stripped if it is a URI.
+ /// </para>
+ /// <para>
+ /// It is <b>very</b> important that this property <i>never</i> be used for database storage
+ /// or lookup to avoid identity spoofing and other security risks. For database storage
+ /// and lookup please use the <see cref="ClaimedIdentifier"/> property.
+ /// </para>
+ /// </remarks>
public string FriendlyIdentifierForDisplay {
get { return null; }
}
+ /// <summary>
+ /// Gets the detailed success or failure status of the authentication attempt.
+ /// </summary>
+ /// <value></value>
public AuthenticationStatus Status {
get { return AuthenticationStatus.Failed; }
}
+ /// <summary>
+ /// Gets the details regarding a failed authentication attempt, if available.
+ /// This will be set if and only if <see cref="Status"/> is <see cref="AuthenticationStatus.Failed"/>.
+ /// </summary>
+ /// <value></value>
public Exception Exception { get; private set; }
+ /// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// <para>This MAY return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
public IDictionary<string, string> GetCallbackArguments() {
return new Dictionary<string, string>();
}
+ /// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// <para>This may return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
public string GetCallbackArgument(string key) {
return null;
}
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
public T GetExtension<T>() where T : IOpenIdMessageExtension, new() {
return default(T);
}
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <param name="extensionType">Type of the extension to look for in the response.</param>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
public IOpenIdMessageExtension GetExtension(Type extensionType) {
return null;
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
index 9cfdf7b..98fe3f9 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationRequest.cs
@@ -78,12 +78,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Makes a dictionary of key/value pairs available when the authentication is completed.
/// </summary>
+ /// <param name="arguments">The arguments to add to the request's return_to URI.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// <para>Note that these values are NOT protected against tampering in transit. No
/// security-sensitive data should be stored using this method.</para>
- /// <para>The values stored here can be retrieved using
+ /// <para>The values stored here can be retrieved using
/// <see cref="IAuthenticationResponse.GetCallbackArguments"/>.</para>
- /// <para>Since the data set here is sent in the querystring of the request and some
+ /// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
/// </remarks>
@@ -92,12 +93,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Makes a key/value pair available when the authentication is completed.
/// </summary>
+ /// <param name="key">The parameter name.</param>
+ /// <param name="value">The value of the argument.</param>
/// <remarks>
- /// <para>Note that these values are NOT protected against tampering in transit. No
+ /// <para>Note that these values are NOT protected against tampering in transit. No
/// security-sensitive data should be stored using this method.</para>
- /// <para>The value stored here can be retrieved using
+ /// <para>The value stored here can be retrieved using
/// <see cref="IAuthenticationResponse.GetCallbackArgument"/>.</para>
- /// <para>Since the data set here is sent in the querystring of the request and some
+ /// <para>Since the data set here is sent in the querystring of the request and some
/// servers place limits on the size of a request URL, this data should be kept relatively
/// small to ensure successful authentication. About 1.5KB is about all that should be stored.</para>
/// </remarks>
@@ -106,6 +109,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Adds an OpenID extension to the request directed at the OpenID provider.
/// </summary>
+ /// <param name="extension">The initialized extension to add to the request.</param>
void AddExtension(IOpenIdMessageExtension extension);
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
index 9105dcd..fb210e2 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/IAuthenticationResponse.cs
@@ -85,15 +85,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Exception Exception { get; }
/// <summary>
- /// Gets a callback argument's value that was previously added using
+ /// Gets a callback argument's value that was previously added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
/// </summary>
- /// <returns>The value of the argument, or null if the named parameter could not be found.</returns>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
/// <remarks>
- /// <para>This may return any argument on the querystring that came with the authentication response,
- /// which may include parameters not explicitly added using
+ /// <para>This may return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
- /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
/// </remarks>
string GetCallbackArgument(string key);
@@ -109,20 +112,26 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
/// <para>Note that these values are NOT protected against tampering in transit.</para>
/// </remarks>
- [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
- IDictionary<string, string> GetCallbackArguments();
+ [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Historically an expensive operation.")]
+ IDictionary<string, string> GetCallbackArguments(); // TODO: consider changing this to a property since the result can be cached.
/// <summary>
/// Tries to get an OpenID extension that may be present in the response.
/// </summary>
- /// <returns>The extension, if it is found. Null otherwise.</returns>
- [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
+ /// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "No parameter at all is required. T is used for return type.")]
T GetExtension<T>() where T : IOpenIdMessageExtension, new();
/// <summary>
/// Tries to get an OpenID extension that may be present in the response.
/// </summary>
- /// <returns>The extension, if it is found. Null otherwise.</returns>
+ /// <param name="extensionType">Type of the extension to look for in the response.</param>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
IOpenIdMessageExtension GetExtension(Type extensionType);
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
index 9d1cffc..4c1992d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
@@ -10,52 +10,108 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
+ /// <summary>
+ /// Wraps a negative assertion response in an <see cref="IAuthenticationResponse"/> instance
+ /// for public consumption by the host web site.
+ /// </summary>
internal class NegativeAuthenticationResponse : IAuthenticationResponse, ISetupRequiredAuthenticationResponse {
+ /// <summary>
+ /// The negative assertion message that was received by the RP that was used
+ /// to create this instance.
+ /// </summary>
private readonly NegativeAssertionResponse response;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NegativeAuthenticationResponse"/> class.
+ /// </summary>
+ /// <param name="response">The negative assertion response received by the Relying Party.</param>
internal NegativeAuthenticationResponse(NegativeAssertionResponse response) {
ErrorUtilities.VerifyArgumentNotNull(response, "response");
this.response = response;
}
- #region IAuthenticationResponse Members
-
+ #region IAuthenticationResponse Properties
+
+ /// <summary>
+ /// Gets the Identifier that the end user claims to own. For use with user database storage and lookup.
+ /// May be null for some failed authentications (i.e. failed directed identity authentications).
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This is the secure identifier that should be used for database storage and lookup.
+ /// It is not always friendly (i.e. =Arnott becomes =!9B72.7DD1.50A9.5CCD), but it protects
+ /// user identities against spoofing and other attacks.
+ /// </para>
+ /// <para>
+ /// For user-friendly identifiers to display, use the
+ /// <see cref="FriendlyIdentifierForDisplay"/> property.
+ /// </para>
+ /// </remarks>
public Identifier ClaimedIdentifier {
get { return null; }
}
+ /// <summary>
+ /// Gets a user-friendly OpenID Identifier for display purposes ONLY.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This <i>should</i> be put through <see cref="HttpUtility.HtmlEncode(string)"/> before
+ /// sending to a browser to secure against javascript injection attacks.
+ /// </para>
+ /// <para>
+ /// This property retains some aspects of the user-supplied identifier that get lost
+ /// in the <see cref="ClaimedIdentifier"/>. For example, XRIs used as user-supplied
+ /// identifiers (i.e. =Arnott) become unfriendly unique strings (i.e. =!9B72.7DD1.50A9.5CCD).
+ /// For display purposes, such as text on a web page that says "You're logged in as ...",
+ /// this property serves to provide the =Arnott string, or whatever else is the most friendly
+ /// string close to what the user originally typed in.
+ /// </para>
+ /// <para>
+ /// If the user-supplied identifier is a URI, this property will be the URI after all
+ /// redirects, and with the protocol and fragment trimmed off.
+ /// If the user-supplied identifier is an XRI, this property will be the original XRI.
+ /// If the user-supplied identifier is an OpenID Provider identifier (i.e. yahoo.com),
+ /// this property will be the Claimed Identifier, with the protocol stripped if it is a URI.
+ /// </para>
+ /// <para>
+ /// It is <b>very</b> important that this property <i>never</i> be used for database storage
+ /// or lookup to avoid identity spoofing and other security risks. For database storage
+ /// and lookup please use the <see cref="ClaimedIdentifier"/> property.
+ /// </para>
+ /// </remarks>
public string FriendlyIdentifierForDisplay {
get { return null; }
}
+ /// <summary>
+ /// Gets the detailed success or failure status of the authentication attempt.
+ /// </summary>
+ /// <value></value>
public AuthenticationStatus Status {
get { return this.response.Immediate ? AuthenticationStatus.SetupRequired : AuthenticationStatus.Canceled; }
}
+ /// <summary>
+ /// Gets the details regarding a failed authentication attempt, if available.
+ /// This will be set if and only if <see cref="Status"/> is <see cref="AuthenticationStatus.Failed"/>.
+ /// </summary>
+ /// <value></value>
public Exception Exception {
get { return null; }
}
- public string GetCallbackArgument(string key) {
- return null;
- }
-
- public IDictionary<string, string> GetCallbackArguments() {
- return EmptyDictionary<string, string>.Instance;
- }
-
- public T GetExtension<T>() where T : IOpenIdMessageExtension, new() {
- return default(T);
- }
-
- public IOpenIdMessageExtension GetExtension(Type extensionType) {
- return null;
- }
-
#endregion
#region ISetupRequiredAuthenticationResponse Members
+ /// <summary>
+ /// Gets the <see cref="Identifier"/> to pass to <see cref="OpenIdRelyingParty.CreateRequest(Identifier)"/>
+ /// in a subsequent authentication attempt.
+ /// </summary>
+ /// <value></value>
public Identifier UserSuppliedIdentifier {
get {
if (this.Status != AuthenticationStatus.SetupRequired) {
@@ -69,5 +125,65 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
#endregion
+
+ #region IAuthenticationResponse Methods
+
+ /// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// <para>This may return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
+ public string GetCallbackArgument(string key) {
+ return null;
+ }
+
+ /// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// <para>This MAY return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
+ public IDictionary<string, string> GetCallbackArguments() {
+ return EmptyDictionary<string, string>.Instance;
+ }
+
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
+ public T GetExtension<T>() where T : IOpenIdMessageExtension, new() {
+ return default(T);
+ }
+
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <param name="extensionType">Type of the extension to look for in the response.</param>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
+ public IOpenIdMessageExtension GetExtension(Type extensionType) {
+ return null;
+ }
+
+ #endregion
}
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index ab2385f..32bcbdc 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -18,6 +18,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.OpenId.Messages;
/// <summary>
+ /// A delegate that decides whether a given OpenID Provider endpoint may be
+ /// considered for authenticating a user.
+ /// </summary>
+ /// <param name="endpoint">The endpoint for consideration.</param>
+ /// <returns>
+ /// <c>True</c> if the endpoint should be considered.
+ /// <c>False</c> to remove it from the pool of acceptable providers.
+ /// </returns>
+ public delegate bool EndpointSelector(IXrdsProviderEndpoint endpoint);
+
+ /// <summary>
/// Provides the programmatic facilities to act as an OpenId consumer.
/// </summary>
public sealed class OpenIdRelyingParty {
@@ -26,6 +37,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
private RelyingPartySecuritySettings securitySettings;
+ /// <summary>
+ /// Backing store for the <see cref="EndpointOrder"/> property.
+ /// </summary>
private Comparison<IXrdsProviderEndpoint> endpointOrder = DefaultEndpointOrder;
/// <summary>
@@ -136,6 +150,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets or sets the ordering routine that will determine which XRDS
/// Service element to try first
/// </summary>
+ /// <value>Default is <see cref="DefaultEndpointOrder"/>.</value>
/// <remarks>
/// This may never be null. To reset to default behavior this property
/// can be set to the value of <see cref="DefaultEndpointOrder"/>.
@@ -283,6 +298,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
+ /// <summary>
+ /// Determines whether some parameter name belongs to OpenID or this library
+ /// as a protocol or internal parameter name.
+ /// </summary>
+ /// <param name="parameterName">Name of the parameter.</param>
+ /// <returns>
+ /// <c>true</c> if the named parameter is a library- or protocol-specific parameter; otherwise, <c>false</c>.
+ /// </returns>
internal static bool IsOpenIdSupportingParameter(string parameterName) {
Protocol protocol = Protocol.Default;
return parameterName.StartsWith(protocol.openid.Prefix, StringComparison.OrdinalIgnoreCase)
@@ -451,10 +474,22 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return association;
}
+ /// <summary>
+ /// Gets an existing association with the specified Provider, or attempts to create
+ /// a new association of one does not already exist.
+ /// </summary>
+ /// <param name="provider">The provider to get an association for.</param>
+ /// <returns>The existing or new association; <c>null</c> if none existed and one could not be created.</returns>
internal Association GetOrCreateAssociation(ProviderEndpointDescription provider) {
return this.GetExistingAssociation(provider) ?? this.CreateNewAssociation(provider);
}
+ /// <summary>
+ /// Gets the priority rating for a given type of endpoint, allowing a
+ /// priority sorting of endpoints.
+ /// </summary>
+ /// <param name="endpoint">The endpoint to prioritize.</param>
+ /// <returns>An arbitary integer, which may be used for sorting against other returned values from this method.</returns>
private static double GetEndpointPrecedenceOrderByServiceType(IXrdsProviderEndpoint endpoint) {
// The numbers returned from this method only need to compare against other numbers
// from this method, which makes them arbitrary but relational to only others here.
@@ -511,15 +546,4 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
}
}
-
-
- /// <summary>
- /// A delegate that decides whether a given OpenID Provider endpoint may be
- /// considered for authenticating a user.
- /// </summary>
- /// <returns>
- /// True if the endpoint should be considered.
- /// False to remove it from the pool of acceptable providers.
- /// </returns>
- public delegate bool EndpointSelector(IXrdsProviderEndpoint endpoint);
}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index 1d9dbdf..787f03b 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -13,9 +13,20 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
+ /// <summary>
+ /// Wraps a positive assertion response in an <see cref="IAuthenticationResponse"/> instance
+ /// for public consumption by the host web site.
+ /// </summary>
[DebuggerDisplay("Status: {Status}, ClaimedIdentifier: {ClaimedIdentifier}")]
internal class PositiveAuthenticationResponse : IAuthenticationResponse {
+ /// <summary>
+ /// The positive assertion message the Relying Party received that this instance wraps.
+ /// </summary>
private readonly PositiveAssertionResponse response;
+
+ /// <summary>
+ /// The relying party that created this request object.
+ /// </summary>
private readonly OpenIdRelyingParty relyingParty;
/// <summary>
@@ -29,6 +40,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
private readonly ServiceEndpoint endpoint;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PositiveAuthenticationResponse"/> class.
+ /// </summary>
+ /// <param name="response">The positive assertion response that was just received by the Relying Party.</param>
+ /// <param name="relyingParty">The relying party.</param>
internal PositiveAuthenticationResponse(PositiveAssertionResponse response, OpenIdRelyingParty relyingParty) {
ErrorUtilities.VerifyArgumentNotNull(response, "response");
ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty");
@@ -49,26 +65,107 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region IAuthenticationResponse Members
+ /// <summary>
+ /// Gets the Identifier that the end user claims to own. For use with user database storage and lookup.
+ /// May be null for some failed authentications (i.e. failed directed identity authentications).
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This is the secure identifier that should be used for database storage and lookup.
+ /// It is not always friendly (i.e. =Arnott becomes =!9B72.7DD1.50A9.5CCD), but it protects
+ /// user identities against spoofing and other attacks.
+ /// </para>
+ /// <para>
+ /// For user-friendly identifiers to display, use the
+ /// <see cref="FriendlyIdentifierForDisplay"/> property.
+ /// </para>
+ /// </remarks>
public Identifier ClaimedIdentifier {
get { return this.endpoint.ClaimedIdentifier; }
}
+ /// <summary>
+ /// Gets a user-friendly OpenID Identifier for display purposes ONLY.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// <para>
+ /// This <i>should</i> be put through <see cref="HttpUtility.HtmlEncode(string)"/> before
+ /// sending to a browser to secure against javascript injection attacks.
+ /// </para>
+ /// <para>
+ /// This property retains some aspects of the user-supplied identifier that get lost
+ /// in the <see cref="ClaimedIdentifier"/>. For example, XRIs used as user-supplied
+ /// identifiers (i.e. =Arnott) become unfriendly unique strings (i.e. =!9B72.7DD1.50A9.5CCD).
+ /// For display purposes, such as text on a web page that says "You're logged in as ...",
+ /// this property serves to provide the =Arnott string, or whatever else is the most friendly
+ /// string close to what the user originally typed in.
+ /// </para>
+ /// <para>
+ /// If the user-supplied identifier is a URI, this property will be the URI after all
+ /// redirects, and with the protocol and fragment trimmed off.
+ /// If the user-supplied identifier is an XRI, this property will be the original XRI.
+ /// If the user-supplied identifier is an OpenID Provider identifier (i.e. yahoo.com),
+ /// this property will be the Claimed Identifier, with the protocol stripped if it is a URI.
+ /// </para>
+ /// <para>
+ /// It is <b>very</b> important that this property <i>never</i> be used for database storage
+ /// or lookup to avoid identity spoofing and other security risks. For database storage
+ /// and lookup please use the <see cref="ClaimedIdentifier"/> property.
+ /// </para>
+ /// </remarks>
public string FriendlyIdentifierForDisplay {
get { return this.endpoint.FriendlyIdentifierForDisplay; }
}
+ /// <summary>
+ /// Gets the detailed success or failure status of the authentication attempt.
+ /// </summary>
+ /// <value></value>
public AuthenticationStatus Status {
get { return AuthenticationStatus.Authenticated; }
}
+ /// <summary>
+ /// Gets the details regarding a failed authentication attempt, if available.
+ /// This will be set if and only if <see cref="Status"/> is <see cref="AuthenticationStatus.Failed"/>.
+ /// </summary>
+ /// <value></value>
public Exception Exception {
get { return null; }
}
+ /// <summary>
+ /// Gets a callback argument's value that was previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.
+ /// </summary>
+ /// <param name="key">The name of the parameter whose value is sought.</param>
+ /// <returns>
+ /// The value of the argument, or null if the named parameter could not be found.
+ /// </returns>
+ /// <remarks>
+ /// <para>This may return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
public string GetCallbackArgument(string key) {
return this.response.GetReturnToArgument(key);
}
+ /// <summary>
+ /// Gets all the callback arguments that were previously added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/> or as a natural part
+ /// of the return_to URL.
+ /// </summary>
+ /// <returns>A name-value dictionary. Never null.</returns>
+ /// <remarks>
+ /// <para>This MAY return any argument on the querystring that came with the authentication response,
+ /// which may include parameters not explicitly added using
+ /// <see cref="IAuthenticationRequest.AddCallbackArguments(string, string)"/>.</para>
+ /// <para>Note that these values are NOT protected against tampering in transit.</para>
+ /// </remarks>
public IDictionary<string, string> GetCallbackArguments() {
var args = new Dictionary<string, string>();
@@ -82,10 +179,24 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
return args;
}
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <typeparam name="T">The type of extension to look for in the response message.</typeparam>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
public T GetExtension<T>() where T : IOpenIdMessageExtension, new() {
return this.response.Extensions.OfType<T>().FirstOrDefault();
}
+ /// <summary>
+ /// Tries to get an OpenID extension that may be present in the response.
+ /// </summary>
+ /// <param name="extensionType">Type of the extension to look for in the response.</param>
+ /// <returns>
+ /// The extension, if it is found. Null otherwise.
+ /// </returns>
public IOpenIdMessageExtension GetExtension(Type extensionType) {
ErrorUtilities.VerifyArgumentNotNull(extensionType, "extensionType");
return this.response.Extensions.OfType<IOpenIdMessageExtension>().Where(ext => extensionType.IsInstanceOfType(ext)).FirstOrDefault();
diff --git a/src/DotNetOpenAuth/Settings.StyleCop b/src/DotNetOpenAuth/Settings.StyleCop
index 9577b59..8c19231 100644
--- a/src/DotNetOpenAuth/Settings.StyleCop
+++ b/src/DotNetOpenAuth/Settings.StyleCop
@@ -10,5 +10,15 @@
</Rules>
<AnalyzerSettings />
</Analyzer>
+ <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.MaintainabilityRules">
+ <Rules>
+ <Rule Name="StatementMustNotUseUnnecessaryParenthesis">
+ <RuleSettings>
+ <BooleanProperty Name="Enabled">False</BooleanProperty>
+ </RuleSettings>
+ </Rule>
+ </Rules>
+ <AnalyzerSettings />
+ </Analyzer>
</Analyzers>
</StyleCopSettings> \ No newline at end of file