public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes) { // If we don't have a desktop session/GUI then we cannot offer browser if (!Context.SessionManager.IsDesktopSession) { modes = modes & ~AuthenticationModes.Browser; } // We need at least one mode! if (modes == AuthenticationModes.None) { throw new ArgumentException(@$ "Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession && TryFindHelperExecutablePath(out string helperPath)) { var cmdArgs = new StringBuilder("prompt"); if (!string.IsNullOrWhiteSpace(userName)) { cmdArgs.AppendFormat(" --username {0}", QuoteCmdArg(userName)); } cmdArgs.AppendFormat(" --url {0}", QuoteCmdArg(targetUri.ToString())); if ((modes & AuthenticationModes.Basic) != 0) { cmdArgs.Append(" --basic"); } if ((modes & AuthenticationModes.Browser) != 0) { cmdArgs.Append(" --browser"); } if ((modes & AuthenticationModes.Pat) != 0) { cmdArgs.Append(" --pat"); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, cmdArgs.ToString()); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "pat": if (!resultDict.TryGetValue("pat", out string pat)) { throw new Exception("Missing 'pat' in response"); } if (!resultDict.TryGetValue("username", out string patUserName)) { // Username is optional for PATs } return(new AuthenticationPromptResult( AuthenticationModes.Pat, new GitCredential(patUserName, pat))); case "browser": return(new AuthenticationPromptResult(AuthenticationModes.Browser)); case "basic": if (!resultDict.TryGetValue("username", out userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { switch (modes) { case AuthenticationModes.Basic: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); Context.Terminal.WriteLine("Enter GitLab credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(AuthenticationModes.Basic, new GitCredential(userName, password))); case AuthenticationModes.Pat: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); Context.Terminal.WriteLine("Enter GitLab credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string token = Context.Terminal.PromptSecret("Personal access token"); return(new AuthenticationPromptResult(AuthenticationModes.Pat, new GitCredential(userName, token))); case AuthenticationModes.Browser: return(new AuthenticationPromptResult(AuthenticationModes.Browser)); case AuthenticationModes.None: throw new ArgumentOutOfRangeException(nameof(modes), @$ "At least one {nameof(AuthenticationModes)} must be supplied"); default: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle); TerminalMenuItem browserItem = null; TerminalMenuItem basicItem = null; TerminalMenuItem patItem = null; if ((modes & AuthenticationModes.Browser) != 0) { browserItem = menu.Add("Web browser"); } if ((modes & AuthenticationModes.Pat) != 0) { patItem = menu.Add("Personal access token"); } if ((modes & AuthenticationModes.Basic) != 0) { basicItem = menu.Add("Username/password"); } // Default to the 'first' choice in the menu TerminalMenuItem choice = menu.Show(0); if (choice == browserItem) { goto case AuthenticationModes.Browser; } if (choice == basicItem) { goto case AuthenticationModes.Basic; } if (choice == patItem) { goto case AuthenticationModes.Pat; } throw new Exception(); } } }
public async Task <CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, string userName, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); string password; // If we don't have a desktop session/GUI then we cannot offer OAuth since the only // supported grant is authcode (i.e, using a web browser; device code is not supported). if (!Context.SessionManager.IsDesktopSession) { modes = modes & ~AuthenticationModes.OAuth; } // If the only supported mode is OAuth then just return immediately if (modes == AuthenticationModes.OAuth) { return(new CredentialsPromptResult(AuthenticationModes.OAuth)); } // We need at least one mode! if (modes == AuthenticationModes.None) { throw new ArgumentException(@$ "Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } // Shell out to the UI helper and show the Bitbucket u/p prompt if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession && TryFindHelperExecutablePath(out string helperPath)) { var cmdArgs = new StringBuilder("userpass"); if (!string.IsNullOrWhiteSpace(userName)) { cmdArgs.AppendFormat(" --username {0}", QuoteCmdArg(userName)); } if ((modes & AuthenticationModes.OAuth) != 0) { cmdArgs.Append(" --show-oauth"); } IDictionary <string, string> output = await InvokeHelperAsync(helperPath, cmdArgs.ToString()); if (output.TryGetValue("mode", out string mode) && StringComparer.OrdinalIgnoreCase.Equals(mode, "oauth")) { return(new CredentialsPromptResult(AuthenticationModes.OAuth)); } else { if (!output.TryGetValue("username", out userName)) { throw new Exception("Missing username in response"); } if (!output.TryGetValue("password", out password)) { throw new Exception("Missing password in response"); } return(new CredentialsPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter Bitbucket credentials for '{0}'...", targetUri); if (!string.IsNullOrWhiteSpace(userName)) { // Don't need to prompt for the username if it has been specified already Context.Terminal.WriteLine("Username: {0}", userName); } else { // Prompt for username userName = Context.Terminal.Prompt("Username"); } // Prompt for password password = Context.Terminal.PromptSecret("Password"); return(new CredentialsPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new CredentialsPromptResult(AuthenticationModes.OAuth)); case AuthenticationModes.None: throw new ArgumentOutOfRangeException(nameof(modes), @$ "At least one {nameof(AuthenticationModes)} must be supplied"); default: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle); TerminalMenuItem oauthItem = null; TerminalMenuItem basicItem = null; if ((modes & AuthenticationModes.OAuth) != 0) { oauthItem = menu.Add("OAuth"); } if ((modes & AuthenticationModes.Basic) != 0) { basicItem = menu.Add("Username/password"); } // Default to the 'first' choice in the menu TerminalMenuItem choice = menu.Show(0); if (choice == oauthItem) { goto case AuthenticationModes.OAuth; } if (choice == basicItem) { goto case AuthenticationModes.Basic; } throw new Exception(); } } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); if (modes == AuthenticationModes.None) { throw new ArgumentException($"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.OAuth) != 0) { promptArgs.Append(" --oauth"); } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", targetUri); } if (!string.IsNullOrWhiteSpace(userName)) { promptArgs.AppendFormat("--username {0}", userName); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "oauth": return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case "basic": if (!resultDict.TryGetValue("username", out userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult(new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic | AuthenticationModes.OAuth: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle) { new TerminalMenuItem(1, "Web browser", isDefault: true), new TerminalMenuItem(2, "Username/password") }; int option = menu.Show(); if (option == 1) { goto case AuthenticationModes.OAuth; } if (option == 2) { goto case AuthenticationModes.Basic; } throw new Exception(); case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); default: throw new ArgumentOutOfRangeException(nameof(modes), $"Unknown {nameof(AuthenticationModes)} value"); } } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); // If the GitHub auth stack doesn't support flows such as RFC 8628 and we do not have // an interactive desktop session, we cannot offer OAuth authentication. if ((modes & AuthenticationModes.OAuth) != 0 && !Context.SessionManager.IsDesktopSession && !GitHubConstants.IsOAuthDeviceAuthSupported) { Context.Trace.WriteLine("Ignoring OAuth authentication mode because we are not in an interactive desktop session. GitHub does not support RFC 8628."); modes &= ~AuthenticationModes.OAuth; } if (modes == AuthenticationModes.None) { throw new ArgumentException($"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.OAuth) != 0) { promptArgs.Append(" --oauth"); } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", targetUri.ToString()); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "oauth": return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case "basic": if (!resultDict.TryGetValue("username", out string userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult(new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic | AuthenticationModes.OAuth: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle) { new TerminalMenuItem(1, "Web browser"), new TerminalMenuItem(2, "Username/password", true) }; int option = menu.Show(); if (option == 1) { goto case AuthenticationModes.OAuth; } if (option == 2) { goto case AuthenticationModes.Basic; } throw new Exception(); case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); string userName = Context.Terminal.Prompt("Username"); string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); default: throw new ArgumentOutOfRangeException(nameof(modes), $"Unknown {nameof(AuthenticationModes)} value"); } } }
public async Task <AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes) { ThrowIfUserInteractionDisabled(); if (modes == AuthenticationModes.None) { throw new ArgumentException(@$ "Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } if (TryFindHelperExecutablePath(out string helperPath)) { var promptArgs = new StringBuilder("prompt"); if (modes == AuthenticationModes.All) { promptArgs.Append(" --all"); } else { if ((modes & AuthenticationModes.Basic) != 0) { promptArgs.Append(" --basic"); } if ((modes & AuthenticationModes.OAuth) != 0) { promptArgs.Append(" --oauth"); } if ((modes & AuthenticationModes.Pat) != 0) { promptArgs.Append(" --pat"); } } if (!GitHubHostProvider.IsGitHubDotCom(targetUri)) { promptArgs.AppendFormat(" --enterprise-url {0}", QuoteCmdArg(targetUri.ToString())); } if (!string.IsNullOrWhiteSpace(userName)) { promptArgs.AppendFormat(" --username {0}", QuoteCmdArg(userName)); } IDictionary <string, string> resultDict = await InvokeHelperAsync(helperPath, promptArgs.ToString(), null); if (!resultDict.TryGetValue("mode", out string responseMode)) { throw new Exception("Missing 'mode' in response"); } switch (responseMode.ToLowerInvariant()) { case "pat": if (!resultDict.TryGetValue("pat", out string pat)) { throw new Exception("Missing 'pat' in response"); } return(new AuthenticationPromptResult( AuthenticationModes.Pat, new GitCredential(userName, pat))); case "oauth": return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case "basic": if (!resultDict.TryGetValue("username", out userName)) { throw new Exception("Missing 'username' in response"); } if (!resultDict.TryGetValue("password", out string password)) { throw new Exception("Missing 'password' in response"); } return(new AuthenticationPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); default: throw new Exception($"Unknown mode value in response '{responseMode}'"); } } else { ThrowIfTerminalPromptsDisabled(); switch (modes) { case AuthenticationModes.Basic: Context.Terminal.WriteLine("Enter GitHub credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult( AuthenticationModes.Basic, new GitCredential(userName, password))); case AuthenticationModes.OAuth: return(new AuthenticationPromptResult(AuthenticationModes.OAuth)); case AuthenticationModes.Pat: Context.Terminal.WriteLine("Enter GitHub personal access token for '{0}'...", targetUri); string pat = Context.Terminal.PromptSecret("Token"); return(new AuthenticationPromptResult( AuthenticationModes.Pat, new GitCredential(userName, pat))); case AuthenticationModes.None: throw new ArgumentOutOfRangeException(nameof(modes), @$ "At least one {nameof(AuthenticationModes)} must be supplied"); default: var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle); TerminalMenuItem oauthItem = null; TerminalMenuItem basicItem = null; TerminalMenuItem patItem = null; if ((modes & AuthenticationModes.OAuth) != 0) { oauthItem = menu.Add("Web browser"); } if ((modes & AuthenticationModes.Pat) != 0) { patItem = menu.Add("Personal access token"); } if ((modes & AuthenticationModes.Basic) != 0) { basicItem = menu.Add("Username/password"); } // Default to the 'first' choice in the menu TerminalMenuItem choice = menu.Show(0); if (choice == oauthItem) { goto case AuthenticationModes.OAuth; } if (choice == basicItem) { goto case AuthenticationModes.Basic; } if (choice == patItem) { goto case AuthenticationModes.Pat; } throw new Exception(); } } }
public AuthenticationPromptResult GetAuthentication(Uri targetUri, string userName, AuthenticationModes modes) { // If we don't have a desktop session/GUI then we cannot offer browser if (!Context.SessionManager.IsDesktopSession) { modes = modes & ~AuthenticationModes.Browser; } // We need at least one mode! if (modes == AuthenticationModes.None) { throw new ArgumentException(@$ "Must specify at least one {nameof(AuthenticationModes)}", nameof(modes)); } switch (modes) { case AuthenticationModes.Basic: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); Context.Terminal.WriteLine("Enter GitLab credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string password = Context.Terminal.PromptSecret("Password"); return(new AuthenticationPromptResult(AuthenticationModes.Basic, new GitCredential(userName, password))); case AuthenticationModes.Pat: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); Context.Terminal.WriteLine("Enter GitLab credentials for '{0}'...", targetUri); if (string.IsNullOrWhiteSpace(userName)) { userName = Context.Terminal.Prompt("Username"); } else { Context.Terminal.WriteLine("Username: {0}", userName); } string token = Context.Terminal.PromptSecret("Personal access token"); return(new AuthenticationPromptResult(AuthenticationModes.Pat, new GitCredential(userName, token))); case AuthenticationModes.Browser: return(new AuthenticationPromptResult(AuthenticationModes.Browser)); case AuthenticationModes.None: throw new ArgumentOutOfRangeException(nameof(modes), @$ "At least one {nameof(AuthenticationModes)} must be supplied"); default: ThrowIfUserInteractionDisabled(); ThrowIfTerminalPromptsDisabled(); var menuTitle = $"Select an authentication method for '{targetUri}'"; var menu = new TerminalMenu(Context.Terminal, menuTitle); TerminalMenuItem browserItem = null; TerminalMenuItem basicItem = null; TerminalMenuItem patItem = null; if ((modes & AuthenticationModes.Browser) != 0) { browserItem = menu.Add("Web browser"); } if ((modes & AuthenticationModes.Pat) != 0) { patItem = menu.Add("Personal access token"); } if ((modes & AuthenticationModes.Basic) != 0) { basicItem = menu.Add("Username/password"); } // Default to the 'first' choice in the menu TerminalMenuItem choice = menu.Show(0); if (choice == browserItem) { goto case AuthenticationModes.Browser; } if (choice == basicItem) { goto case AuthenticationModes.Basic; } if (choice == patItem) { goto case AuthenticationModes.Pat; } throw new Exception(); } }