//-----------------------------------------------------------------------
//
// Copyright (c) Andrew Arnott. All rights reserved.
//
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.OpenId.Messages {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNetOpenAuth.Messaging;
using System.Diagnostics.Contracts;
using DotNetOpenAuth.OpenId.Provider;
internal abstract class AssociateRequestProvider : AssociateRequest {
///
/// Initializes a new instance of the class.
///
/// The OpenID version this message must comply with.
/// The OpenID Provider endpoint.
internal AssociateRequestProvider(Version version, Uri providerEndpoint)
: base(version, providerEndpoint) {
}
///
/// Creates a Provider's response to an incoming association request.
///
/// The association store.
/// The security settings on the Provider.
///
/// The appropriate association response that is ready to be sent back to the Relying Party.
///
///
/// If an association is created, it will be automatically be added to the provided
/// association store.
/// Successful association response messages will derive from .
/// Failed association response messages will derive from .
///
internal IProtocolMessage CreateResponse(IProviderAssociationStore associationStore, ProviderSecuritySettings securitySettings) {
Contract.Requires(associationStore != null);
Contract.Requires(securitySettings != null);
IProtocolMessage response;
if (securitySettings.IsAssociationInPermittedRange(Protocol, this.AssociationType) &&
HmacShaAssociation.IsDHSessionCompatible(Protocol, this.AssociationType, this.SessionType)) {
response = this.CreateResponseCore();
// Create and store the association if this is a successful response.
var successResponse = response as AssociateSuccessfulResponseProvider;
if (successResponse != null) {
successResponse.CreateAssociationAtProvider(this, associationStore, securitySettings);
}
} else {
response = this.CreateUnsuccessfulResponse(securitySettings);
}
return response;
}
///
/// Creates a Provider's response to an incoming association request.
///
///
/// The appropriate association response message.
///
///
/// If an association can be successfully created, the
/// method must not be
/// called by this method.
/// Successful association response messages will derive from .
/// Failed association response messages will derive from .
///
protected abstract IProtocolMessage CreateResponseCore();
///
/// Creates a response that notifies the Relying Party that the requested
/// association type is not supported by this Provider, and offers
/// an alternative association type, if possible.
///
/// The security settings that apply to this Provider.
/// The response to send to the Relying Party.
private AssociateUnsuccessfulResponse CreateUnsuccessfulResponse(ProviderSecuritySettings securitySettings) {
Contract.Requires(securitySettings != null);
var unsuccessfulResponse = new AssociateUnsuccessfulResponse(this.Version, this);
// The strategy here is to suggest that the RP try again with the lowest
// permissible security settings, giving the RP the best chance of being
// able to match with a compatible request.
bool unencryptedAllowed = this.Recipient.IsTransportSecure();
bool useDiffieHellman = !unencryptedAllowed;
string associationType, sessionType;
if (HmacShaAssociation.TryFindBestAssociation(Protocol, false, securitySettings, useDiffieHellman, out associationType, out sessionType)) {
ErrorUtilities.VerifyInternal(this.AssociationType != associationType, "The RP asked for an association that should have been allowed, but the OP is trying to suggest the same one as an alternative!");
unsuccessfulResponse.AssociationType = associationType;
unsuccessfulResponse.SessionType = sessionType;
Logger.OpenId.InfoFormat(
"Association requested of type '{0}' and session '{1}', which the Provider does not support. Sending back suggested alternative of '{0}' with session '{1}'.",
this.AssociationType,
this.SessionType,
unsuccessfulResponse.AssociationType,
unsuccessfulResponse.SessionType);
} else {
Logger.OpenId.InfoFormat("Association requested of type '{0}' and session '{1}', which the Provider does not support. No alternative association type qualified for suggesting back to the Relying Party.", this.AssociationType, this.SessionType);
}
return unsuccessfulResponse;
}
}
}