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 <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);
        }
Example #3
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);
        }