summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2008-11-01 20:57:22 -0700
committerAndrew <andrewarnott@gmail.com>2008-11-01 20:57:22 -0700
commite3b0e50c390de98c9aadcf10451fd17611ad431b (patch)
treef182aa5ee46b1dc3086b4ca0693b41ab84d03032
parentdb11b0a9fa4a304400ca1223427c3ca37f10004e (diff)
downloadDotNetOpenAuth-e3b0e50c390de98c9aadcf10451fd17611ad431b.zip
DotNetOpenAuth-e3b0e50c390de98c9aadcf10451fd17611ad431b.tar.gz
DotNetOpenAuth-e3b0e50c390de98c9aadcf10451fd17611ad431b.tar.bz2
Hugely refactored ServiceProvider and Consumer classes.
Messages are now exposed in the method signatures instead of raw Response instances.
-rw-r--r--samples/Consumer/GoogleAddressBook.aspx.cs3
-rw-r--r--samples/Consumer/SampleWcf.aspx.cs3
-rw-r--r--samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs2
-rw-r--r--samples/ServiceProvider/Members/Authorize.aspx.cs4
-rw-r--r--samples/ServiceProvider/OAuth.ashx6
-rw-r--r--src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs10
-rw-r--r--src/DotNetOAuth.Test/Scenarios/Coordinator.cs2
-rw-r--r--src/DotNetOAuth/ChannelElements/OAuthChannel.cs2
-rw-r--r--src/DotNetOAuth/ClassDiagram.cd13
-rw-r--r--src/DotNetOAuth/ConsumerBase.cs25
-rw-r--r--src/DotNetOAuth/DesktopConsumer.cs5
-rw-r--r--src/DotNetOAuth/DotNetOAuth.csproj1
-rw-r--r--src/DotNetOAuth/Messages/DirectUserToConsumerMessage.cs8
-rw-r--r--src/DotNetOAuth/Messages/GetAccessTokenMessage.cs13
-rw-r--r--src/DotNetOAuth/Messages/GrantRequestTokenMessage.cs15
-rw-r--r--src/DotNetOAuth/Messaging/Channel.cs20
-rw-r--r--src/DotNetOAuth/Messaging/ChannelEventArgs.cs16
-rw-r--r--src/DotNetOAuth/ServiceProvider.cs161
-rw-r--r--src/DotNetOAuth/Strings.Designer.cs9
-rw-r--r--src/DotNetOAuth/Strings.resx3
-rw-r--r--src/DotNetOAuth/WebConsumer.cs12
21 files changed, 222 insertions, 111 deletions
diff --git a/samples/Consumer/GoogleAddressBook.aspx.cs b/samples/Consumer/GoogleAddressBook.aspx.cs
index 59d6187..29037d4 100644
--- a/samples/Consumer/GoogleAddressBook.aspx.cs
+++ b/samples/Consumer/GoogleAddressBook.aspx.cs
@@ -65,6 +65,7 @@ public partial class GoogleAddressBook : System.Web.UI.Page {
};
UriBuilder callback = new UriBuilder(new Uri(Request.Url, Request.RawUrl));
callback.Query = null;
- google.RequestUserAuthorization(callback.Uri, extraParameters, null).Send();
+ var response = google.PrepareRequestUserAuthorization(callback.Uri, extraParameters, null);
+ google.Channel.Send(response).Send();
}
}
diff --git a/samples/Consumer/SampleWcf.aspx.cs b/samples/Consumer/SampleWcf.aspx.cs
index 2164608..01afb43 100644
--- a/samples/Consumer/SampleWcf.aspx.cs
+++ b/samples/Consumer/SampleWcf.aspx.cs
@@ -40,7 +40,8 @@ public partial class SampleWcf : System.Web.UI.Page {
var requestParams = new Dictionary<string, string> {
{ "scope", scope },
};
- consumer.RequestUserAuthorization(callback.Uri, requestParams, null).Send();
+ var response = consumer.PrepareRequestUserAuthorization(callback.Uri, requestParams, null);
+ consumer.Channel.Send(response).Send();
}
protected void getNameButton_Click(object sender, EventArgs e) {
diff --git a/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs b/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
index 02118f8..9d2e3e9 100644
--- a/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
+++ b/samples/ServiceProvider/App_Code/OAuthAuthorizationManager.cs
@@ -19,7 +19,7 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager {
HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri;
ServiceProvider sp = Constants.CreateServiceProvider();
- var auth = sp.GetProtectedResourceAuthorization(httpDetails, requestUri);
+ var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri);
if (auth != null) {
var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken);
diff --git a/samples/ServiceProvider/Members/Authorize.aspx.cs b/samples/ServiceProvider/Members/Authorize.aspx.cs
index 676e5ce..9285df3 100644
--- a/samples/ServiceProvider/Members/Authorize.aspx.cs
+++ b/samples/ServiceProvider/Members/Authorize.aspx.cs
@@ -29,9 +29,9 @@ public partial class Authorize : System.Web.UI.Page {
multiView.ActiveViewIndex = 1;
ServiceProvider sp = new ServiceProvider(Constants.SelfDescription, Global.TokenManager);
- var response = sp.SendAuthorizationResponse(pending);
+ var response = sp.PrepareAuthorizationResponse(pending);
if (response != null) {
- response.Send();
+ sp.Channel.Send(response).Send();
}
}
diff --git a/samples/ServiceProvider/OAuth.ashx b/samples/ServiceProvider/OAuth.ashx
index 91a53f5..6de26ef 100644
--- a/samples/ServiceProvider/OAuth.ashx
+++ b/samples/ServiceProvider/OAuth.ashx
@@ -22,12 +22,14 @@ public class OAuth : IHttpHandler, IRequiresSessionState {
DirectUserToServiceProviderMessage requestAuth;
GetAccessTokenMessage requestAccessToken;
if ((requestToken = request as RequestScopedTokenMessage) != null) {
- sp.SendUnauthorizedTokenResponse(requestToken, null).Send();
+ var response = sp.PrepareUnauthorizedTokenMessage(requestToken);
+ sp.Channel.Send(response).Send();
} else if ((requestAuth = request as DirectUserToServiceProviderMessage) != null) {
Global.PendingOAuthAuthorization = requestAuth;
HttpContext.Current.Response.Redirect("~/Members/Authorize.aspx");
} else if ((requestAccessToken = request as GetAccessTokenMessage) != null) {
- sp.SendAccessToken(requestAccessToken, null).Send();
+ var response = sp.PrepareAccessTokenMessage(requestAccessToken);
+ sp.Channel.Send(response).Send();
} else {
throw new InvalidOperationException();
}
diff --git a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
index 71d0606..40cd023 100644
--- a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
+++ b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
@@ -35,7 +35,7 @@ namespace DotNetOAuth.Test {
consumerDescription,
serviceDescription,
consumer => {
- consumer.RequestUserAuthorization(new Uri("http://printer.example.com/request_token_ready"), null, null);
+ consumer.Channel.Send(consumer.PrepareRequestUserAuthorization(new Uri("http://printer.example.com/request_token_ready"), null, null)); // .Send() dropped because this is just a simulation
string accessToken = consumer.ProcessUserAuthorization().AccessToken;
var photoRequest = consumer.CreateAuthorizingMessage(accessPhotoEndpoint, accessToken);
Response protectedPhoto = ((CoordinatingOAuthChannel)consumer.Channel).RequestProtectedResource(photoRequest);
@@ -46,13 +46,13 @@ namespace DotNetOAuth.Test {
},
sp => {
var requestTokenMessage = sp.ReadTokenRequest();
- sp.SendUnauthorizedTokenResponse(requestTokenMessage, null);
+ sp.Channel.Send(sp.PrepareUnauthorizedTokenMessage(requestTokenMessage)); // .Send() dropped because this is just a simulation
var authRequest = sp.ReadAuthorizationRequest();
((InMemoryTokenManager)sp.TokenManager).AuthorizeRequestToken(authRequest.RequestToken);
- sp.SendAuthorizationResponse(authRequest);
+ sp.Channel.Send(sp.PrepareAuthorizationResponse(authRequest)); // .Send() dropped because this is just a simulation
var accessRequest = sp.ReadAccessTokenRequest();
- sp.SendAccessToken(accessRequest, null);
- string accessToken = sp.GetProtectedResourceAuthorization().AccessToken;
+ sp.Channel.Send(sp.PrepareAccessTokenMessage(accessRequest)); // .Send() dropped because this is just a simulation
+ string accessToken = sp.ReadProtectedResourceAuthorization().AccessToken;
((CoordinatingOAuthChannel)sp.Channel).SendDirectRawResponse(new Response {
ResponseStream = new MemoryStream(new byte[] { 0x33, 0x66 }),
Headers = new WebHeaderCollection {
diff --git a/src/DotNetOAuth.Test/Scenarios/Coordinator.cs b/src/DotNetOAuth.Test/Scenarios/Coordinator.cs
index f03e8d8..3058df9 100644
--- a/src/DotNetOAuth.Test/Scenarios/Coordinator.cs
+++ b/src/DotNetOAuth.Test/Scenarios/Coordinator.cs
@@ -69,7 +69,7 @@ namespace DotNetOAuth.Test.Scenarios {
// Prepare the Consumer and Service Provider objects
WebConsumer consumer = new WebConsumer(this.serviceDescription, consumerTokenManager) {
- Channel = consumerChannel,
+ OAuthChannel = consumerChannel,
ConsumerKey = this.consumerDescription.ConsumerKey,
};
ServiceProvider serviceProvider = new ServiceProvider(this.serviceDescription, serviceTokenManager) {
diff --git a/src/DotNetOAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOAuth/ChannelElements/OAuthChannel.cs
index 16e7006..7ac4527 100644
--- a/src/DotNetOAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOAuth/ChannelElements/OAuthChannel.cs
@@ -236,6 +236,8 @@ namespace DotNetOAuth.ChannelElements {
/// This method implements spec V1.0 section 5.3.
/// </remarks>
protected override Response SendDirectMessageResponse(IProtocolMessage response) {
+ if (response == null) throw new ArgumentNullException("response");
+
MessageSerializer serializer = MessageSerializer.Get(response.GetType());
var fields = serializer.Serialize(response);
string responseBody = MessagingUtilities.CreateQueryString(fields);
diff --git a/src/DotNetOAuth/ClassDiagram.cd b/src/DotNetOAuth/ClassDiagram.cd
index b32f08e..83bea98 100644
--- a/src/DotNetOAuth/ClassDiagram.cd
+++ b/src/DotNetOAuth/ClassDiagram.cd
@@ -2,8 +2,11 @@
<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="NameAndType">
<Class Name="DotNetOAuth.ServiceProvider">
<Position X="0.5" Y="0.5" Width="5.75" />
+ <Members>
+ <Field Name="channel" Hidden="true" />
+ </Members>
<TypeIdentifier>
- <HashCode>EAoAAAAgAAAAAAABCAAEAAAAAAAIAAEAAQAIAAAAAQA=</HashCode>
+ <HashCode>EAoAAAsgAAAAIAAAEAAAAAAAAAAIAAEAAQAIAAwAAAA=</HashCode>
<FileName>ServiceProvider.cs</FileName>
</TypeIdentifier>
</Class>
@@ -16,7 +19,7 @@
</TypeIdentifier>
</Class>
<Class Name="DotNetOAuth.ServiceProviderDescription">
- <Position X="1.25" Y="4.5" Width="4.75" />
+ <Position X="1.25" Y="5.25" Width="4.75" />
<Compartments>
<Compartment Name="Fields" Collapsed="true" />
</Compartments>
@@ -29,21 +32,21 @@
<Position X="6.5" Y="4.5" Width="4.75" />
<InheritanceLine Type="DotNetOAuth.ConsumerBase" FixedToPoint="true">
<Path>
- <Point X="11.375" Y="3.786" />
+ <Point X="11.375" Y="3.978" />
<Point X="11.375" Y="4.125" />
<Point X="8.125" Y="4.125" />
<Point X="8.125" Y="4.5" />
</Path>
</InheritanceLine>
<TypeIdentifier>
- <HashCode>AAAAAAAAAAAAEAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
+ <HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAA=</HashCode>
<FileName>WebConsumer.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DotNetOAuth.ConsumerBase">
<Position X="9" Y="0.5" Width="4.75" />
<TypeIdentifier>
- <HashCode>ACAAAAAgAAABEAAAAAAABgAAAAAIAAAAAQAAAAAAABA=</HashCode>
+ <HashCode>ACAAAAEgAAABAAAAAAAABgAAAAAIAAAAAQAAAAABABA=</HashCode>
<FileName>ConsumerBase.cs</FileName>
</TypeIdentifier>
</Class>
diff --git a/src/DotNetOAuth/ConsumerBase.cs b/src/DotNetOAuth/ConsumerBase.cs
index fbc7f31..405df3a 100644
--- a/src/DotNetOAuth/ConsumerBase.cs
+++ b/src/DotNetOAuth/ConsumerBase.cs
@@ -34,7 +34,7 @@ namespace DotNetOAuth {
this.WebRequestHandler = new StandardWebRequestHandler();
ITamperProtectionChannelBindingElement signingElement = serviceDescription.CreateTamperProtectionElement();
INonceStore store = new NonceMemoryStore(StandardExpirationBindingElement.DefaultMaximumMessageAge);
- this.Channel = new OAuthChannel(signingElement, store, tokenManager, new OAuthConsumerMessageTypeProvider(), this.WebRequestHandler);
+ this.OAuthChannel = new OAuthChannel(signingElement, store, tokenManager, new OAuthConsumerMessageTypeProvider(), this.WebRequestHandler);
this.ServiceProvider = serviceDescription;
}
@@ -52,7 +52,7 @@ namespace DotNetOAuth {
/// Gets the persistence store for tokens and secrets.
/// </summary>
public ITokenManager TokenManager {
- get { return this.Channel.TokenManager; }
+ get { return this.OAuthChannel.TokenManager; }
}
/// <summary>
@@ -65,9 +65,16 @@ namespace DotNetOAuth {
internal IWebRequestHandler WebRequestHandler { get; set; }
/// <summary>
+ /// Gets the channel to use for sending/receiving messages.
+ /// </summary>
+ public Channel Channel {
+ get { return this.OAuthChannel; }
+ }
+
+ /// <summary>
/// Gets or sets the channel to use for sending/receiving messages.
/// </summary>
- internal OAuthChannel Channel { get; set; }
+ internal OAuthChannel OAuthChannel { get; set; }
/// <summary>
/// Creates a web request prepared with OAuth authorization
@@ -78,7 +85,7 @@ namespace DotNetOAuth {
/// <returns>The initialized WebRequest object.</returns>
public WebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint endpoint, string accessToken) {
IDirectedProtocolMessage message = this.CreateAuthorizingMessage(endpoint, accessToken);
- HttpWebRequest wr = this.Channel.InitializeRequest(message);
+ HttpWebRequest wr = this.OAuthChannel.InitializeRequest(message);
return wr;
}
@@ -92,13 +99,13 @@ namespace DotNetOAuth {
/// <exception cref="WebException">Thrown if the request fails for any reason after it is sent to the Service Provider.</exception>
public Response PrepareAuthorizedRequestAndSend(MessageReceivingEndpoint endpoint, string accessToken) {
IDirectedProtocolMessage message = this.CreateAuthorizingMessage(endpoint, accessToken);
- HttpWebRequest wr = this.Channel.InitializeRequest(message);
+ HttpWebRequest wr = this.OAuthChannel.InitializeRequest(message);
return this.WebRequestHandler.GetResponse(wr);
}
/// <summary>
- /// Begins an OAuth authorization request and redirects the user to the Service Provider
- /// to provide that authorization.
+ /// Prepares an OAuth message that begins an authorization request that will
+ /// redirect the user to the Service Provider to provide that authorization.
/// </summary>
/// <param name="callback">
/// An optional Consumer URL that the Service Provider should redirect the
@@ -109,7 +116,7 @@ namespace DotNetOAuth {
/// <param name="requestToken">The request token that must be exchanged for an access token after the user has provided authorization.</param>
/// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#", Justification = "Two results")]
- protected internal Response RequestUserAuthorization(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, out string requestToken) {
+ protected internal DirectUserToServiceProviderMessage PrepareRequestUserAuthorization(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, out string requestToken) {
// Obtain an unauthorized request token.
var token = new GetRequestTokenMessage(this.ServiceProvider.RequestTokenEndpoint) {
ConsumerKey = this.ConsumerKey,
@@ -125,7 +132,7 @@ namespace DotNetOAuth {
};
requestAuthorization.AddNonOAuthParameters(redirectParameters);
requestToken = requestAuthorization.RequestToken;
- return this.Channel.Send(requestAuthorization);
+ return requestAuthorization;
}
/// <summary>
diff --git a/src/DotNetOAuth/DesktopConsumer.cs b/src/DotNetOAuth/DesktopConsumer.cs
index fe293f4..7b9ef49 100644
--- a/src/DotNetOAuth/DesktopConsumer.cs
+++ b/src/DotNetOAuth/DesktopConsumer.cs
@@ -10,6 +10,7 @@ namespace DotNetOAuth {
using System.Diagnostics.CodeAnalysis;
using DotNetOAuth.ChannelElements;
using DotNetOAuth.Messages;
+ using DotNetOAuth.Messaging;
/// <summary>
/// Used by a desktop application to use OAuth to access the Service Provider on behalf of the User.
@@ -37,7 +38,9 @@ namespace DotNetOAuth {
/// <returns>The URL to open a browser window to allow the user to provide authorization.</returns>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "Two results")]
public Uri RequestUserAuthorization(IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters, out string requestToken) {
- return this.RequestUserAuthorization(null, requestParameters, redirectParameters, out requestToken).DirectUriRequest;
+ var message = this.PrepareRequestUserAuthorization(null, requestParameters, redirectParameters, out requestToken);
+ Response response = this.Channel.Send(message);
+ return response.DirectUriRequest;
}
/// <summary>
diff --git a/src/DotNetOAuth/DotNetOAuth.csproj b/src/DotNetOAuth/DotNetOAuth.csproj
index 82c8593..4e1373a 100644
--- a/src/DotNetOAuth/DotNetOAuth.csproj
+++ b/src/DotNetOAuth/DotNetOAuth.csproj
@@ -73,6 +73,7 @@
<Compile Include="DesktopConsumer.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Messages\ITokenSecretContainingMessage.cs" />
+ <Compile Include="Messaging\ChannelEventArgs.cs" />
<Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" />
<Compile Include="ServiceProviderDescription.cs" />
<Compile Include="Messages\ITokenContainingMessage.cs" />
diff --git a/src/DotNetOAuth/Messages/DirectUserToConsumerMessage.cs b/src/DotNetOAuth/Messages/DirectUserToConsumerMessage.cs
index 56ef959..c73eaa4 100644
--- a/src/DotNetOAuth/Messages/DirectUserToConsumerMessage.cs
+++ b/src/DotNetOAuth/Messages/DirectUserToConsumerMessage.cs
@@ -11,14 +11,14 @@ namespace DotNetOAuth.Messages {
/// <summary>
/// A message used to redirect the user from a Service Provider to a Consumer's web site.
/// </summary>
- internal sealed class DirectUserToConsumerMessage : MessageBase, ITokenContainingMessage {
+ /// <remarks>
+ /// The class is sealed because extra parameters are determined by the callback URI provided by the Consumer.
+ /// </remarks>
+ public sealed class DirectUserToConsumerMessage : MessageBase, ITokenContainingMessage {
/// <summary>
/// Initializes a new instance of the <see cref="DirectUserToConsumerMessage"/> class.
/// </summary>
/// <param name="consumer">The URI of the Consumer endpoint to send this message to.</param>
- /// <remarks>
- /// The class is sealed because extra parameters are determined by the callback URI provided by the Consumer.
- /// </remarks>
internal DirectUserToConsumerMessage(Uri consumer)
: base(MessageProtections.None, MessageTransport.Indirect, new MessageReceivingEndpoint(consumer, HttpDeliveryMethods.GetRequest)) {
}
diff --git a/src/DotNetOAuth/Messages/GetAccessTokenMessage.cs b/src/DotNetOAuth/Messages/GetAccessTokenMessage.cs
index 45863d1..15c8ffd 100644
--- a/src/DotNetOAuth/Messages/GetAccessTokenMessage.cs
+++ b/src/DotNetOAuth/Messages/GetAccessTokenMessage.cs
@@ -7,6 +7,7 @@
namespace DotNetOAuth.Messages {
using System;
using DotNetOAuth.Messaging;
+ using System.Globalization;
/// <summary>
/// A direct message sent by the Consumer to exchange an authorized Request Token
@@ -37,5 +38,17 @@ namespace DotNetOAuth.Messages {
/// </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, Strings.MessageNotAllowedExtraParameters, GetType().Name));
+ }
+ }
}
}
diff --git a/src/DotNetOAuth/Messages/GrantRequestTokenMessage.cs b/src/DotNetOAuth/Messages/GrantRequestTokenMessage.cs
index 1b48243..f52ac01 100644
--- a/src/DotNetOAuth/Messages/GrantRequestTokenMessage.cs
+++ b/src/DotNetOAuth/Messages/GrantRequestTokenMessage.cs
@@ -8,6 +8,7 @@ namespace DotNetOAuth.Messages {
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DotNetOAuth.Messaging;
+ using System;
/// <summary>
/// A direct message sent from Service Provider to Consumer in response to
@@ -17,9 +18,18 @@ namespace DotNetOAuth.Messages {
/// <summary>
/// Initializes a new instance of the <see cref="GrantRequestTokenMessage"/> 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>
- protected internal GrantRequestTokenMessage(string requestToken, string tokenSecret) : this() {
+ /// <remarks>
+ /// This constructor is used by the Service Provider to send the message.
+ /// </remarks>
+ protected internal GrantRequestTokenMessage(GetRequestTokenMessage requestMessage, string requestToken, string tokenSecret) : this() {
+ if (requestMessage == null) throw new ArgumentNullException("requestMessage");
+ if (string.IsNullOrEmpty(requestToken)) throw new ArgumentNullException("requestToken");
+ if (string.IsNullOrEmpty(tokenSecret)) throw new ArgumentNullException("tokenSecret");
+
+ this.RequestMessage = requestMessage;
this.RequestToken = requestToken;
this.TokenSecret = tokenSecret;
}
@@ -27,6 +37,7 @@ namespace DotNetOAuth.Messages {
/// <summary>
/// Initializes a new instance of the <see cref="GrantRequestTokenMessage"/> class.
/// </summary>
+ /// <remarks>This constructor is used by the consumer to deserialize the message.</remarks>
protected internal GrantRequestTokenMessage()
: base(MessageProtections.None, MessageTransport.Direct) {
}
@@ -61,6 +72,8 @@ namespace DotNetOAuth.Messages {
[MessagePart("oauth_token", IsRequired = true)]
internal string RequestToken { get; set; }
+ internal GetRequestTokenMessage RequestMessage { get; set; }
+
/// <summary>
/// Gets or sets the Token Secret.
/// </summary>
diff --git a/src/DotNetOAuth/Messaging/Channel.cs b/src/DotNetOAuth/Messaging/Channel.cs
index 77263eb..c283382 100644
--- a/src/DotNetOAuth/Messaging/Channel.cs
+++ b/src/DotNetOAuth/Messaging/Channel.cs
@@ -93,6 +93,24 @@ namespace DotNetOAuth.Messaging {
}
/// <summary>
+ /// An event fired whenever a message is about to be encoded and sent.
+ /// </summary>
+ internal event EventHandler<ChannelEventArgs> Sending;
+
+ /// <summary>
+ /// Fires the <see cref="Sending"/> event.
+ /// </summary>
+ /// <param name="message">The message about to be encoded and sent.</param>
+ protected virtual void OnSending(IProtocolMessage message) {
+ if (message == null) throw new ArgumentNullException("message");
+
+ var sending = this.Sending;
+ if (sending != null) {
+ sending(this, new ChannelEventArgs(message));
+ }
+ }
+
+ /// <summary>
/// Gets a tool that can figure out what kind of message is being received
/// so it can be deserialized.
/// </summary>
@@ -513,6 +531,8 @@ namespace DotNetOAuth.Messaging {
throw new ArgumentNullException("message");
}
+ this.OnSending(message);
+
MessageProtections appliedProtection = MessageProtections.None;
foreach (IChannelBindingElement bindingElement in this.bindingElements) {
if (bindingElement.PrepareMessageForSending(message)) {
diff --git a/src/DotNetOAuth/Messaging/ChannelEventArgs.cs b/src/DotNetOAuth/Messaging/ChannelEventArgs.cs
new file mode 100644
index 0000000..18c1d3a
--- /dev/null
+++ b/src/DotNetOAuth/Messaging/ChannelEventArgs.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DotNetOAuth.Messaging {
+ public class ChannelEventArgs : EventArgs {
+ internal ChannelEventArgs(IProtocolMessage message) {
+ if (message == null) throw new ArgumentNullException("message");
+
+ this.Message = message;
+ }
+
+ public IProtocolMessage Message { get; private set; }
+ }
+}
diff --git a/src/DotNetOAuth/ServiceProvider.cs b/src/DotNetOAuth/ServiceProvider.cs
index 48ccff4..4032a4a 100644
--- a/src/DotNetOAuth/ServiceProvider.cs
+++ b/src/DotNetOAuth/ServiceProvider.cs
@@ -27,6 +27,8 @@ namespace DotNetOAuth {
/// </list>
/// </remarks>
public class ServiceProvider {
+ private OAuthChannel channel;
+
/// <summary>
/// Initializes a new instance of the <see cref="ServiceProvider"/> class.
/// </summary>
@@ -61,6 +63,19 @@ namespace DotNetOAuth {
}
/// <summary>
+ /// Hooks the channel in order to perform some operations on some outgoing messages.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DotNetOAuth.Messaging.ChannelEventArgs"/> instance containing the event data.</param>
+ private void OAuthChannel_Sending(object sender, ChannelEventArgs e) {
+ // Hook to store the token and secret on its way down to the Consumer.
+ var grantRequestTokenResponse = e.Message as GrantRequestTokenMessage;
+ if (grantRequestTokenResponse != null) {
+ this.TokenManager.StoreNewRequestToken(grantRequestTokenResponse.RequestMessage, grantRequestTokenResponse);
+ }
+ }
+
+ /// <summary>
/// Gets the description of this Service Provider.
/// </summary>
public ServiceProviderDescription ServiceDescription { get; private set; }
@@ -87,7 +102,22 @@ namespace DotNetOAuth {
/// <summary>
/// Gets or sets the channel to use for sending/receiving messages.
/// </summary>
- internal OAuthChannel OAuthChannel { get; set; }
+ internal OAuthChannel OAuthChannel {
+ get {
+ return this.channel;
+ }
+ set {
+ if (this.channel != null) {
+ this.channel.Sending -= OAuthChannel_Sending;
+ }
+
+ this.channel = value;
+
+ if (this.channel != null) {
+ this.channel.Sending += OAuthChannel_Sending;
+ }
+ }
+ }
/// <summary>
/// Reads any incoming OAuth message.
@@ -132,20 +162,31 @@ namespace DotNetOAuth {
}
/// <summary>
- /// Sends an unauthorized token back to the Consumer for use in a user agent redirect
- /// for subsequent authorization.
+ /// Reads a request for an unauthorized token from the incoming HTTP request.
+ /// </summary>
+ /// <param name="request">The HTTP request to read from.</param>
+ /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
+ /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
+ public GetRequestTokenMessage ReadTokenRequest(HttpRequestInfo request) {
+ GetRequestTokenMessage message;
+ this.Channel.TryReadFromRequest(request, out message);
+ return message;
+ }
+
+ /// <summary>
+ /// Prepares a message containing an unauthorized token for the Consumer to use in a
+ /// user agent redirect for subsequent authorization.
/// </summary>
/// <param name="request">The token request message the Consumer sent that the Service Provider is now responding to.</param>
- /// <param name="extraParameters">Any extra parameters the Consumer should receive with the OAuth message. May be null.</param>
- /// <returns>The actual response the Service Provider will need to forward as the HTTP response.</returns>
- public Response SendUnauthorizedTokenResponse(GetRequestTokenMessage request, IDictionary<string, string> extraParameters) {
+ /// <returns>The response message to send using the <see cref="Channel"/>, after optionally adding extra data to it.</returns>
+ public GrantRequestTokenMessage PrepareUnauthorizedTokenMessage(GetRequestTokenMessage request) {
+ if (request == null) throw new ArgumentNullException("request");
+
string token = this.TokenGenerator.GenerateRequestToken(request.ConsumerKey);
string secret = this.TokenGenerator.GenerateSecret();
- GrantRequestTokenMessage response = new GrantRequestTokenMessage(token, secret);
- response.AddNonOAuthParameters(extraParameters);
- this.TokenManager.StoreNewRequestToken(request, response);
+ GrantRequestTokenMessage response = new GrantRequestTokenMessage(request, token, secret);
- return this.Channel.Send(response);
+ return response;
}
/// <summary>
@@ -173,14 +214,28 @@ namespace DotNetOAuth {
}
/// <summary>
- /// Completes user authorization of a token by redirecting the user agent back to the Consumer.
+ /// Reads in a Consumer's request for the Service Provider to obtain permission from
+ /// the user to authorize the Consumer's access of some protected resource(s).
+ /// </summary>
+ /// <param name="request">The HTTP request to read from.</param>
+ /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
+ /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
+ public DirectUserToServiceProviderMessage ReadAuthorizationRequest(HttpRequestInfo request) {
+ DirectUserToServiceProviderMessage message;
+ this.Channel.TryReadFromRequest(request, out message);
+ return message;
+ }
+
+ /// <summary>
+ /// Prepares the message to send back to the consumer following proper authorization of
+ /// a token by an interactive user at the Service Provider's web site.
/// </summary>
/// <param name="request">The Consumer's original authorization request.</param>
/// <returns>
- /// The pending user agent redirect based message to be sent as an HttpResponse,
- /// or null if the Consumer requested no callback.
+ /// The message to send to the Consumer using <see cref="Channel"/> if one is necessary.
+ /// Null if the Consumer did not request a callback.
/// </returns>
- public Response SendAuthorizationResponse(DirectUserToServiceProviderMessage request) {
+ public DirectUserToConsumerMessage PrepareAuthorizationResponse(DirectUserToServiceProviderMessage request) {
if (request == null) {
throw new ArgumentNullException("request");
}
@@ -189,7 +244,7 @@ namespace DotNetOAuth {
var authorization = new DirectUserToConsumerMessage(request.Callback) {
RequestToken = request.RequestToken,
};
- return this.Channel.Send(authorization);
+ return authorization;
} else {
return null;
}
@@ -218,10 +273,21 @@ namespace DotNetOAuth {
}
/// <summary>
+ /// Reads in a Consumer's request to exchange an authorized request token for an access token.
+ /// </summary>
+ /// <param name="request">The HTTP request to read from.</param>
+ /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
+ /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
+ public GetAccessTokenMessage ReadAccessTokenRequest(HttpRequestInfo request) {
+ GetAccessTokenMessage message;
+ this.Channel.TryReadFromRequest(request, out message);
+ return message;
+ }
+
+ /// <summary>
/// Prepares and sends an access token to a Consumer, and invalidates the request token.
/// </summary>
/// <param name="request">The Consumer's message requesting an access token.</param>
- /// <param name="extraParameters">Any extra parameters the Consumer should receive with the OAuth message. May be null.</param>
/// <returns>The HTTP response to actually send to the Consumer.</returns>
public GrantAccessTokenMessage PrepareAccessTokenMessage(GetAccessTokenMessage request) {
if (request == null) {
@@ -248,18 +314,6 @@ namespace DotNetOAuth {
}
/// <summary>
- /// Prepares and sends an access token to a Consumer, and invalidates the request token.
- /// </summary>
- /// <param name="request">The Consumer's message requesting an access token.</param>
- /// <param name="extraParameters">Any extra parameters the Consumer should receive with the OAuth message. May be null.</param>
- /// <returns>The HTTP response to actually send to the Consumer.</returns>
- public Response SendAccessToken(GetAccessTokenMessage request, IDictionary<string, string> extraParameters) {
- var grantAccess = PrepareAccessTokenMessage(request);
- grantAccess.AddNonOAuthParameters(extraParameters);
- return this.Channel.Send(grantAccess);
- }
-
- /// <summary>
/// Gets the authorization (access token) for accessing some protected resource.
/// </summary>
/// <returns>The authorization message sent by the Consumer, or null if no authorization message is attached.</returns>
@@ -269,8 +323,8 @@ namespace DotNetOAuth {
/// to access the resources being requested.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception>
- public AccessProtectedResourceMessage GetProtectedResourceAuthorization() {
- return this.GetProtectedResourceAuthorization(this.Channel.GetRequestFromContext());
+ public AccessProtectedResourceMessage ReadProtectedResourceAuthorization() {
+ return this.ReadProtectedResourceAuthorization(this.Channel.GetRequestFromContext());
}
/// <summary>
@@ -284,8 +338,8 @@ namespace DotNetOAuth {
/// to access the resources being requested.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception>
- public AccessProtectedResourceMessage GetProtectedResourceAuthorization(HttpRequest request) {
- return this.GetProtectedResourceAuthorization(new HttpRequestInfo(request));
+ public AccessProtectedResourceMessage ReadProtectedResourceAuthorization(HttpRequest request) {
+ return this.ReadProtectedResourceAuthorization(new HttpRequestInfo(request));
}
/// <summary>
@@ -300,45 +354,8 @@ namespace DotNetOAuth {
/// to access the resources being requested.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception>
- public AccessProtectedResourceMessage GetProtectedResourceAuthorization(HttpRequestMessageProperty request, Uri requestUri) {
- return this.GetProtectedResourceAuthorization(new HttpRequestInfo(request, requestUri));
- }
-
- /// <summary>
- /// Reads a request for an unauthorized token from the incoming HTTP request.
- /// </summary>
- /// <param name="request">The HTTP request to read from.</param>
- /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
- /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
- internal GetRequestTokenMessage ReadTokenRequest(HttpRequestInfo request) {
- GetRequestTokenMessage message;
- this.Channel.TryReadFromRequest(request, out message);
- return message;
- }
-
- /// <summary>
- /// Reads in a Consumer's request for the Service Provider to obtain permission from
- /// the user to authorize the Consumer's access of some protected resource(s).
- /// </summary>
- /// <param name="request">The HTTP request to read from.</param>
- /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
- /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
- internal DirectUserToServiceProviderMessage ReadAuthorizationRequest(HttpRequestInfo request) {
- DirectUserToServiceProviderMessage message;
- this.Channel.TryReadFromRequest(request, out message);
- return message;
- }
-
- /// <summary>
- /// Reads in a Consumer's request to exchange an authorized request token for an access token.
- /// </summary>
- /// <param name="request">The HTTP request to read from.</param>
- /// <returns>The incoming request, or null if no OAuth message was attached.</returns>
- /// <exception cref="ProtocolException">Thrown if an unexpected OAuth message is attached to the incoming request.</exception>
- internal GetAccessTokenMessage ReadAccessTokenRequest(HttpRequestInfo request) {
- GetAccessTokenMessage message;
- this.Channel.TryReadFromRequest(request, out message);
- return message;
+ public AccessProtectedResourceMessage ReadProtectedResourceAuthorization(HttpRequestMessageProperty request, Uri requestUri) {
+ return this.ReadProtectedResourceAuthorization(new HttpRequestInfo(request, requestUri));
}
/// <summary>
@@ -352,7 +369,7 @@ namespace DotNetOAuth {
/// to access the resources being requested.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if an unexpected message is attached to the request.</exception>
- internal AccessProtectedResourceMessage GetProtectedResourceAuthorization(HttpRequestInfo request) {
+ public AccessProtectedResourceMessage ReadProtectedResourceAuthorization(HttpRequestInfo request) {
if (request == null) {
throw new ArgumentNullException("request");
}
diff --git a/src/DotNetOAuth/Strings.Designer.cs b/src/DotNetOAuth/Strings.Designer.cs
index 54cdc9e..c312fe5 100644
--- a/src/DotNetOAuth/Strings.Designer.cs
+++ b/src/DotNetOAuth/Strings.Designer.cs
@@ -97,6 +97,15 @@ namespace DotNetOAuth {
}
/// <summary>
+ /// Looks up a localized string similar to The {0} message included extra data which is not allowed..
+ /// </summary>
+ internal static string MessageNotAllowedExtraParameters {
+ get {
+ return ResourceManager.GetString("MessageNotAllowedExtraParameters", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The request URL query MUST NOT contain any OAuth Protocol Parameters..
/// </summary>
internal static string RequestUrlMustNotHaveOAuthParameters {
diff --git a/src/DotNetOAuth/Strings.resx b/src/DotNetOAuth/Strings.resx
index b4f6bb7..252726e 100644
--- a/src/DotNetOAuth/Strings.resx
+++ b/src/DotNetOAuth/Strings.resx
@@ -129,6 +129,9 @@
<data name="InvalidIncomingMessage" xml:space="preserve">
<value>An invalid OAuth message received and discarded.</value>
</data>
+ <data name="MessageNotAllowedExtraParameters" xml:space="preserve">
+ <value>The {0} message included extra data which is not allowed.</value>
+ </data>
<data name="RequestUrlMustNotHaveOAuthParameters" xml:space="preserve">
<value>The request URL query MUST NOT contain any OAuth Protocol Parameters.</value>
</data>
diff --git a/src/DotNetOAuth/WebConsumer.cs b/src/DotNetOAuth/WebConsumer.cs
index d1de7f1..fbcaed0 100644
--- a/src/DotNetOAuth/WebConsumer.cs
+++ b/src/DotNetOAuth/WebConsumer.cs
@@ -40,14 +40,14 @@ namespace DotNetOAuth {
/// <remarks>
/// Requires HttpContext.Current.
/// </remarks>
- public Response RequestUserAuthorization() {
+ public DirectUserToServiceProviderMessage PrepareRequestUserAuthorization() {
Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix(Protocol.Default.ParameterPrefix);
- return this.RequestUserAuthorization(callback, null, null);
+ return this.PrepareRequestUserAuthorization(callback, null, null);
}
/// <summary>
- /// Begins an OAuth authorization request and redirects the user to the Service Provider
- /// to provide that authorization.
+ /// Prepares an OAuth message that begins an authorization request that will
+ /// redirect the user to the Service Provider to provide that authorization.
/// </summary>
/// <param name="callback">
/// An optional Consumer URL that the Service Provider should redirect the
@@ -56,9 +56,9 @@ namespace DotNetOAuth {
/// <param name="requestParameters">Extra parameters to add to the request token message. Optional.</param>
/// <param name="redirectParameters">Extra parameters to add to the redirect to Service Provider message. Optional.</param>
/// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
- public Response RequestUserAuthorization(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters) {
+ public DirectUserToServiceProviderMessage PrepareRequestUserAuthorization(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters) {
string token;
- return this.RequestUserAuthorization(callback, requestParameters, redirectParameters, out token);
+ return this.PrepareRequestUserAuthorization(callback, requestParameters, redirectParameters, out token);
}
/// <summary>