public async Task <OAuth2TokenResult> GetOAuthTokenViaBrowserAsync(Uri targetUri, IEnumerable <string> scopes) { ThrowIfUserInteractionDisabled(); var oauthClient = new GitHubOAuth2Client(HttpClient, Context.Settings, targetUri); // We require a desktop session to launch the user's default web browser if (!Context.SessionManager.IsDesktopSession) { throw new InvalidOperationException("Browser authentication requires a desktop session"); } var browserOptions = new OAuth2WebBrowserOptions { SuccessResponseHtml = GitHubResources.AuthenticationResponseSuccessHtml, FailureResponseHtmlFormat = GitHubResources.AuthenticationResponseFailureHtmlFormat }; var browser = new OAuth2SystemWebBrowser(Context.Environment, browserOptions); // Write message to the terminal (if any is attached) for some feedback that we're waiting for a web response Context.Terminal.WriteLine("info: please complete authentication in your browser..."); OAuth2AuthorizationCodeResult authCodeResult = await oauthClient.GetAuthorizationCodeAsync(scopes, browser, CancellationToken.None); return(await oauthClient.GetTokenByAuthorizationCodeAsync(authCodeResult, CancellationToken.None)); }
public async Task <OAuth2TokenResult> GetOAuthTokenViaDeviceCodeAsync(Uri targetUri, IEnumerable <string> scopes) { ThrowIfUserInteractionDisabled(); var oauthClient = new GitHubOAuth2Client(HttpClient, Context.Settings, targetUri); OAuth2DeviceCodeResult dcr = await oauthClient.GetDeviceCodeAsync(scopes, CancellationToken.None); // If we have a desktop session show the device code in a dialog if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession && TryFindHelperExecutablePath(out string helperPath)) { var args = new StringBuilder("device"); args.AppendFormat(" --code {0} ", QuoteCmdArg(dcr.UserCode)); args.AppendFormat(" --url {0}", QuoteCmdArg(dcr.VerificationUri.ToString())); var promptCts = new CancellationTokenSource(); var tokenCts = new CancellationTokenSource(); // Show the dialog with the device code but don't await its closure Task promptTask = InvokeHelperAsync(helperPath, args.ToString(), null, promptCts.Token); // Start the request for an OAuth token but don't wait Task <OAuth2TokenResult> tokenTask = oauthClient.GetTokenByDeviceCodeAsync(dcr, tokenCts.Token); Task t = await Task.WhenAny(promptTask, tokenTask); // If the dialog was closed the user wishes to cancel the request if (t == promptTask) { tokenCts.Cancel(); } OAuth2TokenResult tokenResult; try { tokenResult = await tokenTask; } catch (OperationCanceledException) { throw new Exception("User canceled device code authentication"); } // Close the dialog promptCts.Cancel(); return(tokenResult); } else { ThrowIfTerminalPromptsDisabled(); string deviceMessage = $"To complete authentication please visit {dcr.VerificationUri} and enter the following code:" + Environment.NewLine + dcr.UserCode; Context.Terminal.WriteLine(deviceMessage); return(await oauthClient.GetTokenByDeviceCodeAsync(dcr, CancellationToken.None)); } }
public async Task <OAuth2TokenResult> GetOAuthTokenAsync(Uri targetUri, IEnumerable <string> scopes) { ThrowIfUserInteractionDisabled(); var oauthClient = new GitHubOAuth2Client(HttpClient, Context.Settings, targetUri); // If we have a desktop session try authentication using the user's default web browser if (Context.SessionManager.IsDesktopSession) { var browserOptions = new OAuth2WebBrowserOptions { SuccessResponseHtml = GitHubResources.AuthenticationResponseSuccessHtml, FailureResponseHtmlFormat = GitHubResources.AuthenticationResponseFailureHtmlFormat }; var browser = new OAuth2SystemWebBrowser(browserOptions); // Write message to the terminal (if any is attached) for some feedback that we're waiting for a web response Context.Terminal.WriteLine("info: please complete authentication in your browser..."); OAuth2AuthorizationCodeResult authCodeResult = await oauthClient.GetAuthorizationCodeAsync(scopes, browser, CancellationToken.None); return(await oauthClient.GetTokenByAuthorizationCodeAsync(authCodeResult, CancellationToken.None)); } else { ThrowIfTerminalPromptsDisabled(); if (GitHubConstants.IsOAuthDeviceAuthSupported) { OAuth2DeviceCodeResult deviceCodeResult = await oauthClient.GetDeviceCodeAsync(scopes, CancellationToken.None); string deviceMessage = $"To complete authentication please visit {deviceCodeResult.VerificationUri} and enter the following code:" + Environment.NewLine + deviceCodeResult.UserCode; Context.Terminal.WriteLine(deviceMessage); return(await oauthClient.GetTokenByDeviceCodeAsync(deviceCodeResult, CancellationToken.None)); } // We'd like to try using an OAuth2 flow that does not require a web browser on this device // such as the device code flow (RFC 8628) but GitHub's auth stack does not support this. throw new NotSupportedException("GitHub OAuth authentication is not supported without an interactive desktop session."); } }