private void HandleAuthorizationResponse(string response) { if (responseMessageHandler) { UnityEngine.Object.Destroy(responseMessageHandler.gameObject); } if (string.IsNullOrEmpty(response) || response.Trim().StartsWith("Error")) { Debug.LogError($"UnityGoogleDrive: OAuth authorization error: {response}."); HandleProvideAccessTokenComplete(true); return; } var splittedResponse = response.Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (splittedResponse.Length != 3) { Debug.LogError($"UnityGoogleDrive: Malformed OAuth authorization response: {response}."); HandleProvideAccessTokenComplete(true); return; } authCodeExchanger.ExchangeAuthCode(splittedResponse[0], splittedResponse[1], splittedResponse[2]); }
private void HandleAuthorizationResponseOnUnityThread(object responseObj) { var response = (AuthorizationResponse)responseObj; if (response.IsError) { Debug.LogError(string.Format("UnityGoogleDrive: OAuth authorization error: {0}.", response.Error)); HandleProvideAccessTokenComplete(true); return; } authCodeExchanger.ExchangeAuthCode(response.AuthorizationCode, response.CodeVerifier, response.RedirectUri); }
private void HandleHttpListenerCallbackOnUnityThread(object state) { var result = (IAsyncResult)state; var httpListener = (HttpListener)result.AsyncState; var context = httpListener.EndGetContext(result); // Send an HTTP response to the browser to notify the user to close the browser. var response = context.Response; var responseString = settings.LoopbackResponseHtml; var buffer = System.Text.Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; var responseOutput = response.OutputStream; responseOutput.Write(buffer, 0, buffer.Length); responseOutput.Close(); httpListener.Close(); // Check for errors. if (context.Request.QueryString.Get("error") != null) { Debug.LogError(string.Format("UnityGoogleDrive: OAuth authorization error: {0}.", context.Request.QueryString.Get("error"))); HandleProvideAccessTokenComplete(true); return; } if (context.Request.QueryString.Get("code") == null || context.Request.QueryString.Get("state") == null) { Debug.LogError("UnityGoogleDrive: Malformed authorization response. " + context.Request.QueryString); HandleProvideAccessTokenComplete(true); return; } // Extract the authorization code. authorizationCode = context.Request.QueryString.Get("code"); var incomingState = context.Request.QueryString.Get("state"); // Compare the receieved state to the expected value, to ensure that // this app made the request which resulted in authorization. if (incomingState != expectedState) { Debug.LogError(string.Format("UnityGoogleDrive: Received request with invalid state ({0}).", incomingState)); HandleProvideAccessTokenComplete(true); return; } // Exchange the authorization code for tokens. authCodeExchanger.ExchangeAuthCode(authorizationCode, codeVerifier, redirectUri); }
private void ExecuteFullAuth() { // Generate state and PKCE values. expectedState = CryptoUtils.RandomDataBase64Uri(32); codeVerifier = CryptoUtils.RandomDataBase64Uri(32); var codeVerifierHash = CryptoUtils.Sha256(codeVerifier); var codeChallenge = CryptoUtils.Base64UriEncodeNoPadding(codeVerifierHash); // Creates a redirect URI using an available port on the loopback address. redirectUri = string.Format("{0}:{1}", LOOPBACK_URI, GetRandomUnusedPort()); // Listen for requests on the redirect URI. var httpListener = new HttpListener(); httpListener.Prefixes.Add(redirectUri + '/'); httpListener.Start(); // Create the OAuth 2.0 authorization request. // https://developers.google.com/identity/protocols/OAuth2WebServer#creatingclient var authRequest = string.Format("{0}?response_type=code&scope={1}&redirect_uri={2}&client_id={3}&state={4}&code_challenge={5}&code_challenge_method={6}" + "&access_type=offline" + // Forces to return a refresh token at the auth code exchange phase. "&approval_prompt=force", // Forces to show consent screen for each auth request. Needed to return refresh tokens on consequent auth runs. settings.AuthCredentials.AuthUri, settings.AccessScope, Uri.EscapeDataString(redirectUri), settings.AuthCredentials.ClientId, expectedState, codeChallenge, GoogleDriveSettings.CODE_CHALLENGE_METHOD); // Open request in the browser. Application.OpenURL(authRequest); // Wait for the authorization response. var context = httpListener.GetContext(); // Send an HTTP response to the browser to notify the user to close the browser. var response = context.Response; var responseString = settings.LoopbackResponseHtml; var buffer = System.Text.Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; var responseOutput = response.OutputStream; responseOutput.Write(buffer, 0, buffer.Length); responseOutput.Close(); httpListener.Stop(); // Check for errors. if (context.Request.QueryString.Get("error") != null) { Debug.LogError(string.Format("UnityGoogleDrive: OAuth authorization error: {0}.", context.Request.QueryString.Get("error"))); HandleProvideAccessTokenComplete(true); return; } if (context.Request.QueryString.Get("code") == null || context.Request.QueryString.Get("state") == null) { Debug.LogError("UnityGoogleDrive: Malformed authorization response. " + context.Request.QueryString); HandleProvideAccessTokenComplete(true); return; } // Extract the authorization code. authorizationCode = context.Request.QueryString.Get("code"); var incomingState = context.Request.QueryString.Get("state"); // Compare the receieved state to the expected value, to ensure that // this app made the request which resulted in authorization. if (incomingState != expectedState) { Debug.LogError(string.Format("UnityGoogleDrive: Received request with invalid state ({0}).", incomingState)); HandleProvideAccessTokenComplete(true); return; } // Exchange the authorization code for tokens. authCodeExchanger.ExchangeAuthCode(authorizationCode, codeVerifier, redirectUri); }