diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2012-03-21 22:58:36 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2012-03-21 22:58:36 -0700 |
commit | 80028b1c5442c85909b889b3c52cfbd0c0121437 (patch) | |
tree | b1b651c08a349957bb3d26ad5234a266d8d3e42e /src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs | |
parent | f02ccf1e93367b7ab8bece3a2c53e960e98d221d (diff) | |
parent | e1455ee979b150d1ea4afdf1bc82a9e5cbc5b2ba (diff) | |
download | DotNetOpenAuth-80028b1c5442c85909b889b3c52cfbd0c0121437.zip DotNetOpenAuth-80028b1c5442c85909b889b3c52cfbd0c0121437.tar.gz DotNetOpenAuth-80028b1c5442c85909b889b3c52cfbd0c0121437.tar.bz2 |
Merge branch 'v4.0' into dev11
Conflicts:
src/DotNetOpenAuth.sln
Diffstat (limited to 'src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs')
-rw-r--r-- | src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs index ffcc1ee..671214f 100644 --- a/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs +++ b/src/DotNetOpenAuth.OAuth2.Client/OAuth2/WebServerClient.cs @@ -39,43 +39,40 @@ 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"); Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null); if (authorization.Callback == null) { - authorization.Callback = this.Channel.GetRequestFromContext().UrlBeforeRewriting + authorization.Callback = this.Channel.GetRequestFromContext().GetPublicFacingUrl() .StripMessagePartsFromQueryString(this.Channel.MessageDescriptions.Get(typeof(EndUserAuthorizationSuccessResponseBase), Protocol.Default.Version)) .StripMessagePartsFromQueryString(this.Channel.MessageDescriptions.Get(typeof(EndUserAuthorizationFailedResponse), Protocol.Default.Version)); authorization.SaveChanges(); @@ -84,10 +81,21 @@ 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(); + 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."); + } + } + return this.Channel.PrepareResponse(request); } @@ -96,7 +104,7 @@ namespace DotNetOpenAuth.OAuth2 { /// </summary> /// <param name="request">The incoming HTTP request that may carry an authorization response.</param> /// <returns>The authorization state that contains the details of the authorization.</returns> - public IAuthorizationState ProcessUserAuthorization(HttpRequestInfo request = null) { + public IAuthorizationState ProcessUserAuthorization(HttpRequestBase request = null) { Requires.ValidState(!string.IsNullOrEmpty(this.ClientIdentifier), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientIdentifier"); Requires.ValidState(!string.IsNullOrEmpty(this.ClientSecret), OAuth2Strings.RequiredPropertyNotYetPreset, "ClientSecret"); @@ -106,12 +114,19 @@ namespace DotNetOpenAuth.OAuth2 { IMessageWithClientState response; if (this.Channel.TryReadFromRequest<IMessageWithClientState>(request, out response)) { - Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.UrlBeforeRewriting, this.Channel.MessageDescriptions.Get(response)); + Uri callback = MessagingUtilities.StripMessagePartsFromQueryString(request.GetPublicFacingUrl(), this.Channel.MessageDescriptions.Get(response)); IAuthorizationState authorizationState; if (this.AuthorizationTracker != null) { authorizationState = this.AuthorizationTracker.GetAuthorizationState(callback, response.ClientState); ErrorUtilities.VerifyProtocol(authorizationState != null, OAuth2Strings.AuthorizationResponseUnexpectedMismatch); } else { + var context = this.Channel.GetHttpContext(); + if (context.Session != null) { + ErrorUtilities.VerifyProtocol(string.Equals(response.ClientState, context.Session.SessionID, StringComparison.Ordinal), OAuth2Strings.AuthorizationResponseUnexpectedMismatch); + } else { + Logger.OAuth.WarnFormat("No request context discovered, so no client state parameter could be checked to mitigate XSRF attacks."); + } + authorizationState = new AuthorizationState { Callback = callback }; } var success = response as EndUserAuthorizationSuccessAuthCodeResponse; |