/// <summary> /// Identify the Hosting service from the the targetUri. /// <para/> /// Returns a `<see cref="BaseAuthentication"/>` instance if the `<paramref name="targetUri"/>` represents Bitbucket; otherwise `<see langword=""="null"/>`. /// </summary> /// <param name="targetUri"></param> public static BaseAuthentication GetAuthentication( RuntimeContext context, TargetUri targetUri, ICredentialStore personalAccessTokenStore, AcquireCredentialsDelegate acquireCredentialsCallback, AcquireAuthenticationOAuthDelegate acquireAuthenticationOAuthCallback) { BaseAuthentication authentication = null; BaseSecureStore.ValidateTargetUri(targetUri); if (personalAccessTokenStore == null) { throw new ArgumentNullException(nameof(personalAccessTokenStore), $"The `{nameof(personalAccessTokenStore)}` is null or invalid."); } if (targetUri.QueryUri.DnsSafeHost.EndsWith(BitbucketBaseUrlHost, StringComparison.OrdinalIgnoreCase)) { authentication = new Authentication(context, personalAccessTokenStore, acquireCredentialsCallback, acquireAuthenticationOAuthCallback); context.Trace.WriteLine("authentication for Bitbucket created"); } else { authentication = null; } return(authentication); }
private static void Erase() { // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html OperationArguments operationArguments = new OperationArguments(Console.In); Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); Trace.WriteLine("Program::Erase"); Trace.WriteLine(" targetUri = " + operationArguments.TargetUri); BaseAuthentication authentication = CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: authentication.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: BaseVsoAuthentication vsoAuth = authentication as BaseVsoAuthentication; vsoAuth.DeleteCredentials(operationArguments.TargetUri); break; } }
/// <summary> /// Gets a configured authentication object for 'github.com'. /// </summary> /// <param name="targetUri">The uniform resource indicator of the resource which requires /// authentication.</param> /// <param name="tokenScope">The desired scope of any personal access tokens acquired.</param> /// <param name="personalAccessTokenStore">A secure secret store for any personal access /// tokens acquired.</param> /// <param name="authentication">(out) The authentication object if successful.</param> /// <returns>True if success; otherwise false.</returns> public static BaseAuthentication GetAuthentication( TargetUri targetUri, TokenScope tokenScope, ICredentialStore personalAccessTokenStore, AcquireCredentialsDelegate acquireCredentialsCallback, AcquireAuthenticationCodeDelegate acquireAuthenticationCodeCallback, AuthenticationResultDelegate authenticationResultCallback) { const string GitHubBaseUrlHost = "github.com"; BaseAuthentication authentication = null; BaseSecureStore.ValidateTargetUri(targetUri); if (personalAccessTokenStore == null) { throw new ArgumentNullException("personalAccessTokenStore", "The `personalAccessTokenStore` is null or invalid."); } if (targetUri.DnsSafeHost.EndsWith(GitHubBaseUrlHost, StringComparison.OrdinalIgnoreCase)) { authentication = new Authentication(tokenScope, personalAccessTokenStore, acquireCredentialsCallback, acquireAuthenticationCodeCallback, authenticationResultCallback); Git.Trace.WriteLine($"created GitHub authentication for '{targetUri}'."); } else { authentication = null; Git.Trace.WriteLine($"not github.com, authentication creation aborted."); } return(authentication); }
/// <summary> /// Creates a new authentication broker based for the specified resource. /// <para/> /// Returns `<see langword="true"/>` if an authority could be determined; otherwise `<see langword="false"/>`. /// </summary> /// <param name="targetUri">The resource for which authentication is being requested.</param> /// <param name="scope">The scope of the access being requested.</param> /// <param name="personalAccessTokenStore">Storage container for personal access token secrets.</param> public static async Task <BaseAuthentication> GetAuthentication( RuntimeContext context, TargetUri targetUri, TokenScope scope, ICredentialStore personalAccessTokenStore) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (targetUri is null) { throw new ArgumentNullException(nameof(targetUri)); } if (scope is null) { throw new ArgumentNullException(nameof(scope)); } if (personalAccessTokenStore is null) { throw new ArgumentNullException(nameof(personalAccessTokenStore)); } BaseAuthentication authentication = null; var result = await DetectAuthority(context, targetUri); if (!result.HasValue) { return(null); } // Query for the tenant's identity Guid tenantId = result.Value; // empty identity is MSA, anything else is AAD if (tenantId == Guid.Empty) { context.Trace.WriteLine("MSA authority detected."); authentication = new MsaAuthentication(context, scope, personalAccessTokenStore); } else { context.Trace.WriteLine($"AAD authority for tenant '{tenantId}' detected."); authentication = new AadAuthentication(context, tenantId, scope, personalAccessTokenStore); (authentication as AadAuthentication).TenantId = tenantId; } return(authentication); }
internal void Store() { // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html using (var stdin = InStream) { OperationArguments operationArguments = new OperationArguments(stdin); Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.Username != null, "The operaionArgument.Username is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); var credentials = operationArguments.Credentials; var task = Task.Run(async() => { return(await CreateAuthentication(operationArguments)); }); BaseAuthentication authentication = task.Result; switch (operationArguments.Authority) { default: case AuthorityType.Basic: Git.Trace.WriteLine($"storing basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Bitbucket: Git.Trace.WriteLine($"storing Bitbucket credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"storing VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: Git.Trace.WriteLine($"storing GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: Git.Trace.WriteLine($"storing NTLM credentials for '{operationArguments.TargetUri}'."); break; } authentication.SetCredentials(operationArguments.TargetUri, credentials); } }
CreateImpersonationService(IUserInfo testUser, ImpersonationOptions options = null) { options ??= new ImpersonationOptions(); var httpContextAccessor = new FakeHttpContextAccessor(testUser?.IsUserRecognized == true ? testUser.UserName : null); var dataProtectionProvider = new FakeDataProtectionProvider(); BaseAuthentication baseUserInfo = new BaseAuthentication(new RhetosAspNetCoreIdentityUser(httpContextAccessor)); var log = new List <string>(); void logMonitor(EventType eventType, string eventName, Func <string> message) => log.Add($"[{eventType}] {eventName}: {message()}"); var logProvider = new ConsoleLogProvider(logMonitor); var impersonationService = new ImpersonationService(httpContextAccessor, dataProtectionProvider, logProvider, options ?? new ImpersonationOptions(), baseUserInfo); return(impersonationService, httpContextAccessor, log); }
public static async Task <bool> DeleteCredentials(Program program, OperationArguments operationArguments) { if (program is null) { throw new ArgumentNullException(nameof(program)); } if (operationArguments is null) { throw new ArgumentNullException(nameof(operationArguments)); } BaseAuthentication authentication = await program.CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: { program.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'."); return(await authentication.DeleteCredentials(operationArguments.TargetUri)); } case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: { program.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'."); var vstsAuth = authentication as Vsts.Authentication; return(await vstsAuth.DeleteCredentials(operationArguments.TargetUri)); } case AuthorityType.GitHub: { program.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'."); var ghAuth = authentication as Github.Authentication; return(await ghAuth.DeleteCredentials(operationArguments.TargetUri)); } case AuthorityType.Bitbucket: { program.Trace.WriteLine($"deleting Bitbucket credentials for '{operationArguments.TargetUri}'."); var bbAuth = authentication as Bitbucket.Authentication; return(await bbAuth.DeleteCredentials(operationArguments.TargetUri, operationArguments.Username)); } } }
/// <summary> /// Gets a configured authentication object for 'github.com'. /// <para/> /// Returns a `<see cref="Authentication"/>` if successful; otherwise `<see langword="null"/>`. /// </summary> /// <param name="targetUri">The uniform resource indicator of the resource which requires authentication.</param> /// <param name="tokenScope">The desired scope of any personal access tokens acquired.</param> /// <param name="personalAccessTokenStore">A secure secret store for any personal access tokens acquired.</param> /// <param name="authentication">(out) The authentication object if successful.</param> public static BaseAuthentication GetAuthentication( RuntimeContext context, TargetUri targetUri, TokenScope tokenScope, ICredentialStore personalAccessTokenStore, AcquireCredentialsDelegate acquireCredentialsCallback, AcquireAuthenticationCodeDelegate acquireAuthenticationCodeCallback, AuthenticationResultDelegate authenticationResultCallback) { if (context is null) { throw new ArgumentNullException(nameof(context)); } if (targetUri is null) { throw new ArgumentNullException(nameof(targetUri)); } if (personalAccessTokenStore is null) { throw new ArgumentNullException(nameof(personalAccessTokenStore)); } BaseAuthentication authentication = null; if (targetUri.DnsSafeHost.EndsWith(GitHubBaseUrlHost, StringComparison.OrdinalIgnoreCase)) { var normalizedTargetUri = NormalizeUri(targetUri); authentication = new Authentication(context, normalizedTargetUri, tokenScope, personalAccessTokenStore, acquireCredentialsCallback, acquireAuthenticationCodeCallback, authenticationResultCallback); context.Trace.WriteLine($"created GitHub authentication for '{normalizedTargetUri}'."); } else { authentication = null; } return(authentication); }
private static void Store() { // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html using (var stdin = Console.OpenStandardInput()) { OperationArguments operationArguments = new OperationArguments(stdin); Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.CredUsername != null, "The operaionArgument.Username is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); Credential credentials = new Credential(operationArguments.CredUsername, operationArguments.CredPassword); BaseAuthentication authentication = CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: Git.Trace.WriteLine($"storing basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"storing VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: Git.Trace.WriteLine($"storing GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: Git.Trace.WriteLine($"storing NTLM credentials for '{operationArguments.TargetUri}'."); break; } authentication.SetCredentials(operationArguments.TargetUri, credentials); } }
private static void Store() { // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html var stdin = Console.OpenStandardInput(); OperationArguments operationArguments = new OperationArguments(stdin); Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.CredUsername != null, "The operaionArgument.Username is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); BaseAuthentication authentication = CreateAuthentication(operationArguments); Credential credentials = new Credential(operationArguments.CredUsername, operationArguments.CredPassword); authentication.SetCredentials(operationArguments.TargetUri, credentials); }
public static void DeleteCredentials(Program program, OperationArguments operationArguments) { if (operationArguments is null) { throw new ArgumentNullException("operationArguments"); } var task = Task.Run(async() => { return(await program.CreateAuthentication(operationArguments)); }); BaseAuthentication authentication = task.Result; switch (operationArguments.Authority) { default: case AuthorityType.Basic: Git.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'."); authentication.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'."); var vstsAuth = authentication as BaseVstsAuthentication; vstsAuth.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.GitHub: Git.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'."); var ghAuth = authentication as Github.Authentication; ghAuth.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.Bitbucket: Git.Trace.WriteLine($"deleting Bitbucket credentials for '{operationArguments.TargetUri}'."); var bbAuth = authentication as Bitbucket.Authentication; bbAuth.DeleteCredentials(operationArguments.TargetUri, operationArguments.CredUsername); break; } }
internal void Delete() { string[] args = Settings.GetCommandLineArgs(); if (args.Length < 3) { goto error_parse; } string url = args[2]; Uri uri = null; if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) { if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } else { url = string.Format("{0}://{1}", Uri.UriSchemeHttps, url); if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } using (var stdin = InStream) { var operationArguments = new OperationArguments(_context) { QueryUri = uri }; Task.Run(async() => { await operationArguments.ReadInput(stdin); if (operationArguments.TargetUri is null) { var inner = new ArgumentNullException(nameof(operationArguments.TargetUri)); throw new ArgumentException(inner.Message, nameof(operationArguments), inner); } // Load operation arguments. await LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); // Set the parent window handle. ParentHwnd = operationArguments.ParentHwnd; BaseAuthentication authentication = await CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: _context.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: _context.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: _context.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: _context.Trace.WriteLine($"deleting NTLM credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Bitbucket: _context.Trace.WriteLine($"deleting Bitbucket credentials for '{operationArguments.Username}@{operationArguments.TargetUri}'."); break; } await authentication.DeleteCredentials(operationArguments.TargetUri, operationArguments.Username); }).Wait(); } return; error_parse: Die("Unable to parse target URI."); }
private static void Delete() { string[] args = Environment.GetCommandLineArgs(); if (args.Length < 3) { goto error_parse; } string url = args[2]; Uri uri = null; if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) { if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } else { url = String.Format("{0}://{1}", Uri.UriSchemeHttps, url); if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } using (var stdin = Console.OpenStandardInput()) { OperationArguments operationArguments = new OperationArguments(stdin); operationArguments.QueryUri = uri; LoadOperationArguments(operationArguments); BaseAuthentication authentication = CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: Git.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: Git.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: Git.Trace.WriteLine($"deleting NTLM credentials for '{operationArguments.TargetUri}'."); break; } authentication.DeleteCredentials(operationArguments.TargetUri); } return; error_parse: Die("Unable to parse target URI."); }
public static async Task <Credential> QueryCredentials(Program program, OperationArguments operationArguments) { if (program is null) { throw new ArgumentNullException(nameof(program)); } if (operationArguments is null) { throw new ArgumentNullException(nameof(operationArguments)); } if (operationArguments.TargetUri is null) { var innerException = new NullReferenceException($"{operationArguments.TargetUri} cannot be null."); throw new ArgumentException(innerException.Message, nameof(operationArguments), innerException); } BaseAuthentication authentication = await program.CreateAuthentication(operationArguments); Credential credentials = null; switch (operationArguments.Authority) { default: case AuthorityType.Basic: { var basicAuth = authentication as BasicAuthentication; // Attempt to get cached credentials or acquire credentials if interactivity is allowed. if ((operationArguments.Interactivity != Interactivity.Always && (credentials = await authentication.GetCredentials(operationArguments.TargetUri)) != null) || (operationArguments.Interactivity != Interactivity.Never && (credentials = await basicAuth.AcquireCredentials(operationArguments.TargetUri)) != null)) { program.Trace.WriteLine("credentials found."); // No need to save the credentials explicitly, as Git will call back // with a store command if the credentials are valid. } else { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } } break; case AuthorityType.AzureDirectory: { var aadAuth = authentication as VstsAadAuthentication; var patOptions = new PersonalAccessTokenOptions() { RequireCompactToken = true, TokenDuration = operationArguments.TokenDuration, TokenScope = null, }; // Attempt to get cached credentials -> non-interactive logon -> interactive // logon note that AAD "credentials" are always scoped access tokens. if (((operationArguments.Interactivity != Interactivity.Always && ((credentials = await aadAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) || (operationArguments.Interactivity != Interactivity.Always && ((credentials = await aadAuth.NoninteractiveLogon(operationArguments.TargetUri, patOptions)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await aadAuth.InteractiveLogon(operationArguments.TargetUri, patOptions)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"Azure Directory credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve Azure Directory credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } } break; case AuthorityType.MicrosoftAccount: { var msaAuth = authentication as VstsMsaAuthentication; var patOptions = new PersonalAccessTokenOptions() { RequireCompactToken = true, TokenDuration = operationArguments.TokenDuration, TokenScope = null, }; // Attempt to get cached credentials -> interactive logon note that MSA // "credentials" are always scoped access tokens. if (((operationArguments.Interactivity != Interactivity.Always && ((credentials = await msaAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await msaAuth.InteractiveLogon(operationArguments.TargetUri, patOptions)) != null) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"Microsoft Live credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve Microsoft Live credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } } break; case AuthorityType.GitHub: { var ghAuth = authentication as Github.Authentication; if ((operationArguments.Interactivity != Interactivity.Always && ((credentials = await ghAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await ghAuth.InteractiveLogon(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"GitHub credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve GitHub credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } } break; case AuthorityType.Bitbucket: { var bbcAuth = authentication as Bitbucket.Authentication; if (((operationArguments.Interactivity != Interactivity.Always) && ((credentials = await bbcAuth.GetCredentials(operationArguments.TargetUri, operationArguments.Username)) != null) && (!operationArguments.ValidateCredentials || ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.Username, credentials)) != null))) || ((operationArguments.Interactivity != Interactivity.Never) && ((credentials = await bbcAuth.InteractiveLogon(operationArguments.TargetUri, operationArguments.Username)) != null) && (!operationArguments.ValidateCredentials || ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.Username, credentials)) != null)))) { program.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); // Bitbucket relies on a username + secret, so make sure there is a // username to return. if (operationArguments.Username != null) { credentials = new Credential(operationArguments.Username, credentials.Password); } program.LogEvent($"Bitbucket credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { program.LogEvent($"Failed to retrieve Bitbucket credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } } break; case AuthorityType.Ntlm: { program.Trace.WriteLine($"'{operationArguments.TargetUri}' is NTLM."); credentials = BasicAuthentication.NtlmCredentials; } break; } if (credentials != null) { operationArguments.Credentials = credentials; } return(credentials); }
public static async Task <BaseAuthentication> CreateAuthentication(Program program, OperationArguments operationArguments) { if (operationArguments is null) { throw new ArgumentNullException(nameof(operationArguments)); } if (operationArguments.TargetUri is null) { var innerException = new NullReferenceException($"`{operationArguments.TargetUri}` cannot be null."); throw new ArgumentException(innerException.Message, nameof(operationArguments), innerException); } var secretsNamespace = operationArguments.CustomNamespace ?? Program.SecretsNamespace; BaseAuthentication authority = null; var basicCredentialCallback = (operationArguments.UseModalUi) ? new AcquireCredentialsDelegate(program.ModalPromptForCredentials) : new AcquireCredentialsDelegate(program.BasicCredentialPrompt); var bitbucketPrompts = new Bitbucket.AuthenticationPrompts(program.Context); var bitbucketCredentialCallback = (operationArguments.UseModalUi) ? bitbucketPrompts.CredentialModalPrompt : new Bitbucket.Authentication.AcquireCredentialsDelegate(program.BitbucketCredentialPrompt); var bitbucketOauthCallback = (operationArguments.UseModalUi) ? bitbucketPrompts.AuthenticationOAuthModalPrompt : new Bitbucket.Authentication.AcquireAuthenticationOAuthDelegate(program.BitbucketOAuthPrompt); var githubPrompts = new Github.AuthenticationPrompts(program.Context); var githubCredentialCallback = (operationArguments.UseModalUi) ? new Github.Authentication.AcquireCredentialsDelegate(githubPrompts.CredentialModalPrompt) : new Github.Authentication.AcquireCredentialsDelegate(program.GitHubCredentialPrompt); var githubAuthcodeCallback = (operationArguments.UseModalUi) ? new Github.Authentication.AcquireAuthenticationCodeDelegate(githubPrompts.AuthenticationCodeModalPrompt) : new Github.Authentication.AcquireAuthenticationCodeDelegate(program.GitHubAuthCodePrompt); NtlmSupport basicNtlmSupport = NtlmSupport.Auto; switch (operationArguments.Authority) { case AuthorityType.Auto: program.Trace.WriteLine($"detecting authority type for '{operationArguments.TargetUri}'."); // Detect the authority. authority = await BaseVstsAuthentication.GetAuthentication(program.Context, operationArguments.TargetUri, Program.VstsCredentialScope, new SecretStore(program.Context, secretsNamespace, BaseVstsAuthentication.UriNameConversion)) ?? Github.Authentication.GetAuthentication(program.Context, operationArguments.TargetUri, Program.GitHubCredentialScope, new SecretStore(program.Context, secretsNamespace, Secret.UriToName), githubCredentialCallback, githubAuthcodeCallback, null) ?? Bitbucket.Authentication.GetAuthentication(program.Context, operationArguments.TargetUri, new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl), bitbucketCredentialCallback, bitbucketOauthCallback); if (authority != null) { // Set the authority type based on the returned value. if (authority is VstsMsaAuthentication) { operationArguments.Authority = AuthorityType.MicrosoftAccount; goto case AuthorityType.MicrosoftAccount; } else if (authority is VstsAadAuthentication) { operationArguments.Authority = AuthorityType.AzureDirectory; goto case AuthorityType.AzureDirectory; } else if (authority is Github.Authentication) { operationArguments.Authority = AuthorityType.GitHub; goto case AuthorityType.GitHub; } else if (authority is Bitbucket.Authentication) { operationArguments.Authority = AuthorityType.Bitbucket; goto case AuthorityType.Bitbucket; } } goto default; case AuthorityType.AzureDirectory: program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Azure Directory."); Guid tenantId = Guid.Empty; // Get the identity of the tenant. var result = await BaseVstsAuthentication.DetectAuthority(program.Context, operationArguments.TargetUri); if (result.HasValue) { tenantId = result.Value; } // Return the allocated authority or a generic AAD backed VSTS authentication object. return(authority ?? new VstsAadAuthentication(program.Context, tenantId, operationArguments.VstsTokenScope, new SecretStore(program.Context, secretsNamespace, VstsAadAuthentication.UriNameConversion))); case AuthorityType.Basic: // Enforce basic authentication only. basicNtlmSupport = NtlmSupport.Never; goto default; case AuthorityType.GitHub: program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is GitHub."); // Return a GitHub authentication object. return(authority ?? new Github.Authentication(program.Context, operationArguments.TargetUri, Program.GitHubCredentialScope, new SecretStore(program.Context, secretsNamespace, Secret.UriToName), githubCredentialCallback, githubAuthcodeCallback, null)); case AuthorityType.Bitbucket: program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Bitbucket"); // Return a Bitbucket authentication object. return(authority ?? new Bitbucket.Authentication(program.Context, new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl), bitbucketCredentialCallback, bitbucketOauthCallback)); case AuthorityType.MicrosoftAccount: program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Microsoft Live."); // Return the allocated authority or a generic MSA backed VSTS authentication object. return(authority ?? new VstsMsaAuthentication(program.Context, operationArguments.VstsTokenScope, new SecretStore(program.Context, secretsNamespace, VstsMsaAuthentication.UriNameConversion))); case AuthorityType.Ntlm: // Enforce NTLM authentication only. basicNtlmSupport = NtlmSupport.Always; goto default; default: program.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is basic with NTLM={basicNtlmSupport}."); // Return a generic username + password authentication object. return(authority ?? new BasicAuthentication(program.Context, new SecretStore(program.Context, secretsNamespace, Secret.UriToIdentityUrl), basicNtlmSupport, basicCredentialCallback, null)); } }
private static void Delete() { Trace.WriteLine("Program::Erase"); string[] args = Environment.GetCommandLineArgs(); if (args.Length < 3) { goto error_parse; } string url = args[2]; Uri uri = null; if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) { if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } else { url = String.Format("{0}://{1}", Uri.UriSchemeHttps, url); if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } var stdin = Console.OpenStandardInput(); OperationArguments operationArguments = new OperationArguments(stdin); operationArguments.QueryUri = uri; LoadOperationArguments(operationArguments); BaseAuthentication authentication = CreateAuthentication(operationArguments); switch (operationArguments.Authority) { default: case AuthorityType.Basic: Trace.WriteLine(" deleting basic credentials"); authentication.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Trace.WriteLine(" deleting VSTS credentials"); BaseVstsAuthentication vstsAuth = authentication as BaseVstsAuthentication; vstsAuth.DeleteCredentials(operationArguments.TargetUri); // call delete twice to purge any stored ADA tokens vstsAuth.DeleteCredentials(operationArguments.TargetUri); break; case AuthorityType.GitHub: Trace.WriteLine(" deleting GitHub credentials"); GitHubAuthentication ghAuth = authentication as GitHubAuthentication; ghAuth.DeleteCredentials(operationArguments.TargetUri); break; } return; error_parse: Console.Error.WriteLine("Fatal: unable to parse target URI."); }
internal void Delete() { string[] args = Environment.GetCommandLineArgs(); if (args.Length < 3) { goto error_parse; } string url = args[2]; Uri uri = null; if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) { if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } else { url = string.Format("{0}://{1}", Uri.UriSchemeHttps, url); if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { goto error_parse; } } using (var stdin = InStream) { OperationArguments operationArguments = new OperationArguments(stdin) { QueryUri = uri }; LoadOperationArguments(operationArguments); var task = Task.Run(async() => { return(await CreateAuthentication(operationArguments)); }); BaseAuthentication authentication = task.Result; switch (operationArguments.Authority) { default: case AuthorityType.Basic: Git.Trace.WriteLine($"deleting basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"deleting VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: Git.Trace.WriteLine($"deleting GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: Git.Trace.WriteLine($"deleting NTLM credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Bitbucket: Git.Trace.WriteLine($"deleting Bitbucket credentials for '{operationArguments.Username}@{operationArguments.TargetUri}'."); break; } authentication.DeleteCredentials(operationArguments.TargetUri, operationArguments.Username); } return; error_parse: Die("Unable to parse target URI."); }
private static void Get() { const string AadMsaAuthFailureMessage = "Logon failed, use ctrl+c to cancel basic credential prompt."; const string GitHubAuthFailureMessage = "Logon failed, use ctrl+c to cancel basic credential prompt."; // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html OperationArguments operationArguments = new OperationArguments(Console.In); Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); Trace.WriteLine("Program::Get"); Trace.WriteLine(" targetUri = " + operationArguments.TargetUri); BaseAuthentication authentication = CreateAuthentication(operationArguments); Credential credentials = null; switch (operationArguments.Authority) { default: case AuthorityType.Basic: if (authentication.GetCredentials(operationArguments.TargetUri, out credentials)) { Trace.WriteLine(" credentials found"); operationArguments.SetCredentials(credentials); } break; case AuthorityType.AzureDirectory: VsoAadAuthentication aadAuth = authentication as VsoAadAuthentication; Task.Run(async() => { // attmempt to get cached creds -> refresh creds -> non-interactive logon -> interactive logon // note that AAD "credentials" are always scoped access tokens if (((operationArguments.Interactivity != Interactivity.Always && aadAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Always && await aadAuth.RefreshCredentials(operationArguments.TargetUri, true) && aadAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Always && await aadAuth.NoninteractiveLogon(operationArguments.TargetUri, true) && aadAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && aadAuth.InteractiveLogon(operationArguments.TargetUri, true)) && aadAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Trace.WriteLine(" credentials found"); operationArguments.SetCredentials(credentials); LogEvent("Azure Directory credentials for " + operationArguments.TargetUri + " successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Console.Error.WriteLine(AadMsaAuthFailureMessage); LogEvent("Failed to retrieve Azure Directory credentials for " + operationArguments.TargetUri + ".", EventLogEntryType.FailureAudit); } }).Wait(); break; case AuthorityType.MicrosoftAccount: VsoMsaAuthentication msaAuth = authentication as VsoMsaAuthentication; Task.Run(async() => { // attmempt to get cached creds -> refresh creds -> interactive logon // note that MSA "credentials" are always scoped access tokens if (((operationArguments.Interactivity != Interactivity.Always && msaAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Always && await msaAuth.RefreshCredentials(operationArguments.TargetUri, true) && msaAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && msaAuth.InteractiveLogon(operationArguments.TargetUri, true)) && msaAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Trace.WriteLine(" credentials found"); operationArguments.SetCredentials(credentials); LogEvent("Microsoft Live credentials for " + operationArguments.TargetUri + " successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Console.Error.WriteLine(AadMsaAuthFailureMessage); LogEvent("Failed to retrieve Microsoft Live credentials for " + operationArguments.TargetUri + ".", EventLogEntryType.FailureAudit); } }).Wait(); break; case AuthorityType.GitHub: GithubAuthentication ghAuth = authentication as GithubAuthentication; Task.Run(async() => { if ((operationArguments.Interactivity != Interactivity.Always && ghAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && ghAuth.InteractiveLogon(operationArguments.TargetUri, out credentials) && ghAuth.GetCredentials(operationArguments.TargetUri, out credentials) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Trace.WriteLine(" credentials found"); operationArguments.SetCredentials(credentials); LogEvent("GitHub credentials for " + operationArguments.TargetUri + " successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Console.Error.WriteLine(GitHubAuthFailureMessage); LogEvent("Failed to retrieve GitHub credentials for " + operationArguments.TargetUri + ".", EventLogEntryType.FailureAudit); } }).Wait(); break; case AuthorityType.Integrated: credentials = new Credential(String.Empty, String.Empty); operationArguments.SetCredentials(credentials); break; } Console.Out.Write(operationArguments); }
internal void Store() { // parse the operations arguments from stdin (this is how git sends commands) // see: https://www.kernel.org/pub/software/scm/git/docs/technical/api-credentials.html // see: https://www.kernel.org/pub/software/scm/git/docs/git-credential.html using (var stdin = InStream) { var operationArguments = new OperationArguments(_context); Task.Run(async() => { await operationArguments.ReadInput(stdin); if (operationArguments.TargetUri is null) { var inner = new ArgumentNullException(nameof(operationArguments.TargetUri)); throw new ArgumentException(inner.Message, nameof(operationArguments), inner); } if (operationArguments.Username is null) { var inner = new ArgumentNullException(nameof(operationArguments.Username)); throw new ArgumentException(inner.Message, nameof(operationArguments), inner); } // Load operation arguments. await LoadOperationArguments(operationArguments); EnableTraceLogging(operationArguments); // Read the details of any git-remote-http(s).exe parent process, but only if // an override hasn't been set which would override the git-remote details. if (string.IsNullOrEmpty(operationArguments.UrlOverride)) { ReadGitRemoteDetails(operationArguments); } // Set the parent window handle. ParentHwnd = operationArguments.ParentHwnd; var credentials = operationArguments.Credentials; BaseAuthentication authentication = await CreateAuthentication(operationArguments);; switch (operationArguments.Authority) { default: case AuthorityType.Basic: Trace.WriteLine($"storing basic credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Bitbucket: Trace.WriteLine($"storing Bitbucket credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.AzureDirectory: case AuthorityType.MicrosoftAccount: Trace.WriteLine($"storing VSTS credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.GitHub: Trace.WriteLine($"storing GitHub credentials for '{operationArguments.TargetUri}'."); break; case AuthorityType.Ntlm: Trace.WriteLine($"storing NTLM credentials for '{operationArguments.TargetUri}'."); break; } await authentication.SetCredentials(operationArguments.TargetUri, credentials); }).Wait(); } }
private static BaseAuthentication CreateAuthentication(OperationArguments operationArguments) { Debug.Assert(operationArguments != null, "The operationArguments is null"); Trace.WriteLine("Program::CreateAuthentication"); var secrets = new SecretStore(SecretsNamespace); BaseAuthentication authority = null; switch (operationArguments.Authority) { case AuthorityType.Auto: Trace.WriteLine(" detecting authority type"); // detect the authority if (BaseVsoAuthentication.GetAuthentication(operationArguments.TargetUri, VsoCredentialScope, secrets, null, out authority) || GithubAuthentication.GetAuthentication(operationArguments.TargetUri, GithubCredentialScope, secrets, out authority)) { // set the authority type based on the returned value if (authority is VsoMsaAuthentication) { operationArguments.Authority = AuthorityType.MicrosoftAccount; goto case AuthorityType.MicrosoftAccount; } else if (authority is VsoAadAuthentication) { operationArguments.Authority = AuthorityType.AzureDirectory; goto case AuthorityType.AzureDirectory; } else if (authority is GithubAuthentication) { operationArguments.Authority = AuthorityType.GitHub; goto case AuthorityType.GitHub; } } operationArguments.Authority = AuthorityType.Basic; goto case AuthorityType.Basic; case AuthorityType.AzureDirectory: Trace.WriteLine(" authority is Azure Directory"); Guid tenantId = Guid.Empty; // return the allocated authority or a generic AAD backed VSO authentication object return(authority ?? new VsoAadAuthentication(Guid.Empty, VsoCredentialScope, secrets)); case AuthorityType.Basic: default: Trace.WriteLine(" authority is basic"); // return a generic username + password authentication object return(authority ?? new BasicAuthentication(secrets)); case AuthorityType.GitHub: Trace.WriteLine(" authority it GitHub"); // return a GitHub authenitcation object return(authority ?? new GithubAuthentication(GithubCredentialScope, secrets)); case AuthorityType.MicrosoftAccount: Trace.WriteLine(" authority is Microsoft Live"); // return the allocated authority or a generic MSA backed VSO authentication object return(authority ?? new VsoMsaAuthentication(VsoCredentialScope, secrets)); } }
public static Credential QueryCredentials(Program program, OperationArguments operationArguments) { if (ReferenceEquals(operationArguments, null)) { throw new ArgumentNullException(nameof(operationArguments)); } if (ReferenceEquals(operationArguments.TargetUri, null)) { throw new ArgumentException("TargetUri property returned null", nameof(operationArguments)); } var task = Task.Run(async() => { return(await program.CreateAuthentication(operationArguments)); }); BaseAuthentication authentication = task.Result; Credential credentials = null; switch (operationArguments.Authority) { default: case AuthorityType.Basic: { BasicAuthentication basicAuth = authentication as BasicAuthentication; Task.Run(async() => { // attempt to get cached creds or acquire creds if interactivity is allowed if ((operationArguments.Interactivity != Interactivity.Always && (credentials = authentication.GetCredentials(operationArguments.TargetUri)) != null) || (operationArguments.Interactivity != Interactivity.Never && (credentials = await basicAuth.AcquireCredentials(operationArguments.TargetUri)) != null)) { Git.Trace.WriteLine("credentials found."); // no need to save the credentials explicitly, as Git will call back with // a store command if the credentials are valid. } else { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } }).Wait(); } break; case AuthorityType.AzureDirectory: { VstsAadAuthentication aadAuth = authentication as VstsAadAuthentication; Task.Run(async() => { // attempt to get cached creds -> non-interactive logon -> interactive // logon note that AAD "credentials" are always scoped access tokens if (((operationArguments.Interactivity != Interactivity.Always && ((credentials = aadAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) || (operationArguments.Interactivity != Interactivity.Always && ((credentials = await aadAuth.NoninteractiveLogon(operationArguments.TargetUri, true)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await aadAuth.InteractiveLogon(operationArguments.TargetUri, true)) != null) && (!operationArguments.ValidateCredentials || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"Azure Directory credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve Azure Directory credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } }).Wait(); } break; case AuthorityType.MicrosoftAccount: { VstsMsaAuthentication msaAuth = authentication as VstsMsaAuthentication; Task.Run(async() => { // attempt to get cached creds -> interactive logon note that MSA // "credentials" are always scoped access tokens if (((operationArguments.Interactivity != Interactivity.Always && ((credentials = msaAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await msaAuth.InteractiveLogon(operationArguments.TargetUri, true)) != null) && (!operationArguments.ValidateCredentials || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"Microsoft Live credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve Microsoft Live credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } }).Wait(); } break; case AuthorityType.GitHub: { Github.Authentication ghAuth = authentication as Github.Authentication; Task.Run(async() => { if ((operationArguments.Interactivity != Interactivity.Always && ((credentials = ghAuth.GetCredentials(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) || (operationArguments.Interactivity != Interactivity.Never && ((credentials = await ghAuth.InteractiveLogon(operationArguments.TargetUri)) != null) && (!operationArguments.ValidateCredentials || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); program.LogEvent($"GitHub credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found."); program.LogEvent($"Failed to retrieve GitHub credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } }).Wait(); } break; case AuthorityType.Bitbucket: { var bbcAuth = authentication as Bitbucket.Authentication; Task.Run(async() => { if (((operationArguments.Interactivity != Interactivity.Always) && ((credentials = bbcAuth.GetCredentials(operationArguments.TargetUri, operationArguments.CredUsername)) != null) && (!operationArguments.ValidateCredentials || ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.CredUsername, credentials)) != null))) || ((operationArguments.Interactivity != Interactivity.Never) && ((credentials = await bbcAuth.InteractiveLogon(operationArguments.TargetUri, operationArguments.CredUsername)) != null) && (!operationArguments.ValidateCredentials || ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.CredUsername, credentials)) != null)))) { Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found."); // Bitbucket relies on a username + secret, so make sure there is a // username to return if (operationArguments.CredUsername != null) { credentials = new Credential(operationArguments.CredUsername, credentials.Password); } program.LogEvent($"Bitbucket credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit); } else { program.LogEvent($"Failed to retrieve Bitbucket credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit); } }).Wait(); } break; case AuthorityType.Ntlm: { Git.Trace.WriteLine($"'{operationArguments.TargetUri}' is NTLM."); credentials = BasicAuthentication.NtlmCredentials; } break; } if (credentials != null) { operationArguments.SetCredentials(credentials); } return(credentials); }
public static async Task <BaseAuthentication> CreateAuthentication(Program program, OperationArguments operationArguments) { Debug.Assert(operationArguments != null, "The operationArguments is null"); Debug.Assert(operationArguments.TargetUri != null, "The operationArgument.TargetUri is null"); var secretsNamespace = operationArguments.CustomNamespace ?? Program.SecretsNamespace; var secrets = new SecretStore(secretsNamespace, null, null, Secret.UriToName); BaseAuthentication authority = null; var basicCredentialCallback = (operationArguments.UseModalUi) ? new AcquireCredentialsDelegate(program.ModalPromptForCredentials) : new AcquireCredentialsDelegate(program.BasicCredentialPrompt); var bitbucketCredentialCallback = (operationArguments.UseModalUi) ? Bitbucket.AuthenticationPrompts.CredentialModalPrompt : new Bitbucket.Authentication.AcquireCredentialsDelegate(program.BitbucketCredentialPrompt); var bitbucketOauthCallback = (operationArguments.UseModalUi) ? Bitbucket.AuthenticationPrompts.AuthenticationOAuthModalPrompt : new Bitbucket.Authentication.AcquireAuthenticationOAuthDelegate(program.BitbucketOAuthPrompt); var githubCredentialCallback = (operationArguments.UseModalUi) ? new Github.Authentication.AcquireCredentialsDelegate(Github.AuthenticationPrompts.CredentialModalPrompt) : new Github.Authentication.AcquireCredentialsDelegate(program.GitHubCredentialPrompt); var githubAuthcodeCallback = (operationArguments.UseModalUi) ? new Github.Authentication.AcquireAuthenticationCodeDelegate(Github.AuthenticationPrompts.AuthenticationCodeModalPrompt) : new Github.Authentication.AcquireAuthenticationCodeDelegate(program.GitHubAuthCodePrompt); NtlmSupport basicNtlmSupport = NtlmSupport.Auto; switch (operationArguments.Authority) { case AuthorityType.Auto: Git.Trace.WriteLine($"detecting authority type for '{operationArguments.TargetUri}'."); // detect the authority authority = await BaseVstsAuthentication.GetAuthentication(operationArguments.TargetUri, Program.VstsCredentialScope, secrets) ?? Github.Authentication.GetAuthentication(operationArguments.TargetUri, Program.GitHubCredentialScope, secrets, githubCredentialCallback, githubAuthcodeCallback, null) ?? Bitbucket.Authentication.GetAuthentication(operationArguments.TargetUri, new SecretStore(secretsNamespace, Secret.UriToActualUrl), bitbucketCredentialCallback, bitbucketOauthCallback); if (authority != null) { // set the authority type based on the returned value if (authority is VstsMsaAuthentication) { operationArguments.Authority = AuthorityType.MicrosoftAccount; goto case AuthorityType.MicrosoftAccount; } else if (authority is VstsAadAuthentication) { operationArguments.Authority = AuthorityType.AzureDirectory; goto case AuthorityType.AzureDirectory; } else if (authority is Github.Authentication) { operationArguments.Authority = AuthorityType.GitHub; goto case AuthorityType.GitHub; } else if (authority is Bitbucket.Authentication) { operationArguments.Authority = AuthorityType.Bitbucket; goto case AuthorityType.Bitbucket; } } goto default; case AuthorityType.AzureDirectory: Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Azure Directory."); Guid tenantId = Guid.Empty; // Get the identity of the tenant. var result = await BaseVstsAuthentication.DetectAuthority(operationArguments.TargetUri); if (result.Key) { tenantId = result.Value; } // return the allocated authority or a generic AAD backed VSTS authentication object return(authority ?? new VstsAadAuthentication(tenantId, Program.VstsCredentialScope, secrets)); case AuthorityType.Basic: // enforce basic authentication only basicNtlmSupport = NtlmSupport.Never; goto default; case AuthorityType.GitHub: Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is GitHub."); // return a GitHub authentication object return(authority ?? new Github.Authentication(operationArguments.TargetUri, Program.GitHubCredentialScope, secrets, githubCredentialCallback, githubAuthcodeCallback, null)); case AuthorityType.Bitbucket: Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Bitbucket"); // return a Bitbucket authentication object return(authority ?? new Bitbucket.Authentication(secrets, bitbucketCredentialCallback, bitbucketOauthCallback)); case AuthorityType.MicrosoftAccount: Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is Microsoft Live."); // return the allocated authority or a generic MSA backed VSTS authentication object return(authority ?? new VstsMsaAuthentication(Program.VstsCredentialScope, secrets)); case AuthorityType.Ntlm: // enforce NTLM authentication only basicNtlmSupport = NtlmSupport.Always; goto default; default: Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is basic with NTLM={basicNtlmSupport}."); // return a generic username + password authentication object return(authority ?? new BasicAuthentication(secrets, basicNtlmSupport, basicCredentialCallback, null)); } }