//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.OAuth2.Messages { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using DotNetOpenAuth.Messaging; using Validation; /// /// A common message base class for OAuth messages. /// [Serializable] public class MessageBase : IDirectedProtocolMessage, IDirectResponseProtocolMessage { /// /// A dictionary to contain extra message data. /// private Dictionary extraData = new Dictionary(); /// /// The originating request. /// private IDirectedProtocolMessage originatingRequest; /// /// The backing field for the property. /// private Version version; /// /// A value indicating whether this message is a direct or indirect message. /// private MessageTransport messageTransport; /// /// Initializes a new instance of the class /// that is used for direct response messages. /// /// The version. protected MessageBase(Version version) { Requires.NotNull(version, "version"); this.messageTransport = MessageTransport.Direct; this.version = version; this.HttpMethods = HttpDeliveryMethods.GetRequest; } /// /// Initializes a new instance of the class. /// /// The originating request. /// The recipient of the directed message. Null if not applicable. protected MessageBase(IDirectedProtocolMessage request, Uri recipient = null) { Requires.NotNull(request, "request"); this.originatingRequest = request; this.messageTransport = request.Transport; this.version = request.Version; this.Recipient = recipient; this.HttpMethods = HttpDeliveryMethods.GetRequest; } /// /// Initializes a new instance of the class /// that is used for directed messages. /// /// The version. /// The message transport. /// The recipient. protected MessageBase(Version version, MessageTransport messageTransport, Uri recipient) { Requires.NotNull(version, "version"); Requires.NotNull(recipient, "recipient"); this.version = version; this.messageTransport = messageTransport; this.Recipient = recipient; this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest; } #region IMessage Properties /// /// Gets the version of the protocol or extension this message is prepared to implement. /// /// /// Implementations of this interface should ensure that this property never returns null. /// Version IMessage.Version { get { return this.Version; } } /// /// Gets the extra, non-standard Protocol parameters included in the message. /// /// /// /// Implementations of this interface should ensure that this property never returns null. /// public IDictionary ExtraData { get { return this.extraData; } } #endregion #region IProtocolMessage Members /// /// Gets the level of protection this message requires. /// /// MessageProtections IProtocolMessage.RequiredProtection { get { return RequiredProtection; } } /// /// Gets a value indicating whether this is a direct or indirect message. /// /// MessageTransport IProtocolMessage.Transport { get { return this.Transport; } } #endregion #region IDirectedProtocolMessage Members /// /// Gets the preferred method of transport for the message. /// /// /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent: /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript /// to automate submission. /// HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods { get { return this.HttpMethods; } } /// /// Gets the URL of the intended receiver of this message. /// Uri IDirectedProtocolMessage.Recipient { get { return this.Recipient; } } #endregion #region IDirectResponseProtocolMessage Members /// /// Gets the originating request message that caused this response to be formed. /// IDirectedProtocolMessage IDirectResponseProtocolMessage.OriginatingRequest { get { return this.OriginatingRequest; } } #endregion /// /// Gets the level of protection this message requires. /// protected static MessageProtections RequiredProtection { get { return MessageProtections.None; } } /// /// Gets a value indicating whether this is a direct or indirect message. /// protected MessageTransport Transport { get { return this.messageTransport; } } /// /// Gets the version of the protocol or extension this message is prepared to implement. /// protected Version Version { get { return this.version; } } /// /// Gets or sets the preferred method of transport for the message. /// /// /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent: /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript /// to automate submission. /// protected HttpDeliveryMethods HttpMethods { get; set; } /// /// Gets the originating request message that caused this response to be formed. /// protected IDirectedProtocolMessage OriginatingRequest { get { return this.originatingRequest; } } /// /// Gets the URL of the intended receiver of this message. /// protected Uri Recipient { get; private set; } #region IMessage Methods /// /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// /// /// Some messages have required fields, or combinations of fields that must relate to each other /// in specialized ways. After deserializing a message, this method checks the state of the /// message to see if it conforms to the protocol. /// Note that this property should not check signatures or perform any state checks /// outside this scope of this particular message. /// /// Thrown if the message is invalid. void IMessage.EnsureValidMessage() { this.EnsureValidMessage(); } #endregion /// /// Checks the message state for conformity to the protocol specification /// and throws an exception if the message is invalid. /// /// /// Some messages have required fields, or combinations of fields that must relate to each other /// in specialized ways. After deserializing a message, this method checks the state of the /// message to see if it conforms to the protocol. /// Note that this property should not check signatures or perform any state checks /// outside this scope of this particular message. /// /// Thrown if the message is invalid. protected virtual void EnsureValidMessage() { } } }