private async Task <ICredential> GeneratePersonalAccessTokenAsync(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 Azure Repos. Ensure the repository remote URL is using HTTPS."); } Uri remoteUri = input.GetRemoteUri(); Uri orgUri = UriHelpers.CreateOrganizationUri(remoteUri, out _); // Determine the MS authentication authority for this organization _context.Trace.WriteLine("Determining Microsoft Authentication Authority..."); string authAuthority = await _azDevOps.GetAuthorityAsync(orgUri); _context.Trace.WriteLine($"Authority is '{authAuthority}'."); // Get an AAD access token for the Azure DevOps SPS _context.Trace.WriteLine("Getting Azure AD access token..."); IMicrosoftAuthenticationResult result = await _msAuth.GetTokenAsync( authAuthority, GetClientId(), GetRedirectUri(), AzureDevOpsConstants.AzureDevOpsDefaultScopes, null); _context.Trace.WriteLineSecrets( $"Acquired Azure access token. Account='{result.AccountUpn}' Token='{{0}}'", new object[] { result.AccessToken }); // Ask the Azure DevOps instance to create a new PAT var patScopes = new[] { AzureDevOpsConstants.PersonalAccessTokenScopes.ReposWrite, AzureDevOpsConstants.PersonalAccessTokenScopes.ArtifactsRead }; _context.Trace.WriteLine($"Creating Azure DevOps PAT with scopes '{string.Join(", ", patScopes)}'..."); string pat = await _azDevOps.CreatePersonalAccessTokenAsync( orgUri, result.AccessToken, patScopes); _context.Trace.WriteLineSecrets("PAT created. PAT='{0}'", new object[] { pat }); return(new GitCredential(result.AccountUpn, pat)); }