summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth2.Client/OAuth2
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.Client/OAuth2')
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/IOAuth2ChannelWithClient.cs6
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs8
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs42
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs37
4 files changed, 79 insertions, 14 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/IOAuth2ChannelWithClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/IOAuth2ChannelWithClient.cs
index c802be6..db8b9f8 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/IOAuth2ChannelWithClient.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/IOAuth2ChannelWithClient.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using System.Xml;
/// <summary>
/// An interface that defines the OAuth2 client specific channel additions.
@@ -23,5 +24,10 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
/// Gets or sets the client credentials applicator extension to use.
/// </summary>
ClientCredentialApplicator ClientCredentialApplicator { get; set; }
+
+ /// <summary>
+ /// Gets quotas used when deserializing JSON.
+ /// </summary>
+ XmlDictionaryReaderQuotas JsonReaderQuotas { get; }
}
}
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
index 8ad2ed9..b0cdb4b 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ChannelElements/OAuth2ClientChannel.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
using System.Diagnostics.Contracts;
using System.Net;
using System.Web;
+ using System.Xml;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2.Messages;
@@ -50,6 +51,13 @@ namespace DotNetOpenAuth.OAuth2.ChannelElements {
public ClientCredentialApplicator ClientCredentialApplicator { get; set; }
/// <summary>
+ /// Gets quotas used when deserializing JSON.
+ /// </summary>
+ public XmlDictionaryReaderQuotas JsonReaderQuotas {
+ get { return this.XmlDictionaryReaderQuotas; }
+ }
+
+ /// <summary>
/// Prepares an HTTP request that carries a given message.
/// </summary>
/// <param name="request">The message to send.</param>
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
index 49d0732..e9c952d 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/ClientBase.cs
@@ -16,6 +16,8 @@ namespace DotNetOpenAuth.OAuth2 {
#endif
using System.Security;
using System.Text;
+ using System.Xml;
+
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2.ChannelElements;
using DotNetOpenAuth.OAuth2.Messages;
@@ -71,6 +73,13 @@ namespace DotNetOpenAuth.OAuth2 {
}
/// <summary>
+ /// Gets quotas used when deserializing JSON.
+ /// </summary>
+ public XmlDictionaryReaderQuotas JsonReaderQuotas {
+ get { return this.OAuthChannel.JsonReaderQuotas; }
+ }
+
+ /// <summary>
/// Gets the OAuth client channel.
/// </summary>
internal IOAuth2ChannelWithClient OAuthChannel {
@@ -87,7 +96,20 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(request, "request");
Requires.NotNullOrEmpty(accessToken, "accessToken");
- OAuthUtilities.AuthorizeWithBearerToken(request, accessToken);
+ AuthorizeRequest(request.Headers, accessToken);
+ }
+
+ /// <summary>
+ /// Adds the necessary HTTP Authorization header to an HTTP request for protected resources
+ /// so that the Service Provider will allow the request through.
+ /// </summary>
+ /// <param name="requestHeaders">The headers on the request for protected resources from the service provider.</param>
+ /// <param name="accessToken">The access token previously obtained from the Authorization Server.</param>
+ public static void AuthorizeRequest(WebHeaderCollection requestHeaders, string accessToken) {
+ Requires.NotNull(requestHeaders, "requestHeaders");
+ Requires.NotNullOrEmpty(accessToken, "accessToken");
+
+ OAuthUtilities.AuthorizeWithBearerToken(requestHeaders, accessToken);
}
/// <summary>
@@ -99,6 +121,19 @@ namespace DotNetOpenAuth.OAuth2 {
public void AuthorizeRequest(HttpWebRequest request, IAuthorizationState authorization) {
Requires.NotNull(request, "request");
Requires.NotNull(authorization, "authorization");
+
+ this.AuthorizeRequest(request.Headers, authorization);
+ }
+
+ /// <summary>
+ /// Adds the OAuth authorization token to an outgoing HTTP request, renewing a
+ /// (nearly) expired access token if necessary.
+ /// </summary>
+ /// <param name="requestHeaders">The headers on the request for protected resources from the service provider.</param>
+ /// <param name="authorization">The authorization for this request previously obtained via OAuth.</param>
+ public void AuthorizeRequest(WebHeaderCollection requestHeaders, IAuthorizationState authorization) {
+ Requires.NotNull(requestHeaders, "requestHeaders");
+ Requires.NotNull(authorization, "authorization");
Requires.True(!string.IsNullOrEmpty(authorization.AccessToken), "authorization");
ErrorUtilities.VerifyProtocol(!authorization.AccessTokenExpirationUtc.HasValue || authorization.AccessTokenExpirationUtc >= DateTime.UtcNow || authorization.RefreshToken != null, ClientStrings.AuthorizationExpired);
@@ -107,7 +142,7 @@ namespace DotNetOpenAuth.OAuth2 {
this.RefreshAuthorization(authorization);
}
- AuthorizeRequest(request, authorization.AccessToken);
+ AuthorizeRequest(requestHeaders, authorization.AccessToken);
}
#if CLR4
@@ -216,7 +251,7 @@ namespace DotNetOpenAuth.OAuth2 {
Requires.NotNull(password, "password");
var request = new AccessTokenResourceOwnerPasswordCredentialsRequest(this.AuthorizationServer.TokenEndpoint, this.AuthorizationServer.Version) {
- UserName = userName,
+ RequestingUserName = userName,
Password = password,
};
@@ -372,6 +407,7 @@ namespace DotNetOpenAuth.OAuth2 {
var failure = response as AccessTokenFailedResponse;
ErrorUtilities.VerifyProtocol(success != null || failure != null, MessagingStrings.UnexpectedMessageReceivedOfMany);
if (success != null) {
+ authorizationState.Scope.Clear(); // clear the scope we requested so that the response will repopulate it.
UpdateAuthorizationWithResponse(authorizationState, success);
} else { // failure
Logger.OAuth.Info("Credentials rejected by the Authorization Server.");
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
index 939d1df..879e4e3 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
@@ -8,10 +8,14 @@ namespace DotNetOpenAuth.OAuth2 {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+ using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
+ using System.Web.Security;
+
+ using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth2.Messages;
@@ -20,6 +24,11 @@ namespace DotNetOpenAuth.OAuth2 {
/// </summary>
public class WebServerClient : ClientBase {
/// <summary>
+ /// The cookie name for XSRF mitigation during authorization code grant flows.
+ /// </summary>
+ private const string XsrfCookieName = "DotNetOpenAuth.WebServerClient.XSRF-Session";
+
+ /// <summary>
/// Initializes a new instance of the <see cref="WebServerClient"/> class.
/// </summary>
/// <param name="authorizationServer">The authorization server.</param>
@@ -100,16 +109,25 @@ namespace DotNetOpenAuth.OAuth2 {
// Mitigate XSRF attacks by including a state value that would be unpredictable between users, but
// verifiable for the same user/session.
// If the host is implementing the authorization tracker though, they're handling this protection themselves.
+ HttpCookie cookie = null;
if (this.AuthorizationTracker == null) {
var context = this.Channel.GetHttpContext();
- if (context.Session != null) {
- request.ClientState = context.Session.SessionID;
- } else {
- Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be set to mitigate XSRF attacks.");
- }
+
+ string xsrfKey = MessagingUtilities.GetNonCryptoRandomDataAsBase64(16);
+ cookie = new HttpCookie(XsrfCookieName, xsrfKey) {
+ HttpOnly = true,
+ Secure = FormsAuthentication.RequireSSL,
+ ////Expires = DateTime.Now.Add(OAuth2ClientSection.Configuration.MaxAuthorizationTime), // we prefer session cookies to persistent ones
+ };
+ request.ClientState = xsrfKey;
+ }
+
+ var response = this.Channel.PrepareResponse(request);
+ if (cookie != null) {
+ response.Cookies.Add(cookie);
}
- return this.Channel.PrepareResponse(request);
+ return response;
}
/// <summary>
@@ -134,12 +152,9 @@ namespace DotNetOpenAuth.OAuth2 {
ErrorUtilities.VerifyProtocol(authorizationState != null, ClientStrings.AuthorizationResponseUnexpectedMismatch);
} else {
var context = this.Channel.GetHttpContext();
- if (context.Session != null) {
- ErrorUtilities.VerifyProtocol(string.Equals(response.ClientState, context.Session.SessionID, StringComparison.Ordinal), ClientStrings.AuthorizationResponseUnexpectedMismatch);
- } else {
- Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be checked to mitigate XSRF attacks.");
- }
+ HttpCookie cookie = request.Cookies[XsrfCookieName];
+ ErrorUtilities.VerifyProtocol(cookie != null && string.Equals(response.ClientState, cookie.Value, StringComparison.Ordinal), ClientStrings.AuthorizationResponseUnexpectedMismatch);
authorizationState = new AuthorizationState { Callback = callback };
}
var success = response as EndUserAuthorizationSuccessAuthCodeResponse;