diff --git a/ShareX.UploadersLib/OAuth/GoogleOAuth2.cs b/ShareX.UploadersLib/OAuth/GoogleOAuth2.cs index 3de83e4e3..df8960540 100644 --- a/ShareX.UploadersLib/OAuth/GoogleOAuth2.cs +++ b/ShareX.UploadersLib/OAuth/GoogleOAuth2.cs @@ -39,6 +39,7 @@ public class GoogleOAuth2 : IOAuth2Loopback public OAuth2Info AuthInfo { get; private set; } private Uploader GoogleUploader { get; set; } public string RedirectURI { get; set; } + public string State { get; set; } public string Scope { get; set; } public GoogleOAuth2(OAuth2Info oauth, Uploader uploader) @@ -53,6 +54,7 @@ public string GetAuthorizationURL() args.Add("response_type", "code"); args.Add("client_id", AuthInfo.Client_ID); args.Add("redirect_uri", RedirectURI); + args.Add("state", State); args.Add("scope", Scope); return URLHelpers.CreateQueryString(AuthorizationEndpoint, args); diff --git a/ShareX.UploadersLib/OAuth/IOauth2Loopback.cs b/ShareX.UploadersLib/OAuth/IOauth2Loopback.cs index eda2c7a81..a35998ad7 100644 --- a/ShareX.UploadersLib/OAuth/IOauth2Loopback.cs +++ b/ShareX.UploadersLib/OAuth/IOauth2Loopback.cs @@ -28,5 +28,7 @@ namespace ShareX.UploadersLib public interface IOAuth2Loopback : IOAuth2 { string RedirectURI { get; set; } + string State { get; set; } + string Scope { get; set; } } } \ No newline at end of file diff --git a/ShareX.UploadersLib/OAuth/OAuthListener.cs b/ShareX.UploadersLib/OAuth/OAuthListener.cs index bae594ab8..259e26834 100644 --- a/ShareX.UploadersLib/OAuth/OAuthListener.cs +++ b/ShareX.UploadersLib/OAuth/OAuthListener.cs @@ -36,7 +36,6 @@ namespace ShareX.UploadersLib public class OAuthListener : IDisposable { public IOAuth2Loopback OAuth { get; private set; } - public string Code { get; private set; } private HttpListener listener; @@ -54,13 +53,14 @@ public void Dispose() public async Task ConnectAsync() { Dispose(); - Code = null; IPAddress ip = IPAddress.Loopback; int port = URLHelpers.GetRandomUnusedPort(); string redirectURI = string.Format($"http://{ip}:{port}/"); + string state = Helpers.GetRandomAlphanumeric(32); OAuth.RedirectURI = redirectURI; + OAuth.State = state; string url = OAuth.GetAuthorizationURL(); if (!string.IsNullOrEmpty(url)) @@ -74,6 +74,10 @@ public async Task ConnectAsync() return false; } + string queryCode = null; + string queryState = null; + bool stateValidation = false; + try { listener = new HttpListener(); @@ -81,13 +85,19 @@ public async Task ConnectAsync() listener.Start(); HttpListenerContext context = await listener.GetContextAsync(); - Code = context.Request.QueryString.Get("code"); + queryCode = context.Request.QueryString.Get("code"); + queryState = context.Request.QueryString.Get("state"); + stateValidation = !string.IsNullOrEmpty(queryState) && queryState == state; using (HttpListenerResponse response = context.Response) { string status; - if (!string.IsNullOrEmpty(Code)) + if (!stateValidation) + { + status = "Invalid state parameter."; + } + else if (!string.IsNullOrEmpty(queryCode)) { status = "Authorization completed successfully."; } @@ -113,9 +123,9 @@ public async Task ConnectAsync() Dispose(); } - if (!string.IsNullOrEmpty(Code)) + if (stateValidation && !string.IsNullOrEmpty(queryCode)) { - return await Task.Run(() => OAuth.GetAccessToken(Code)); + return await Task.Run(() => OAuth.GetAccessToken(queryCode)); } return false;