summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs6
-rw-r--r--src/DotNetOAuth.Test/Scenarios/CoordinatingOAuthChannel.cs1
-rw-r--r--src/DotNetOAuth/Consumer.cs27
-rw-r--r--src/DotNetOAuth/Messaging/MessagingStrings.Designer.cs9
-rw-r--r--src/DotNetOAuth/Messaging/MessagingStrings.resx3
-rw-r--r--src/DotNetOAuth/Messaging/MessagingUtilities.cs23
-rw-r--r--src/DotNetOAuth/Messaging/Response.cs2
-rw-r--r--src/DotNetOAuth/ServiceProvider.cs7
-rw-r--r--src/DotNetOAuth/Strings.Designer.cs9
-rw-r--r--src/DotNetOAuth/Strings.resx3
10 files changed, 67 insertions, 23 deletions
diff --git a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
index ee574c9..66e8b5f 100644
--- a/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
+++ b/src/DotNetOAuth.Test/Scenarios/AppendixScenarios.cs
@@ -39,7 +39,7 @@ namespace DotNetOAuth.Test {
Coordinator coordinator = new Coordinator(
channel => {
consumer.Channel = channel;
- consumer.RequestUserAuthorization(new Uri("http://printer.example.com/request_token_ready"), null);
+ consumer.RequestUserAuthorization(new Uri("http://printer.example.com/request_token_ready"), null, null);
string accessToken = consumer.ProcessUserAuthorization();
var photoRequest = consumer.CreateAuthorizedRequestInternal(accessPhotoEndpoint, accessToken);
Response protectedPhoto = channel.RequestProtectedResource(photoRequest);
@@ -52,12 +52,12 @@ namespace DotNetOAuth.Test {
tokenManager.AddConsumer(consumer.ConsumerKey, consumer.ConsumerSecret);
sp.Channel = channel;
var requestTokenMessage = sp.ReadTokenRequest();
- sp.SendUnauthorizedTokenResponse(requestTokenMessage);
+ sp.SendUnauthorizedTokenResponse(requestTokenMessage, null);
var authRequest = sp.ReadAuthorizationRequest();
tokenManager.AuthorizeRequestToken(authRequest.RequestToken);
sp.SendAuthorizationResponse(authRequest);
var accessRequest = sp.ReadAccessTokenRequest();
- sp.SendAccessToken(accessRequest);
+ sp.SendAccessToken(accessRequest, null);
string accessToken = sp.GetAccessTokenInRequest();
channel.SendDirectRawResponse(new Response {
ResponseStream = new MemoryStream(new byte[] { 0x33, 0x66 }),
diff --git a/src/DotNetOAuth.Test/Scenarios/CoordinatingOAuthChannel.cs b/src/DotNetOAuth.Test/Scenarios/CoordinatingOAuthChannel.cs
index 12974fd..6bddaf8 100644
--- a/src/DotNetOAuth.Test/Scenarios/CoordinatingOAuthChannel.cs
+++ b/src/DotNetOAuth.Test/Scenarios/CoordinatingOAuthChannel.cs
@@ -29,6 +29,7 @@ namespace DotNetOAuth.Test.Scenarios {
/// <param name="signingBindingElement">
/// The signing element for the Consumer to use. Null for the Service Provider.
/// </param>
+ /// <param name="isConsumer">True if this channel is constructed for a Consumer.</param>
internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, bool isConsumer)
: base(
signingBindingElement,
diff --git a/src/DotNetOAuth/Consumer.cs b/src/DotNetOAuth/Consumer.cs
index 3be3f6c..9bc7951 100644
--- a/src/DotNetOAuth/Consumer.cs
+++ b/src/DotNetOAuth/Consumer.cs
@@ -16,6 +16,10 @@ namespace DotNetOAuth {
/// <summary>
/// A website or application that uses OAuth to access the Service Provider on behalf of the User.
/// </summary>
+ /// <remarks>
+ /// The methods on this class are thread-safe. Provided the properties are set and not changed
+ /// afterward, a single instance of this class may be used by an entire web application safely.
+ /// </remarks>
public class Consumer {
/// <summary>
/// Initializes a new instance of the <see cref="Consumer"/> class.
@@ -74,21 +78,35 @@ namespace DotNetOAuth {
/// <summary>
/// Begins an OAuth authorization request and redirects the user to the Service Provider
+ /// to provide that authorization. Upon successful authorization, the user is redirected
+ /// back to the current page.
+ /// </summary>
+ /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns>
+ /// <remarks>
+ /// Requires HttpContext.Current.
+ /// </remarks>
+ public Response RequestUserAuthorization() {
+ return this.RequestUserAuthorization(MessagingUtilities.GetRequestUrlFromContext(), null, null);
+ }
+
+ /// <summary>
+ /// Begins an OAuth authorization request and redirects 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
/// User Agent to upon successful authorization.
/// </param>
- /// <param name="extraParameters">Extra parameters to add to the request token message. Optional.</param>
+ /// <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> extraParameters) {
+ public Response RequestUserAuthorization(Uri callback, IDictionary<string, string> requestParameters, IDictionary<string, string> redirectParameters) {
// Obtain an unauthorized request token.
var requestToken = new RequestTokenMessage(this.ServiceProvider.RequestTokenEndpoint) {
ConsumerKey = this.ConsumerKey,
ConsumerSecret = this.ConsumerSecret,
};
- requestToken.AddNonOAuthParameters(extraParameters);
+ requestToken.AddNonOAuthParameters(requestParameters);
var requestTokenResponse = this.Channel.Request<UnauthorizedRequestTokenMessage>(requestToken);
this.TokenManager.StoreNewRequestToken(this.ConsumerKey, requestTokenResponse.RequestToken, requestTokenResponse.TokenSecret, null/*TODO*/);
@@ -97,6 +115,7 @@ namespace DotNetOAuth {
Callback = callback,
RequestToken = requestTokenResponse.RequestToken,
};
+ requestAuthorization.AddNonOAuthParameters(redirectParameters);
return this.Channel.Send(requestAuthorization);
}
@@ -132,7 +151,7 @@ namespace DotNetOAuth {
/// <returns>The initialized WebRequest object.</returns>
public WebRequest CreateAuthorizedRequest(MessageReceivingEndpoint endpoint, string accessToken) {
IDirectedProtocolMessage message = this.CreateAuthorizedRequestInternal(endpoint, accessToken);
- WebRequest wr = this.Channel.InitializeRequest(message);
+ HttpWebRequest wr = this.Channel.InitializeRequest(message);
return wr;
}
diff --git a/src/DotNetOAuth/Messaging/MessagingStrings.Designer.cs b/src/DotNetOAuth/Messaging/MessagingStrings.Designer.cs
index b3d9d2e..5fd839a 100644
--- a/src/DotNetOAuth/Messaging/MessagingStrings.Designer.cs
+++ b/src/DotNetOAuth/Messaging/MessagingStrings.Designer.cs
@@ -70,6 +70,15 @@ namespace DotNetOAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed..
+ /// </summary>
+ internal static string CurrentHttpContextRequired {
+ get {
+ return ResourceManager.GetString("CurrentHttpContextRequired", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to DataContractSerializer could not be initialized on message type {0}. Is it missing a [DataContract] attribute?.
/// </summary>
internal static string DataContractMissingFromMessageType {
diff --git a/src/DotNetOAuth/Messaging/MessagingStrings.resx b/src/DotNetOAuth/Messaging/MessagingStrings.resx
index 1753bb7..66db7f4 100644
--- a/src/DotNetOAuth/Messaging/MessagingStrings.resx
+++ b/src/DotNetOAuth/Messaging/MessagingStrings.resx
@@ -120,6 +120,9 @@
<data name="ArgumentPropertyMissing" xml:space="preserve">
<value>Argument's {0}.{1} property is required but is empty or null.</value>
</data>
+ <data name="CurrentHttpContextRequired" xml:space="preserve">
+ <value>HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed.</value>
+ </data>
<data name="DataContractMissingFromMessageType" xml:space="preserve">
<value>DataContractSerializer could not be initialized on message type {0}. Is it missing a [DataContract] attribute?</value>
</data>
diff --git a/src/DotNetOAuth/Messaging/MessagingUtilities.cs b/src/DotNetOAuth/Messaging/MessagingUtilities.cs
index 226e4e9..995fe66 100644
--- a/src/DotNetOAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOAuth/Messaging/MessagingUtilities.cs
@@ -133,6 +133,27 @@ namespace DotNetOAuth.Messaging {
}
/// <summary>
+ /// Gets the original request URL, as seen from the browser before any URL rewrites on the server if any.
+ /// Cookieless session directory (if applicable) is also included.
+ /// </summary>
+ /// <returns>The URL in the user agent's Location bar.</returns>
+ internal static Uri GetRequestUrlFromContext() {
+ HttpContext context = HttpContext.Current;
+ if (context == null) {
+ throw new InvalidOperationException(MessagingStrings.CurrentHttpContextRequired);
+ }
+
+ // We use Request.Url for the full path to the server, and modify it
+ // with Request.RawUrl to capture both the cookieless session "directory" if it exists
+ // and the original path in case URL rewriting is going on. We don't want to be
+ // fooled by URL rewriting because we're comparing the actual URL with what's in
+ // the return_to parameter in some cases.
+ // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless
+ // session, but not the URL rewriting problem.
+ return new Uri(context.Request.Url, context.Request.RawUrl);
+ }
+
+ /// <summary>
/// Extracts the recipient from an HttpRequestInfo.
/// </summary>
/// <param name="request">The request to get recipient information from.</param>
@@ -146,7 +167,7 @@ namespace DotNetOAuth.Messaging {
/// </summary>
/// <param name="message">The message to copy the extra data into.</param>
/// <param name="extraParameters">The extra data to copy into the message. May be null to do nothing.</param>
- internal static void AddNonOAuthParameters(this ITamperResistantOAuthMessage message, IDictionary<string, string> extraParameters) {
+ internal static void AddNonOAuthParameters(this IProtocolMessage message, IDictionary<string, string> extraParameters) {
if (message == null) {
throw new ArgumentNullException("message");
}
diff --git a/src/DotNetOAuth/Messaging/Response.cs b/src/DotNetOAuth/Messaging/Response.cs
index c02acc2..833ceb5 100644
--- a/src/DotNetOAuth/Messaging/Response.cs
+++ b/src/DotNetOAuth/Messaging/Response.cs
@@ -109,7 +109,7 @@ namespace DotNetOAuth.Messaging {
/// </summary>
public void Send() {
if (HttpContext.Current == null) {
- throw new InvalidOperationException(Strings.CurrentHttpContextRequired);
+ throw new InvalidOperationException(MessagingStrings.CurrentHttpContextRequired);
}
HttpContext.Current.Response.Clear();
diff --git a/src/DotNetOAuth/ServiceProvider.cs b/src/DotNetOAuth/ServiceProvider.cs
index 5d66639..44d64e4 100644
--- a/src/DotNetOAuth/ServiceProvider.cs
+++ b/src/DotNetOAuth/ServiceProvider.cs
@@ -12,6 +12,7 @@ namespace DotNetOAuth {
using DotNetOAuth.Messages;
using DotNetOAuth.Messaging;
using DotNetOAuth.Messaging.Bindings;
+using System.Collections.Generic;
/// <summary>
/// A web application that allows access via OAuth.
@@ -79,7 +80,7 @@ namespace DotNetOAuth {
return this.Channel.ReadFromRequest<RequestTokenMessage>(request);
}
- internal void SendUnauthorizedTokenResponse(RequestTokenMessage request) {
+ internal void SendUnauthorizedTokenResponse(RequestTokenMessage request, IDictionary<string, string> extraParameters) {
string token = this.TokenGenerator.GenerateRequestToken(request.ConsumerKey);
string secret = this.TokenGenerator.GenerateSecret();
this.TokenManager.StoreNewRequestToken(request.ConsumerKey, token, secret, null/*add params*/);
@@ -87,6 +88,7 @@ namespace DotNetOAuth {
RequestToken = token,
TokenSecret = secret,
};
+ response.AddNonOAuthParameters(extraParameters);
this.Channel.Send(response);
}
@@ -127,7 +129,7 @@ namespace DotNetOAuth {
return this.Channel.ReadFromRequest<RequestAccessTokenMessage>(request);
}
- internal void SendAccessToken(RequestAccessTokenMessage request) {
+ internal void SendAccessToken(RequestAccessTokenMessage request, IDictionary<string, string> extraParameters) {
if (!this.TokenManager.IsRequestTokenAuthorized(request.RequestToken)) {
throw new ProtocolException(
string.Format(
@@ -143,6 +145,7 @@ namespace DotNetOAuth {
AccessToken = accessToken,
TokenSecret = tokenSecret,
};
+ grantAccess.AddNonOAuthParameters(extraParameters);
this.Channel.Send(grantAccess);
}
diff --git a/src/DotNetOAuth/Strings.Designer.cs b/src/DotNetOAuth/Strings.Designer.cs
index 357a3ca..75ae01c 100644
--- a/src/DotNetOAuth/Strings.Designer.cs
+++ b/src/DotNetOAuth/Strings.Designer.cs
@@ -79,15 +79,6 @@ namespace DotNetOAuth {
}
/// <summary>
- /// Looks up a localized string similar to HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed..
- /// </summary>
- internal static string CurrentHttpContextRequired {
- get {
- return ResourceManager.GetString("CurrentHttpContextRequired", resourceCulture);
- }
- }
-
- /// <summary>
/// Looks up a localized string similar to An invalid OAuth message received and discarded..
/// </summary>
internal static string InvalidIncomingMessage {
diff --git a/src/DotNetOAuth/Strings.resx b/src/DotNetOAuth/Strings.resx
index 9ed8ab6..3c6b5f6 100644
--- a/src/DotNetOAuth/Strings.resx
+++ b/src/DotNetOAuth/Strings.resx
@@ -123,9 +123,6 @@
<data name="BadAccessTokenInProtectedResourceRequest" xml:space="preserve">
<value>The access token '{0}' is invalid or expired.</value>
</data>
- <data name="CurrentHttpContextRequired" xml:space="preserve">
- <value>HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed.</value>
- </data>
<data name="InvalidIncomingMessage" xml:space="preserve">
<value>An invalid OAuth message received and discarded.</value>
</data>