diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2008-12-31 10:45:24 -0700 |
---|---|---|
committer | Andrew <andrewarnott@gmail.com> | 2009-01-03 19:24:47 -0800 |
commit | 3c3232d6eccf9804fe1e0ce5c751b35ab752df40 (patch) | |
tree | 3abaa7eee21cc2c48369ec6c86d7c668725f475e | |
parent | 49aaed61a5c029c0fc98fcd5ab252902601bad5b (diff) | |
download | DotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.zip DotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.tar.gz DotNetOpenAuth-3c3232d6eccf9804fe1e0ce5c751b35ab752df40.tar.bz2 |
StyleCop work
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 |