summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OpenId.RelyingParty/OpenId')
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs6
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs6
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs103
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs2
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs15
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/ISetupRequiredAuthenticationResponse.cs1
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/NegativeAuthenticationResponse.cs1
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs27
-rw-r--r--src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs10
9 files changed, 115 insertions, 56 deletions
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
index 90910b7..b3a3f79 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/RelyingPartySecurityOptions.cs
@@ -15,8 +15,14 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Helps ensure compliance to some properties in the <see cref="RelyingPartySecuritySettings"/>.
/// </summary>
internal class RelyingPartySecurityOptions : IChannelBindingElement {
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+ /// <summary>
+ /// A reusable pre-completed task that may be returned multiple times to reduce GC pressure.
+ /// </summary>
private static readonly Task<MessageProtections?> NoneTask =
Task.FromResult<MessageProtections?>(MessageProtections.None);
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
index 1948215..a919560 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/ChannelElements/ReturnToNonceBindingElement.cs
@@ -48,8 +48,14 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// only on the RP side and only on some messages.</para>
/// </remarks>
internal class ReturnToNonceBindingElement : IChannelBindingElement {
+ /// <summary>
+ /// A reusable, precompleted task that can be returned many times to reduce GC pressure.
+ /// </summary>
private static readonly Task<MessageProtections?> NullTask = Task.FromResult<MessageProtections?>(null);
+ /// <summary>
+ /// A reusable, precompleted task that can be returned many times to reduce GC pressure.
+ /// </summary>
private static readonly Task<MessageProtections?> ReplayProtectionTask =
Task.FromResult<MessageProtections?>(MessageProtections.ReplayProtection);
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
index fb4006c..80a1665 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/HostMetaDiscoveryService.cs
@@ -193,6 +193,9 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="identifier">The identifier under discovery.</param>
/// <param name="response">The response.</param>
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
+ /// <returns>
+ /// A task that completes with the asynchronous operation.
+ /// </returns>
/// <exception cref="ProtocolException">Thrown if the XRDS document has an invalid or a missing signature.</exception>
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "XmlDSig", Justification = "xml")]
private static async Task ValidateXmlDSigAsync(XrdsDocument document, UriIdentifier identifier, HttpResponseMessage response, string signingHost) {
@@ -259,6 +262,47 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Verifies that a certificate chain is trusted.
+ /// </summary>
+ /// <param name="certificates">The chain of certificates to verify.</param>
+ private static void VerifyCertificateChain(IList<X509Certificate2> certificates) {
+ Requires.NotNullEmptyOrNullElements(certificates, "certificates");
+
+ // Before calling into the OS to validate the certificate, since that can for some bizzare reason hang for 5 seconds
+ // on some systems, check a cache of previously verified certificates first.
+ if (OpenIdElement.Configuration.RelyingParty.HostMetaDiscovery.EnableCertificateValidationCache) {
+ lock (ApprovedCertificateThumbprintCache) {
+ // HashSet<T> isn't thread-safe.
+ if (ApprovedCertificateThumbprintCache.Contains(certificates[0].Thumbprint)) {
+ return;
+ }
+ }
+ }
+
+ // Verify that we trust the signer of the certificates.
+ // Start by trying to validate just the certificate used to sign the XRDS document,
+ // since we can do that with partial trust.
+ Logger.OpenId.Debug("Verifying that we trust the certificate used to sign the discovery document.");
+ if (!certificates[0].Verify()) {
+ // We couldn't verify just the signing certificate, so try to verify the whole certificate chain.
+ try {
+ Logger.OpenId.Debug("Verifying the whole certificate chain.");
+ VerifyCertChain(certificates);
+ Logger.OpenId.Debug("Certificate chain verified.");
+ } catch (SecurityException) {
+ Logger.Yadis.Warn("Signing certificate verification failed and we have insufficient code access security permissions to perform certificate chain validation.");
+ ErrorUtilities.ThrowProtocol(OpenIdStrings.X509CertificateNotTrusted);
+ }
+ }
+
+ if (OpenIdElement.Configuration.RelyingParty.HostMetaDiscovery.EnableCertificateValidationCache) {
+ lock (ApprovedCertificateThumbprintCache) {
+ ApprovedCertificateThumbprintCache.Add(certificates[0].Thumbprint);
+ }
+ }
+ }
+
+ /// <summary>
/// Gets the services for an identifier that are described by an external XRDS document.
/// </summary>
/// <param name="xrds">The XRD elements to search for described-by services.</param>
@@ -332,47 +376,6 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Verifies that a certificate chain is trusted.
- /// </summary>
- /// <param name="certificates">The chain of certificates to verify.</param>
- private static void VerifyCertificateChain(IList<X509Certificate2> certificates) {
- Requires.NotNullEmptyOrNullElements(certificates, "certificates");
-
- // Before calling into the OS to validate the certificate, since that can for some bizzare reason hang for 5 seconds
- // on some systems, check a cache of previously verified certificates first.
- if (OpenIdElement.Configuration.RelyingParty.HostMetaDiscovery.EnableCertificateValidationCache) {
- lock (ApprovedCertificateThumbprintCache) {
- // HashSet<T> isn't thread-safe.
- if (ApprovedCertificateThumbprintCache.Contains(certificates[0].Thumbprint)) {
- return;
- }
- }
- }
-
- // Verify that we trust the signer of the certificates.
- // Start by trying to validate just the certificate used to sign the XRDS document,
- // since we can do that with partial trust.
- Logger.OpenId.Debug("Verifying that we trust the certificate used to sign the discovery document.");
- if (!certificates[0].Verify()) {
- // We couldn't verify just the signing certificate, so try to verify the whole certificate chain.
- try {
- Logger.OpenId.Debug("Verifying the whole certificate chain.");
- VerifyCertChain(certificates);
- Logger.OpenId.Debug("Certificate chain verified.");
- } catch (SecurityException) {
- Logger.Yadis.Warn("Signing certificate verification failed and we have insufficient code access security permissions to perform certificate chain validation.");
- ErrorUtilities.ThrowProtocol(OpenIdStrings.X509CertificateNotTrusted);
- }
- }
-
- if (OpenIdElement.Configuration.RelyingParty.HostMetaDiscovery.EnableCertificateValidationCache) {
- lock (ApprovedCertificateThumbprintCache) {
- ApprovedCertificateThumbprintCache.Add(certificates[0].Thumbprint);
- }
- }
- }
-
- /// <summary>
/// Gets the XRDS HTTP response for a given identifier.
/// </summary>
/// <param name="identifier">The identifier.</param>
@@ -479,17 +482,35 @@ namespace DotNetOpenAuth.OpenId {
return result;
}
+ /// <summary>
+ /// A compound result of some value with the signing host.
+ /// </summary>
+ /// <typeparam name="T">The type of the primary result.</typeparam>
private struct ResultWithSigningHost<T> : IDisposable {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ResultWithSigningHost{T}"/> struct.
+ /// </summary>
+ /// <param name="result">The result.</param>
+ /// <param name="signingHost">The signing host.</param>
internal ResultWithSigningHost(T result, string signingHost)
: this() {
this.Result = result;
this.SigningHost = signingHost;
}
+ /// <summary>
+ /// Gets the result.
+ /// </summary>
public T Result { get; private set; }
+ /// <summary>
+ /// Gets the signing host.
+ /// </summary>
public string SigningHost { get; private set; }
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
public void Dispose() {
var disposable = this.Result as IDisposable;
disposable.DisposeIfNotNull();
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
index 367c146..86f178b 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AssociationManager.cs
@@ -187,7 +187,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// The newly created association, or null if no association can be created with
/// the given Provider given the current security settings.
/// </returns>
- /// <exception cref="ProtocolException"></exception>
+ /// <exception cref="ProtocolException">Create if an error occurs while creating the new association.</exception>
private async Task<Association> CreateNewAssociationAsync(IProviderEndpoint provider, AssociateRequest associateRequest, int retriesRemaining, CancellationToken cancellationToken) {
Requires.NotNull(provider, "provider");
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
index 6298f9c..c7c1fe3 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -355,7 +355,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
// Perform discovery right now (not deferred).
IEnumerable<IdentifierDiscoveryResult> serviceEndpoints;
try {
- var results = (await relyingParty.DiscoverAsync(userSuppliedIdentifier, cancellationToken)).CacheGeneratedResults();
+ var identifierDiscoveryResults = await relyingParty.DiscoverAsync(userSuppliedIdentifier, cancellationToken);
+ var results = identifierDiscoveryResults.CacheGeneratedResults();
// If any OP Identifier service elements were found, we must not proceed
// to use any Claimed Identifier services, per OpenID 2.0 sections 7.3.2.2 and 11.2.
@@ -404,7 +405,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
- /// Performs deferred request generation for the <see cref="Create" /> method.
+ /// Performs deferred request generation for the <see cref="CreateAsync" /> method.
/// </summary>
/// <param name="userSuppliedIdentifier">The user supplied identifier.</param>
/// <param name="relyingParty">The relying party.</param>
@@ -534,7 +535,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Creates the request message to send to the Provider,
/// based on the properties in this instance.
/// </summary>
- /// <returns>The message to send to the Provider.</returns>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The message to send to the Provider.
+ /// </returns>
private async Task<SignedResponseRequest> CreateRequestMessageAsync(CancellationToken cancellationToken) {
Association association = await this.GetAssociationAsync(cancellationToken);
@@ -565,7 +569,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets the association to use for this authentication request.
/// </summary>
- /// <returns>The association to use; <c>null</c> to use 'dumb mode'.</returns>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The association to use; <c>null</c> to use 'dumb mode'.
+ /// </returns>
private async Task<Association> GetAssociationAsync(CancellationToken cancellationToken) {
Association association = null;
switch (this.associationPreference) {
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/ISetupRequiredAuthenticationResponse.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/ISetupRequiredAuthenticationResponse.cs
index af36a00..f4fdeb1 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/ISetupRequiredAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/ISetupRequiredAuthenticationResponse.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Threading;
+ using System.Web;
/// <summary>
/// An interface to expose useful properties and functionality for handling
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/NegativeAuthenticationResponse.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
index 79fc5de..fdd3529 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Linq;
+ using System.Threading;
using System.Threading.Tasks;
using System.Web;
using DotNetOpenAuth.Messaging;
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
index db23cdb..ad20356 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -336,7 +336,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Requires.NotNull(realm, "realm");
Requires.NotNull(returnToUrl, "returnToUrl");
try {
- return (await this.CreateRequestsAsync(userSuppliedIdentifier, realm, returnToUrl)).First();
+ var requests = await this.CreateRequestsAsync(userSuppliedIdentifier, realm, returnToUrl);
+ return requests.First();
} catch (InvalidOperationException ex) {
throw ErrorUtilities.Wrap(ex, OpenIdStrings.OpenIdEndpointNotFound);
}
@@ -364,7 +365,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
Requires.NotNull(realm, "realm");
try {
- var result = (await this.CreateRequestsAsync(userSuppliedIdentifier, realm, cancellationToken: cancellationToken)).First();
+ var request = await this.CreateRequestsAsync(userSuppliedIdentifier, realm, cancellationToken: cancellationToken);
+ var result = request.First();
Assumes.True(result != null);
return result;
} catch (InvalidOperationException ex) {
@@ -391,7 +393,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public async Task<IAuthenticationRequest> CreateRequestAsync(Identifier userSuppliedIdentifier, HttpRequestBase requestContext = null, CancellationToken cancellationToken = default(CancellationToken)) {
Requires.NotNull(userSuppliedIdentifier, "userSuppliedIdentifier");
try {
- return (await this.CreateRequestsAsync(userSuppliedIdentifier, requestContext, cancellationToken)).First();
+ var authenticationRequests = await this.CreateRequestsAsync(userSuppliedIdentifier, requestContext, cancellationToken);
+ return authenticationRequests.First();
} catch (InvalidOperationException ex) {
throw ErrorUtilities.Wrap(ex, OpenIdStrings.OpenIdEndpointNotFound);
}
@@ -495,7 +498,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <para>Any individual generated request can satisfy the authentication.
/// The generated requests are sorted in preferred order.
/// Each request is generated as it is enumerated to. Associations are created only as
- /// <see cref="IAuthenticationRequest.RedirectingResponse" /> is called.</para>
+ /// <see cref="IAuthenticationRequest.GetRedirectingResponseAsync" /> is called.</para>
/// <para>No exception is thrown if no OpenID endpoints were discovered.
/// An empty enumerable is returned instead.</para>
/// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
@@ -509,9 +512,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets an authentication response from a Provider.
/// </summary>
- /// <returns>The processed authentication response if there is any; <c>null</c> otherwise.</returns>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The processed authentication response if there is any; <c>null</c> otherwise.
+ /// </returns>
/// <remarks>
- /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
+ /// Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.
/// </remarks>
public Task<IAuthenticationResponse> GetResponseAsync(CancellationToken cancellationToken) {
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
@@ -565,9 +571,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Processes the response received in a popup window or iframe to an AJAX-directed OpenID authentication.
/// </summary>
- /// <returns>The HTTP response to send to this HTTP request.</returns>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>
+ /// The HTTP response to send to this HTTP request.
+ /// </returns>
/// <remarks>
- /// <para>Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.</para>
+ /// Requires an <see cref="HttpContext.Current">HttpContext.Current</see> context.
/// </remarks>
public Task<HttpResponseMessage> ProcessResponseFromPopupAsync(CancellationToken cancellationToken) {
RequiresEx.ValidState(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired);
@@ -597,7 +606,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <typeparam name="T">The extension <i>response</i> type that will read data from the assertion.</typeparam>
/// <param name="propertyName">The property name on the openid_identifier input box object that will be used to store the extension data. For example: sreg</param>
/// <remarks>
- /// This method should be called before <see cref="ProcessResponseFromPopup()"/>.
+ /// This method should be called before <see cref="ProcessResponseFromPopupAsync()"/>.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "By design")]
public void RegisterClientScriptExtension<T>(string propertyName) where T : IClientScriptExtensionResponse {
diff --git a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index d73d45f..79e9f65 100644
--- a/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth.OpenId.RelyingParty/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -16,7 +16,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using Validation;
/// <summary>
- /// Wraps a positive assertion response in an <see cref="IAuthenticationResponse"/> instance
+ /// 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}")]
@@ -123,6 +123,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
get { return (PositiveAssertionResponse)base.Response; }
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PositiveAuthenticationResponse"/> class
+ /// after verifying that discovery on the identifier matches the asserted data.
+ /// </summary>
+ /// <param name="response">The response.</param>
+ /// <param name="relyingParty">The relying party.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>The newly initialized instance.</returns>
internal static async Task<PositiveAuthenticationResponse> CreateAsync(
PositiveAssertionResponse response, OpenIdRelyingParty relyingParty, CancellationToken cancellationToken) {
var result = new PositiveAuthenticationResponse(response, relyingParty);