using System;
using System.Collections.Specialized;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;
using System.Globalization;
namespace DotNetOpenId.Provider {
///
/// A request to establish an association.
///
[DebuggerDisplay("Mode: {Mode}, AssocType: {assoc_type}, Session: {session.SessionType}, OpenId: {Protocol.Version}")]
internal class AssociateRequest : Request {
string assoc_type;
ProviderSession session;
public AssociateRequest(OpenIdProvider provider)
: base(provider) {
session = ProviderSession.CreateSession(provider);
assoc_type = Util.GetRequiredArg(Query, Protocol.openid.assoc_type);
if (Array.IndexOf(Protocol.Args.SignatureAlgorithm.All, assoc_type) < 0) {
throw new OpenIdException(string.Format(CultureInfo.CurrentCulture,
Strings.InvalidOpenIdQueryParameterValue,
Protocol.openid.assoc_type, assoc_type), provider.Query) {
ExtraArgsToReturn = CreateAssociationTypeHints(provider),
};
}
}
///
/// This method is used to throw a carefully crafted exception that will end up getting
/// encoded as a response to the RP, given hints as to what
/// assoc_type and session_type args we support.
///
/// A dictionary that should be passed to the OpenIdException
/// via the property.
internal static IDictionary CreateAssociationTypeHints(
OpenIdProvider provider) {
Protocol protocol = provider.Protocol;
return new Dictionary {
{ protocol.openidnp.error_code, protocol.Args.ErrorCode.UnsupportedType },
{ protocol.openidnp.session_type, protocol.Args.SessionType.DH_SHA1 },
{ protocol.openidnp.assoc_type, protocol.Args.SignatureAlgorithm.HMAC_SHA1 },
};
}
public override bool IsResponseReady {
// This type of request can always be responded to immediately.
get { return true; }
}
///
/// Returns the string "associate".
///
internal override string Mode {
get { return Protocol.Args.Mode.associate; }
}
///
/// Respond to this request with an association.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1820:TestForEmptyStringsUsingStringLength")]
public EncodableResponse Answer() {
Association assoc = Provider.Signatory.CreateAssociation(AssociationRelyingPartyType.Smart, Provider);
EncodableResponse response = EncodableResponse.PrepareDirectMessage(Protocol);
response.Fields[Protocol.openidnp.expires_in] = assoc.SecondsTillExpiration.ToString(CultureInfo.InvariantCulture);
response.Fields[Protocol.openidnp.assoc_type] = assoc.GetAssociationType(Protocol);
response.Fields[Protocol.openidnp.assoc_handle] = assoc.Handle;
response.Fields[Protocol.openidnp.session_type] = session.SessionType;
IDictionary nvc = session.Answer(assoc.SecretKey);
foreach (var pair in nvc) {
response.Fields[pair.Key] = nvc[pair.Key];
}
Logger.InfoFormat("Association {0} created.", assoc.Handle);
return response;
}
protected override IEncodable CreateResponse() {
return Answer();
}
public override string ToString() {
string returnString = "AssociateRequest._assoc_type = {0}";
return base.ToString() + Environment.NewLine + string.Format(CultureInfo.CurrentCulture,
returnString, assoc_type);
}
}
}