summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OAuth2.Client
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2012-03-08 19:29:50 -0800
committerAndrew Arnott <andrewarnott@gmail.com>2012-03-08 19:29:50 -0800
commitadad8ced8fc37ead73b1dc9ace246066103911fb (patch)
tree3a0e89cefa61042d38f3be5be95cc735ed65014f /src/DotNetOpenAuth.OAuth2.Client
parent4377c981006a129ca659cbf639aa0959a3b267cf (diff)
downloadDotNetOpenAuth-adad8ced8fc37ead73b1dc9ace246066103911fb.zip
DotNetOpenAuth-adad8ced8fc37ead73b1dc9ace246066103911fb.tar.gz
DotNetOpenAuth-adad8ced8fc37ead73b1dc9ace246066103911fb.tar.bz2
OAuth 2 clients now use the state parameter to mitigate XSRF attacks.
Fixes #84
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.Client')
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs2
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx1
-rw-r--r--src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs24
3 files changed, 17 insertions, 10 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
index d140b7e..74c0685 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.239
+// Runtime Version:4.0.30319.261
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
index 114b3e8..0a41e42 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/OAuth2Strings.resx
@@ -125,6 +125,7 @@
</data>
<data name="AuthorizationResponseUnexpectedMismatch" xml:space="preserve">
<value>Unexpected OAuth authorization response received with callback and client state that does not match an expected value.</value>
+ <comment>The error message generated when detecting a mismatch between the state sent to the authorization server originally and what we got back with successful authorization, or that the user sessions were not identical between the two requests, suggesting XSRF or other attack on the user (victim).</comment>
</data>
<data name="RequiredPropertyNotYetPreset" xml:space="preserve">
<value>The property {0} must be set before this operation is allowed.</value>
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
index fe37dc3..42fa62b 100644
--- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
+++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs
@@ -39,36 +39,33 @@ namespace DotNetOpenAuth.OAuth2 {
/// Prepares a request for user authorization from an authorization server.
/// </summary>
/// <param name="scope">The scope of authorized access requested.</param>
- /// <param name="state">The state of the client that should be sent back with the authorization response.</param>
/// <param name="returnTo">The URL the authorization server should redirect the browser (typically on this site) to when the authorization is completed. If null, the current request's URL will be used.</param>
- public void RequestUserAuthorization(IEnumerable<string> scope = null, string state = null, Uri returnTo = null) {
+ public void RequestUserAuthorization(IEnumerable<string> scope = null, Uri returnTo = null) {
var authorizationState = new AuthorizationState(scope) {
Callback = returnTo,
};
- this.PrepareRequestUserAuthorization(authorizationState, state).Send();
+ this.PrepareRequestUserAuthorization(authorizationState).Send();
}
/// <summary>
/// Prepares a request for user authorization from an authorization server.
/// </summary>
/// <param name="scopes">The scope of authorized access requested.</param>
- /// <param name="state">The state of the client that should be sent back with the authorization response.</param>
/// <param name="returnTo">The URL the authorization server should redirect the browser (typically on this site) to when the authorization is completed. If null, the current request's URL will be used.</param>
/// <returns>The authorization request.</returns>
- public OutgoingWebResponse PrepareRequestUserAuthorization(IEnumerable<string> scopes = null, string state = null, Uri returnTo = null) {
+ public OutgoingWebResponse PrepareRequestUserAuthorization(IEnumerable<string> scopes = null, Uri returnTo = null) {
var authorizationState = new AuthorizationState(scopes) {
Callback = returnTo,
};
- return this.PrepareRequestUserAuthorization(authorizationState, state);
+ return this.PrepareRequestUserAuthorization(authorizationState);
}
/// <summary>
/// Prepares a request for user authorization from an authorization server.
/// </summary>
/// <param name="authorization">The authorization state to associate with this particular request.</param>
- /// <param name="state">The state of the client that should be sent back with the authorization response.</param>
/// <returns>The authorization request.</returns>
- public OutgoingWebResponse PrepareRequestUserAuthorization(IAuthorizationState authorization, string state = null) {
+ public OutgoingWebResponse PrepareRequestUserAuthorization(IAuthorizationState authorization) {
Requires.NotNull(authorization, "authorization");
Requires.ValidState(authorization.Callback != null || (HttpContext.Current != null && HttpContext.Current.Request != null), MessagingStrings.HttpContextRequired);
Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier");
@@ -84,10 +81,17 @@ namespace DotNetOpenAuth.OAuth2 {
var request = new EndUserAuthorizationRequest(this.AuthorizationServer) {
ClientIdentifier = this.ClientIdentifier,
Callback = authorization.Callback,
- ClientState = state,
};
request.Scope.ResetContents(authorization.Scope);
+ // 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.
+ if (this.AuthorizationTracker == null) {
+ var context = this.Channel.GetHttpContext();
+ request.ClientState = context.Session.SessionID;
+ }
+
return this.Channel.PrepareResponse(request);
}
@@ -112,6 +116,8 @@ namespace DotNetOpenAuth.OAuth2 {
authorizationState = this.AuthorizationTracker.GetAuthorizationState(callback, response.ClientState);
ErrorUtilities.VerifyProtocol(authorizationState != null, OAuth2Strings.AuthorizationResponseUnexpectedMismatch);
} else {
+ var context = this.Channel.GetHttpContext();
+ ErrorUtilities.VerifyProtocol(String.Equals(response.ClientState, context.Session.SessionID, StringComparison.Ordinal), OAuth2Strings.AuthorizationResponseUnexpectedMismatch);
authorizationState = new AuthorizationState { Callback = callback };
}
var success = response as EndUserAuthorizationSuccessAuthCodeResponse;