summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth/OAuth/Messages
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2011-07-01 16:49:44 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2011-07-01 16:49:44 -0700
commitb6f7a18b949acb4346754ae47fb07424076a3cd0 (patch)
tree4c23cb2b8174f3288cb0b787cff4c6ac432c6bef /src/DotNetOpenAuth.OAuth/OAuth/Messages
parentf16525005555b86151b7a1c741aa29550635108a (diff)
downloadDotNetOpenAuth-b6f7a18b949acb4346754ae47fb07424076a3cd0.zip
DotNetOpenAuth-b6f7a18b949acb4346754ae47fb07424076a3cd0.tar.gz
DotNetOpenAuth-b6f7a18b949acb4346754ae47fb07424076a3cd0.tar.bz2
First pass at dividing DotNetOpenAuth features into separate assemblies.
Nothing compiles at this point.
Diffstat (limited to 'src/DotNetOpenAuth.OAuth/OAuth/Messages')
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/AccessProtectedResourceRequest.cs72
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenRequest.cs62
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenResponse.cs62
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenContainingMessage.cs17
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenSecretContainingMessage.cs17
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBase.cs281
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/OAuth Messages.cd164
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/SignedMessageBase.cs197
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenRequest.cs44
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenResponse.cs100
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationRequest.cs82
-rw-r--r--src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationResponse.cs56
12 files changed, 1154 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/AccessProtectedResourceRequest.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
new file mode 100644
index 0000000..f3231f0
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
@@ -0,0 +1,72 @@
+//-----------------------------------------------------------------------
+// <copyright file="AccessProtectedResourceRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A message attached to a request for protected resources that provides the necessary
+ /// credentials to be granted access to those resources.
+ /// </summary>
+ public class AccessProtectedResourceRequest : SignedMessageBase, ITokenContainingMessage, IMessageWithBinaryData {
+ /// <summary>
+ /// A store for the binary data that is carried in the message.
+ /// </summary>
+ private List<MultipartPostPart> binaryData = new List<MultipartPostPart>();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AccessProtectedResourceRequest"/> class.
+ /// </summary>
+ /// <param name="serviceProvider">The URI of the Service Provider endpoint to send this message to.</param>
+ /// <param name="version">The OAuth version.</param>
+ protected internal AccessProtectedResourceRequest(MessageReceivingEndpoint serviceProvider, Version version)
+ : base(MessageTransport.Direct, serviceProvider, version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Token.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This property IS accessible by a different name.")]
+ string ITokenContainingMessage.Token {
+ get { return this.AccessToken; }
+ set { this.AccessToken = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Access Token.
+ /// </summary>
+ /// <remarks>
+ /// In addition to just allowing OAuth to verify a valid message,
+ /// this property is useful on the Service Provider to verify that the access token
+ /// has proper authorization for the resource being requested, and to know the
+ /// context around which user provided the authorization.
+ /// </remarks>
+ [MessagePart("oauth_token", IsRequired = true)]
+ public string AccessToken { get; set; }
+
+ #region IMessageWithBinaryData Members
+
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ public IList<MultipartPostPart> BinaryData {
+ get { return this.binaryData; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ public bool SendAsMultipart {
+ get { return this.HttpMethod == "POST" && this.BinaryData.Count > 0; }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenRequest.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenRequest.cs
new file mode 100644
index 0000000..02c6c1d
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenRequest.cs
@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------
+// <copyright file="AuthorizedTokenRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Globalization;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A direct message sent by the Consumer to exchange an authorized Request Token
+ /// for an Access Token and Token Secret.
+ /// </summary>
+ /// <remarks>
+ /// The class is sealed because the OAuth spec forbids adding parameters to this message.
+ /// </remarks>
+ public sealed class AuthorizedTokenRequest : SignedMessageBase, ITokenContainingMessage {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthorizedTokenRequest"/> class.
+ /// </summary>
+ /// <param name="serviceProvider">The URI of the Service Provider endpoint to send this message to.</param>
+ /// <param name="version">The OAuth version.</param>
+ internal AuthorizedTokenRequest(MessageReceivingEndpoint serviceProvider, Version version)
+ : base(MessageTransport.Direct, serviceProvider, version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Token.
+ /// </summary>
+ string ITokenContainingMessage.Token {
+ get { return this.RequestToken; }
+ set { this.RequestToken = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the verification code received by the Consumer from the Service Provider
+ /// in the <see cref="UserAuthorizationResponse.VerificationCode"/> property.
+ /// </summary>
+ [MessagePart("oauth_verifier", IsRequired = true, AllowEmpty = false, MinVersion = Protocol.V10aVersion)]
+ public string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets the authorized Request Token used to obtain authorization.
+ /// </summary>
+ [MessagePart("oauth_token", IsRequired = true)]
+ internal string RequestToken { get; set; }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ protected override void EnsureValidMessage() {
+ base.EnsureValidMessage();
+
+ if (this.ExtraData.Count > 0) {
+ throw new ProtocolException(string.Format(CultureInfo.CurrentCulture, OAuthStrings.MessageNotAllowedExtraParameters, GetType().Name));
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenResponse.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenResponse.cs
new file mode 100644
index 0000000..0b14819
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/AuthorizedTokenResponse.cs
@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------
+// <copyright file="AuthorizedTokenResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A direct message sent from Service Provider to Consumer in response to
+ /// a Consumer's <see cref="AuthorizedTokenRequest"/> request.
+ /// </summary>
+ public class AuthorizedTokenResponse : MessageBase, ITokenSecretContainingMessage {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AuthorizedTokenResponse"/> class.
+ /// </summary>
+ /// <param name="originatingRequest">The originating request.</param>
+ protected internal AuthorizedTokenResponse(AuthorizedTokenRequest originatingRequest)
+ : base(MessageProtections.None, originatingRequest, originatingRequest.Version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Access Token assigned by the Service Provider.
+ /// </summary>
+ [MessagePart("oauth_token", IsRequired = true)]
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This property IS accessible by a different name.")]
+ string ITokenContainingMessage.Token {
+ get { return this.AccessToken; }
+ set { this.AccessToken = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token secret.
+ /// </summary>
+ string ITokenSecretContainingMessage.TokenSecret {
+ get { return this.TokenSecret; }
+ set { this.TokenSecret = value; }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-OAuth parameters that will be included in the message.
+ /// </summary>
+ public new IDictionary<string, string> ExtraData {
+ get { return base.ExtraData; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Token Secret.
+ /// </summary>
+ [MessagePart("oauth_token_secret", IsRequired = true)]
+ protected internal string TokenSecret { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenContainingMessage.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenContainingMessage.cs
new file mode 100644
index 0000000..832b754
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenContainingMessage.cs
@@ -0,0 +1,17 @@
+//-----------------------------------------------------------------------
+// <copyright file="ITokenContainingMessage.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ /// <summary>
+ /// An interface implemented by all OAuth messages that have a request or access token property.
+ /// </summary>
+ public interface ITokenContainingMessage {
+ /// <summary>
+ /// Gets or sets the Request or Access Token.
+ /// </summary>
+ string Token { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenSecretContainingMessage.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenSecretContainingMessage.cs
new file mode 100644
index 0000000..95809ec
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/ITokenSecretContainingMessage.cs
@@ -0,0 +1,17 @@
+//-----------------------------------------------------------------------
+// <copyright file="ITokenSecretContainingMessage.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ /// <summary>
+ /// An interface implemented by all OAuth messages that have a request or access token and secret properties.
+ /// </summary>
+ public interface ITokenSecretContainingMessage : ITokenContainingMessage {
+ /// <summary>
+ /// Gets or sets the Request or Access Token secret.
+ /// </summary>
+ string TokenSecret { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBase.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBase.cs
new file mode 100644
index 0000000..1a0ba23
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/MessageBase.cs
@@ -0,0 +1,281 @@
+//-----------------------------------------------------------------------
+// <copyright file="MessageBase.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Text;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Reflection;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ /// <summary>
+ /// A base class for all OAuth messages.
+ /// </summary>
+ [Serializable]
+ public abstract class MessageBase : IDirectedProtocolMessage, IDirectResponseProtocolMessage {
+ /// <summary>
+ /// A store for extra name/value data pairs that are attached to this message.
+ /// </summary>
+ private Dictionary<string, string> extraData = new Dictionary<string, string>();
+
+ /// <summary>
+ /// Gets a value indicating whether signing this message is required.
+ /// </summary>
+ private MessageProtections protectionRequired;
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ private MessageTransport transport;
+
+ /// <summary>
+ /// The URI to the remote endpoint to send this message to.
+ /// </summary>
+ private MessageReceivingEndpoint recipient;
+
+ /// <summary>
+ /// Backing store for the <see cref="OriginatingRequest"/> properties.
+ /// </summary>
+ private IDirectedProtocolMessage originatingRequest;
+
+ /// <summary>
+ /// Backing store for the <see cref="Incoming"/> properties.
+ /// </summary>
+ private bool incoming;
+
+#if DEBUG
+ /// <summary>
+ /// Initializes static members of the <see cref="MessageBase"/> class.
+ /// </summary>
+ static MessageBase() {
+ LowSecurityMode = true;
+ }
+#endif
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MessageBase"/> class for direct response messages.
+ /// </summary>
+ /// <param name="protectionRequired">The level of protection the message requires.</param>
+ /// <param name="originatingRequest">The request that asked for this direct response.</param>
+ /// <param name="version">The OAuth version.</param>
+ protected MessageBase(MessageProtections protectionRequired, IDirectedProtocolMessage originatingRequest, Version version) {
+ Contract.Requires<ArgumentNullException>(originatingRequest != null);
+ Contract.Requires<ArgumentNullException>(version != null);
+
+ this.protectionRequired = protectionRequired;
+ this.transport = MessageTransport.Direct;
+ this.originatingRequest = originatingRequest;
+ this.Version = version;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MessageBase"/> class for direct requests or indirect messages.
+ /// </summary>
+ /// <param name="protectionRequired">The level of protection the message requires.</param>
+ /// <param name="transport">A value indicating whether this message requires a direct or indirect transport.</param>
+ /// <param name="recipient">The URI that a directed message will be delivered to.</param>
+ /// <param name="version">The OAuth version.</param>
+ protected MessageBase(MessageProtections protectionRequired, MessageTransport transport, MessageReceivingEndpoint recipient, Version version) {
+ Contract.Requires<ArgumentNullException>(recipient != null);
+ Contract.Requires<ArgumentNullException>(version != null);
+
+ this.protectionRequired = protectionRequired;
+ this.transport = transport;
+ this.recipient = recipient;
+ this.Version = version;
+ }
+
+ #region IProtocolMessage Properties
+
+ /// <summary>
+ /// Gets the version of the protocol this message is prepared to implement.
+ /// </summary>
+ Version IMessage.Version {
+ get { return this.Version; }
+ }
+
+ /// <summary>
+ /// Gets the level of protection this message requires.
+ /// </summary>
+ MessageProtections IProtocolMessage.RequiredProtection {
+ get { return this.RequiredProtection; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ MessageTransport IProtocolMessage.Transport {
+ get { return this.Transport; }
+ }
+
+ /// <summary>
+ /// Gets the dictionary of additional name/value fields tacked on to this message.
+ /// </summary>
+ IDictionary<string, string> IMessage.ExtraData {
+ get { return this.ExtraData; }
+ }
+
+ #endregion
+
+ #region IDirectedProtocolMessage Members
+
+ /// <summary>
+ /// Gets the URI to the Service Provider endpoint to send this message to.
+ /// </summary>
+ Uri IDirectedProtocolMessage.Recipient {
+ get { return this.recipient != null ? this.recipient.Location : null; }
+ }
+
+ /// <summary>
+ /// Gets the preferred method of transport for the message.
+ /// </summary>
+ HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods {
+ get { return this.HttpMethods; }
+ }
+
+ #endregion
+
+ #region IDirectResponseProtocolMessage Members
+
+ /// <summary>
+ /// Gets the originating request message that caused this response to be formed.
+ /// </summary>
+ IDirectedProtocolMessage IDirectResponseProtocolMessage.OriginatingRequest {
+ get { return this.originatingRequest; }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets a value indicating whether security sensitive strings are
+ /// emitted from the ToString() method.
+ /// </summary>
+ internal static bool LowSecurityMode { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether this message was deserialized as an incoming message.
+ /// </summary>
+ protected internal bool Incoming {
+ get { return this.incoming; }
+ }
+
+ /// <summary>
+ /// Gets the version of the protocol this message is prepared to implement.
+ /// </summary>
+ protected internal Version Version { get; private set; }
+
+ /// <summary>
+ /// Gets the level of protection this message requires.
+ /// </summary>
+ protected MessageProtections RequiredProtection {
+ get { return this.protectionRequired; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ protected MessageTransport Transport {
+ get { return this.transport; }
+ }
+
+ /// <summary>
+ /// Gets the dictionary of additional name/value fields tacked on to this message.
+ /// </summary>
+ protected IDictionary<string, string> ExtraData {
+ get { return this.extraData; }
+ }
+
+ /// <summary>
+ /// Gets the preferred method of transport for the message.
+ /// </summary>
+ protected HttpDeliveryMethods HttpMethods {
+ get { return this.recipient != null ? this.recipient.AllowedMethods : HttpDeliveryMethods.None; }
+ }
+
+ /// <summary>
+ /// Gets or sets the URI to the Service Provider endpoint to send this message to.
+ /// </summary>
+ protected Uri Recipient {
+ get {
+ return this.recipient != null ? this.recipient.Location : null;
+ }
+
+ set {
+ if (this.recipient != null) {
+ this.recipient = new MessageReceivingEndpoint(value, this.recipient.AllowedMethods);
+ } else if (value != null) {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the originating request message that caused this response to be formed.
+ /// </summary>
+ protected IDirectedProtocolMessage OriginatingRequest {
+ get { return this.originatingRequest; }
+ }
+
+ #region IProtocolMessage Methods
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ void IMessage.EnsureValidMessage() {
+ this.EnsureValidMessage();
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Returns a human-friendly string describing the message and all serializable properties.
+ /// </summary>
+ /// <param name="channel">The channel that will carry this message.</param>
+ /// <returns>
+ /// The string representation of this object.
+ /// </returns>
+ internal virtual string ToString(Channel channel) {
+ Contract.Requires<ArgumentNullException>(channel != null);
+
+ StringBuilder builder = new StringBuilder();
+ builder.AppendFormat(CultureInfo.InvariantCulture, "{0} message", GetType().Name);
+ if (this.recipient != null) {
+ builder.AppendFormat(CultureInfo.InvariantCulture, " as {0} to {1}", this.recipient.AllowedMethods, this.recipient.Location);
+ }
+ builder.AppendLine();
+ MessageDictionary dictionary = channel.MessageDescriptions.GetAccessor(this);
+ foreach (var pair in dictionary) {
+ string value = pair.Value;
+ if (pair.Key == "oauth_signature" && !LowSecurityMode) {
+ value = "xxxxxxxxxxxxx (not shown)";
+ }
+ builder.Append('\t');
+ builder.Append(pair.Key);
+ builder.Append(": ");
+ builder.AppendLine(value);
+ }
+
+ return builder.ToString();
+ }
+
+ /// <summary>
+ /// Sets a flag indicating that this message is received (as opposed to sent).
+ /// </summary>
+ internal void SetAsIncoming() {
+ this.incoming = true;
+ }
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ protected virtual void EnsureValidMessage() { }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/OAuth Messages.cd b/src/DotNetOpenAuth.OAuth/OAuth/Messages/OAuth Messages.cd
new file mode 100644
index 0000000..f5526d2
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/OAuth Messages.cd
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ClassDiagram MajorVersion="1" MinorVersion="1" GroupingSetting="Access">
+ <Comment CommentText="Messages from Service Provider">
+ <Position X="7.912" Y="0.715" Height="0.291" Width="2.02" />
+ </Comment>
+ <Comment CommentText="Messages from Consumer">
+ <Position X="4.36" Y="0.683" Height="0.291" Width="2.02" />
+ </Comment>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest">
+ <Position X="4.25" Y="1" Width="3" />
+ <Compartments>
+ <Compartment Name="Internal" Collapsed="true" />
+ <Compartment Name="Private" Collapsed="true" />
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\UnauthorizedTokenRequest.cs</FileName>
+ </TypeIdentifier>
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenResponse">
+ <Position X="7.5" Y="1.5" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ <Property Name="ITokenSecretContainingMessage.TokenSecret" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACAAAAAAAAAAEAAAAAAIAAIAAAIAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\UnauthorizedTokenResponse.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.SignedMessageBase">
+ <Position X="0.5" Y="1.5" Width="3.5" />
+ <Members>
+ <Property Name="ITamperResistantOAuthMessage.ConsumerSecret" Hidden="true" />
+ <Property Name="ITamperResistantOAuthMessage.HttpMethod" Hidden="true" />
+ <Property Name="ITamperResistantOAuthMessage.SignatureMethod" Hidden="true" />
+ <Property Name="ITamperResistantOAuthMessage.TokenSecret" Hidden="true" />
+ <Property Name="ITamperResistantProtocolMessage.Signature" Hidden="true" />
+ </Members>
+ <TypeIdentifier>
+ <HashCode>AIAAFAAAAIAAAAACgICAAgAAAgAAIAQAAAEAIgAQAAE=</HashCode>
+ <FileName>OAuth\Messages\SignedMessageBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.UserAuthorizationRequest">
+ <Position X="4.25" Y="3" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACAAAAAAAAAAAAAAAAAIAAAAAAIAAAAAAAQAA=</HashCode>
+ <FileName>OAuth\Messages\UserAuthorizationRequest.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.UserAuthorizationResponse">
+ <Position X="7.5" Y="4.5" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\UserAuthorizationResponse.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.AuthorizedTokenResponse">
+ <Position X="7.5" Y="6.25" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ <Property Name="ITokenSecretContainingMessage.TokenSecret" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACAAAAAAAAAAAAAAAAEAAAIAAAIAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\AuthorizedTokenResponse.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.AuthorizedTokenRequest">
+ <Position X="4.25" Y="5.5" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Methods" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACQAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\AuthorizedTokenRequest.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.AccessProtectedResourceRequest">
+ <Position X="4.25" Y="7.75" Width="3" />
+ <Members>
+ <Property Name="ITokenContainingMessage.Token" Hidden="true" />
+ </Members>
+ <TypeIdentifier>
+ <HashCode>AAAAAAACAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\AccessProtectedResourceRequest.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Class Name="DotNetOpenAuth.OAuth.Messages.MessageBase">
+ <Position X="11" Y="1" Width="3.5" />
+ <Members>
+ <Field Name="extraData" Hidden="true" />
+ <Property Name="IDirectedProtocolMessage.Recipient" Hidden="true" />
+ <Method Name="IMessage.EnsureValidMessage" Hidden="true" />
+ <Property Name="IMessage.ExtraData" Hidden="true" />
+ <Property Name="IMessage.Version" Hidden="true" />
+ <Property Name="IProtocolMessage.RequiredProtection" Hidden="true" />
+ <Property Name="IProtocolMessage.Transport" Hidden="true" />
+ <Field Name="protectionRequired" Hidden="true" />
+ <Field Name="recipient" Hidden="true" />
+ <Field Name="transport" Hidden="true" />
+ </Members>
+ <Compartments>
+ <Compartment Name="Fields" Collapsed="true" />
+ </Compartments>
+ <TypeIdentifier>
+ <HashCode>ICAMAAQAYAAAgAkEAIAIAAYACgAEYBAAIECBACAAAAA=</HashCode>
+ <FileName>OAuth\Messages\MessageBase.cs</FileName>
+ </TypeIdentifier>
+ <Lollipop Position="0.2" />
+ </Class>
+ <Interface Name="DotNetOpenAuth.ChannelElements.ITamperResistantOAuthMessage">
+ <Position X="11.25" Y="5.25" Width="2.5" />
+ <TypeIdentifier>
+ <HashCode>AIAAAAAAAAAAAAAAAIAAAgAAAAAAIAQAAAAAAAAAAAA=</HashCode>
+ <FileName>ChannelElements\ITamperResistantOAuthMessage.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="DotNetOpenAuth.OAuth.Messages.ITokenContainingMessage">
+ <Position X="1" Y="6" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA=</HashCode>
+ <FileName>OAuth\Messages\ITokenContainingMessage.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Interface Name="DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage">
+ <Position X="1" Y="7.5" Width="2" />
+ <TypeIdentifier>
+ <HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAA=</HashCode>
+ <FileName>OAuth\Messages\ITokenSecretContainingMessage.cs</FileName>
+ </TypeIdentifier>
+ </Interface>
+ <Font Name="Segoe UI" Size="9" />
+</ClassDiagram> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/SignedMessageBase.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/SignedMessageBase.cs
new file mode 100644
index 0000000..6084fc0
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/SignedMessageBase.cs
@@ -0,0 +1,197 @@
+//-----------------------------------------------------------------------
+// <copyright file="SignedMessageBase.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Messaging.Bindings;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ /// <summary>
+ /// A base class for all signed OAuth messages.
+ /// </summary>
+ public class SignedMessageBase : MessageBase, ITamperResistantOAuthMessage, IExpiringProtocolMessage, IReplayProtectedProtocolMessage {
+ /// <summary>
+ /// The reference date and time for calculating time stamps.
+ /// </summary>
+ private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ /// <summary>
+ /// The number of seconds since 1/1/1970, consistent with the OAuth timestamp requirement.
+ /// </summary>
+ [MessagePart("oauth_timestamp", IsRequired = true)]
+ private long timestamp;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SignedMessageBase"/> class.
+ /// </summary>
+ /// <param name="transport">A value indicating whether this message requires a direct or indirect transport.</param>
+ /// <param name="recipient">The URI that a directed message will be delivered to.</param>
+ /// <param name="version">The OAuth version.</param>
+ internal SignedMessageBase(MessageTransport transport, MessageReceivingEndpoint recipient, Version version)
+ : base(MessageProtections.All, transport, recipient, version) {
+ ITamperResistantOAuthMessage self = (ITamperResistantOAuthMessage)this;
+ HttpDeliveryMethods methods = ((IDirectedProtocolMessage)this).HttpMethods;
+ self.HttpMethod = MessagingUtilities.GetHttpVerb(methods);
+ }
+
+ #region ITamperResistantOAuthMessage Members
+
+ /// <summary>
+ /// Gets or sets the signature method used to sign the request.
+ /// </summary>
+ string ITamperResistantOAuthMessage.SignatureMethod {
+ get { return this.SignatureMethod; }
+ set { this.SignatureMethod = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Token Secret used to sign the message.
+ /// </summary>
+ string ITamperResistantOAuthMessage.TokenSecret {
+ get { return this.TokenSecret; }
+ set { this.TokenSecret = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Consumer key.
+ /// </summary>
+ [MessagePart("oauth_consumer_key", IsRequired = true)]
+ public string ConsumerKey { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Consumer Secret used to sign the message.
+ /// </summary>
+ string ITamperResistantOAuthMessage.ConsumerSecret {
+ get { return this.ConsumerSecret; }
+ set { this.ConsumerSecret = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the HTTP method that will be used to transmit the message.
+ /// </summary>
+ string ITamperResistantOAuthMessage.HttpMethod {
+ get { return this.HttpMethod; }
+ set { this.HttpMethod = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the URI to the Service Provider endpoint to send this message to.
+ /// </summary>
+ Uri ITamperResistantOAuthMessage.Recipient {
+ get { return this.Recipient; }
+ set { this.Recipient = value; }
+ }
+
+ #endregion
+
+ #region ITamperResistantProtocolMessage Members
+
+ /// <summary>
+ /// Gets or sets the message signature.
+ /// </summary>
+ string ITamperResistantProtocolMessage.Signature {
+ get { return this.Signature; }
+ set { this.Signature = value; }
+ }
+
+ #endregion
+
+ #region IExpiringProtocolMessage Members
+
+ /// <summary>
+ /// Gets or sets the OAuth timestamp of the message.
+ /// </summary>
+ DateTime IExpiringProtocolMessage.UtcCreationDate {
+ get { return epoch + TimeSpan.FromSeconds(this.timestamp); }
+ set { this.timestamp = (long)(value - epoch).TotalSeconds; }
+ }
+
+ #endregion
+
+ #region IReplayProtectedProtocolMessage Members
+
+ /// <summary>
+ /// Gets the context within which the nonce must be unique.
+ /// </summary>
+ /// <value>The consumer key.</value>
+ string IReplayProtectedProtocolMessage.NonceContext {
+ get { return this.ConsumerKey; }
+ }
+
+ /// <summary>
+ /// Gets or sets the message nonce used for replay detection.
+ /// </summary>
+ [MessagePart("oauth_nonce", IsRequired = true)]
+ string IReplayProtectedProtocolMessage.Nonce { get; set; }
+
+ #endregion
+
+ #region IMessageOriginalPayload Members
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ IDictionary<string, string> IMessageOriginalPayload.OriginalPayload {
+ get { return this.OriginalPayload; }
+ set { this.OriginalPayload = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")]
+ protected IDictionary<string, string> OriginalPayload { get; set; }
+
+ #endregion
+
+ /// <summary>
+ /// Gets or sets the signature method used to sign the request.
+ /// </summary>
+ [MessagePart("oauth_signature_method", IsRequired = true)]
+ protected string SignatureMethod { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Token Secret used to sign the message.
+ /// </summary>
+ protected string TokenSecret { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Consumer Secret used to sign the message.
+ /// </summary>
+ protected string ConsumerSecret { get; set; }
+
+ /// <summary>
+ /// Gets or sets the HTTP method that will be used to transmit the message.
+ /// </summary>
+ protected string HttpMethod { get; set; }
+
+ /// <summary>
+ /// Gets or sets the message signature.
+ /// </summary>
+ [MessagePart("oauth_signature", IsRequired = true)]
+ protected string Signature { get; set; }
+
+ /// <summary>
+ /// Gets or sets the version of the protocol this message was created with.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Accessed via reflection.")]
+ [MessagePart("oauth_version", IsRequired = false)]
+ private string OAuthVersion {
+ get {
+ return Protocol.Lookup(Version).PublishedVersion;
+ }
+
+ set {
+ if (value != this.OAuthVersion) {
+ throw new ArgumentOutOfRangeException("value");
+ }
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenRequest.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenRequest.cs
new file mode 100644
index 0000000..9214d91
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenRequest.cs
@@ -0,0 +1,44 @@
+//-----------------------------------------------------------------------
+// <copyright file="UnauthorizedTokenRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth.ChannelElements;
+
+ /// <summary>
+ /// A direct message sent from Consumer to Service Provider to request a Request Token.
+ /// </summary>
+ public class UnauthorizedTokenRequest : SignedMessageBase {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UnauthorizedTokenRequest"/> class.
+ /// </summary>
+ /// <param name="serviceProvider">The URI of the Service Provider endpoint to send this message to.</param>
+ /// <param name="version">The OAuth version.</param>
+ protected internal UnauthorizedTokenRequest(MessageReceivingEndpoint serviceProvider, Version version)
+ : base(MessageTransport.Direct, serviceProvider, version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the absolute URL to which the Service Provider will redirect the
+ /// User back when the Obtaining User Authorization step is completed.
+ /// </summary>
+ /// <value>
+ /// The callback URL; or <c>null</c> if the Consumer is unable to receive
+ /// callbacks or a callback URL has been established via other means.
+ /// </value>
+ [MessagePart("oauth_callback", IsRequired = true, AllowEmpty = false, MinVersion = Protocol.V10aVersion, Encoder = typeof(UriOrOobEncoding))]
+ public Uri Callback { get; set; }
+
+ /// <summary>
+ /// Gets the extra, non-OAuth parameters that will be included in the message.
+ /// </summary>
+ public new IDictionary<string, string> ExtraData {
+ get { return base.ExtraData; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenResponse.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenResponse.cs
new file mode 100644
index 0000000..0be9f63
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UnauthorizedTokenResponse.cs
@@ -0,0 +1,100 @@
+//-----------------------------------------------------------------------
+// <copyright file="UnauthorizedTokenResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A direct message sent from Service Provider to Consumer in response to
+ /// a Consumer's <see cref="UnauthorizedTokenRequest"/> request.
+ /// </summary>
+ public class UnauthorizedTokenResponse : MessageBase, ITokenSecretContainingMessage {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UnauthorizedTokenResponse"/> class.
+ /// </summary>
+ /// <param name="requestMessage">The unauthorized request token message that this message is being generated in response to.</param>
+ /// <param name="requestToken">The request token.</param>
+ /// <param name="tokenSecret">The token secret.</param>
+ /// <remarks>
+ /// This constructor is used by the Service Provider to send the message.
+ /// </remarks>
+ protected internal UnauthorizedTokenResponse(UnauthorizedTokenRequest requestMessage, string requestToken, string tokenSecret)
+ : this(requestMessage, requestMessage.Version) {
+ Contract.Requires<ArgumentNullException>(requestToken != null);
+ Contract.Requires<ArgumentNullException>(tokenSecret != null);
+
+ this.RequestToken = requestToken;
+ this.TokenSecret = tokenSecret;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UnauthorizedTokenResponse"/> class.
+ /// </summary>
+ /// <param name="originatingRequest">The originating request.</param>
+ /// <param name="version">The OAuth version.</param>
+ /// <remarks>This constructor is used by the consumer to deserialize the message.</remarks>
+ protected internal UnauthorizedTokenResponse(UnauthorizedTokenRequest originatingRequest, Version version)
+ : base(MessageProtections.None, originatingRequest, version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This property IS accessible by a different name.")]
+ string ITokenContainingMessage.Token {
+ get { return this.RequestToken; }
+ set { this.RequestToken = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token secret.
+ /// </summary>
+ string ITokenSecretContainingMessage.TokenSecret {
+ get { return this.TokenSecret; }
+ set { this.TokenSecret = value; }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-OAuth parameters that will be included in the message.
+ /// </summary>
+ public new IDictionary<string, string> ExtraData {
+ get { return base.ExtraData; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Request Token.
+ /// </summary>
+ [MessagePart("oauth_token", IsRequired = true)]
+ internal string RequestToken { get; set; }
+
+ /// <summary>
+ /// Gets the original request for an unauthorized token.
+ /// </summary>
+ internal UnauthorizedTokenRequest RequestMessage {
+ get { return (UnauthorizedTokenRequest)this.OriginatingRequest; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Token Secret.
+ /// </summary>
+ [MessagePart("oauth_token_secret", IsRequired = true)]
+ protected internal string TokenSecret { get; set; }
+
+ /// <summary>
+ /// Gets a value indicating whether the Service Provider recognized the callback parameter in the request.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Message serialization invoked.")]
+ [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Message parts must be instance members.")]
+ [MessagePart("oauth_callback_confirmed", IsRequired = true, MinVersion = Protocol.V10aVersion)]
+ private bool CallbackConfirmed {
+ get { return true; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationRequest.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationRequest.cs
new file mode 100644
index 0000000..a5823bb
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationRequest.cs
@@ -0,0 +1,82 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserAuthorizationRequest.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A message used to redirect the user from a Consumer to a Service Provider's web site
+ /// so the Service Provider can ask the user to authorize the Consumer's access to some
+ /// protected resource(s).
+ /// </summary>
+ [Serializable]
+ public class UserAuthorizationRequest : MessageBase, ITokenContainingMessage {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserAuthorizationRequest"/> class.
+ /// </summary>
+ /// <param name="serviceProvider">The URI of the Service Provider endpoint to send this message to.</param>
+ /// <param name="requestToken">The request token.</param>
+ /// <param name="version">The OAuth version.</param>
+ internal UserAuthorizationRequest(MessageReceivingEndpoint serviceProvider, string requestToken, Version version)
+ : this(serviceProvider, version) {
+ this.RequestToken = requestToken;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserAuthorizationRequest"/> class.
+ /// </summary>
+ /// <param name="serviceProvider">The URI of the Service Provider endpoint to send this message to.</param>
+ /// <param name="version">The OAuth version.</param>
+ internal UserAuthorizationRequest(MessageReceivingEndpoint serviceProvider, Version version)
+ : base(MessageProtections.None, MessageTransport.Indirect, serviceProvider, version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Justification = "This property IS accessible by a different name.")]
+ string ITokenContainingMessage.Token {
+ get { return this.RequestToken; }
+ set { this.RequestToken = value; }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-OAuth parameters that will be included in the message.
+ /// </summary>
+ public new IDictionary<string, string> ExtraData {
+ get { return base.ExtraData; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a safe OAuth authorization request.
+ /// </summary>
+ /// <value><c>true</c> if the Consumer is using OAuth 1.0a or later; otherwise, <c>false</c>.</value>
+ public bool IsUnsafeRequest {
+ get { return this.Version < Protocol.V10a.Version; }
+ }
+
+ /// <summary>
+ /// Gets or sets the Request Token obtained in the previous step.
+ /// </summary>
+ /// <remarks>
+ /// The Service Provider MAY declare this parameter as REQUIRED, or
+ /// accept requests to the User Authorization URL without it, in which
+ /// case it will prompt the User to enter it manually.
+ /// </remarks>
+ [MessagePart("oauth_token", IsRequired = false)]
+ internal string RequestToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets a URL the Service Provider will use to redirect the User back
+ /// to the Consumer when Obtaining User Authorization is complete. Optional.
+ /// </summary>
+ [MessagePart("oauth_callback", IsRequired = false, MaxVersion = "1.0")]
+ internal Uri Callback { get; set; }
+ }
+}
diff --git a/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationResponse.cs b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationResponse.cs
new file mode 100644
index 0000000..73fddc7
--- /dev/null
+++ b/src/DotNetOpenAuth.OAuth/OAuth/Messages/UserAuthorizationResponse.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="UserAuthorizationResponse.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OAuth.Messages {
+ using System;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// A message used to redirect the user from a Service Provider to a Consumer's web site.
+ /// </summary>
+ /// <remarks>
+ /// The class is sealed because extra parameters are determined by the callback URI provided by the Consumer.
+ /// </remarks>
+ [Serializable]
+ public sealed class UserAuthorizationResponse : MessageBase, ITokenContainingMessage {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UserAuthorizationResponse"/> class.
+ /// </summary>
+ /// <param name="consumer">The URI of the Consumer endpoint to send this message to.</param>
+ /// <param name="version">The OAuth version.</param>
+ internal UserAuthorizationResponse(Uri consumer, Version version)
+ : base(MessageProtections.None, MessageTransport.Indirect, new MessageReceivingEndpoint(consumer, HttpDeliveryMethods.GetRequest), version) {
+ }
+
+ /// <summary>
+ /// Gets or sets the Request or Access Token.
+ /// </summary>
+ string ITokenContainingMessage.Token {
+ get { return this.RequestToken; }
+ set { this.RequestToken = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the verification code that must accompany the request to exchange the
+ /// authorized request token for an access token.
+ /// </summary>
+ /// <value>An unguessable value passed to the Consumer via the User and REQUIRED to complete the process.</value>
+ /// <remarks>
+ /// If the Consumer did not provide a callback URL, the Service Provider SHOULD display the value of the
+ /// verification code, and instruct the User to manually inform the Consumer that authorization is
+ /// completed. If the Service Provider knows a Consumer to be running on a mobile device or set-top box,
+ /// the Service Provider SHOULD ensure that the verifier value is suitable for manual entry.
+ /// </remarks>
+ [MessagePart("oauth_verifier", IsRequired = true, AllowEmpty = false, MinVersion = Protocol.V10aVersion)]
+ public string VerificationCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Request Token.
+ /// </summary>
+ [MessagePart("oauth_token", IsRequired = true)]
+ internal string RequestToken { get; set; }
+ }
+}