/// <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);
        }
Example #2
0
        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;
            }
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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);
        }
Example #5
0
        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));
            }
            }
        }
Example #8
0
        /// <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);
            }
        }
Example #10
0
        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);
        }
Example #11
0
        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));
            }
        }
Example #16
0
        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.");
        }
Example #17
0
        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.");
        }
Example #18
0
        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();
            }
        }
Example #20
0
        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));
            }
        }