Ejemplo n.º 1
0
        public override async Task <ICredential> GenerateCredentialAsync(InputArguments input)
        {
            ThrowIfDisposed();

            // We should not allow unencrypted communication and should inform the user
            if (StringComparer.OrdinalIgnoreCase.Equals(input.Protocol, "http"))
            {
                throw new Exception("Unencrypted HTTP is not supported for GitHub. Ensure the repository remote URL is using HTTPS.");
            }

            Uri remoteUri = input.GetRemoteUri();

            string service = GetServiceName(input);

            AuthenticationModes authModes = await GetSupportedAuthenticationModesAsync(remoteUri);

            AuthenticationPromptResult promptResult = await _gitHubAuth.GetAuthenticationAsync(remoteUri, input.UserName, authModes);

            switch (promptResult.AuthenticationMode)
            {
            case AuthenticationModes.Basic:
                GitCredential patCredential = await GeneratePersonalAccessTokenAsync(remoteUri, promptResult.Credential);

                // HACK: Store the PAT immediately in case this PAT is not valid for SSO.
                // We don't know if this PAT is valid for SAML SSO and if it's not Git will fail
                // with a 403 and call neither 'store' or 'erase'. The user is expected to fiddle with
                // the PAT permissions manually on the web and then retry the Git operation.
                // We must store the PAT now so they can resume/repeat the operation with the same,
                // now SSO authorized, PAT.
                // See: https://github.com/GitCredentialManager/git-credential-manager/issues/133
                Context.CredentialStore.AddOrUpdate(service, patCredential.Account, patCredential.Password);
                return(patCredential);

            case AuthenticationModes.Browser:
                return(await GenerateOAuthCredentialAsync(remoteUri, useBrowser : true));

            case AuthenticationModes.Device:
                return(await GenerateOAuthCredentialAsync(remoteUri, useBrowser : false));

            case AuthenticationModes.Pat:
                // The token returned by the user should be good to use directly as the password for Git
                string token = promptResult.Credential.Password;

                // Resolve the GitHub user handle if we don't have a specific username already from the
                // initial request. The reason for this is GitHub requires a (any?) value for the username
                // when Git makes calls to GitHub.
                string userName = promptResult.Credential.Account;
                if (userName is null)
                {
                    GitHubUserInfo userInfo = await _gitHubApi.GetUserInfoAsync(remoteUri, token);

                    userName = userInfo.Login;
                }

                return(new GitCredential(userName, token));

            default:
                throw new ArgumentOutOfRangeException(nameof(promptResult));
            }
        }
Ejemplo n.º 2
0
        public override async Task <ICredential> GenerateCredentialAsync(InputArguments input)
        {
            ThrowIfDisposed();

            // We should not allow unencrypted communication and should inform the user
            if (StringComparer.OrdinalIgnoreCase.Equals(input.Protocol, "http"))
            {
                throw new Exception("Unencrypted HTTP is not supported for GitHub. Ensure the repository remote URL is using HTTPS.");
            }

            Uri remoteUri = input.GetRemoteUri();

            string service = GetServiceName(input);

            AuthenticationModes authModes = await GetSupportedAuthenticationModesAsync(remoteUri);

            AuthenticationPromptResult promptResult = await _gitHubAuth.GetAuthenticationAsync(remoteUri, input.UserName, authModes);

            switch (promptResult.AuthenticationMode)
            {
            case AuthenticationModes.Basic:
                GitCredential patCredential = await GeneratePersonalAccessTokenAsync(remoteUri, promptResult.BasicCredential);

                // HACK: Store the PAT immediately in case this PAT is not valid for SSO.
                // We don't know if this PAT is valid for SAML SSO and if it's not Git will fail
                // with a 403 and call neither 'store' or 'erase'. The user is expected to fiddle with
                // the PAT permissions manually on the web and then retry the Git operation.
                // We must store the PAT now so they can resume/repeat the operation with the same,
                // now SSO authorized, PAT.
                // See: https://github.com/microsoft/Git-Credential-Manager-Core/issues/133
                Context.CredentialStore.AddOrUpdate(service, patCredential.Account, patCredential.Password);
                return(patCredential);

            case AuthenticationModes.OAuth:
                return(await GenerateOAuthCredentialAsync(remoteUri));

            default:
                throw new ArgumentOutOfRangeException(nameof(promptResult));
            }
        }