/// <summary> /// Gets a list of token provider executables to call to get token. /// </summary> /// <param name="visualStudioTokenProviderFile">Visual Studio Token provider file</param> /// <param name="resource"></param> /// <param name="tenant"></param> /// <returns></returns> private List <ProcessStartInfo> GetProcessStartInfos(VisualStudioTokenProviderFile visualStudioTokenProviderFile, string resource, string tenant = default(string)) { List <ProcessStartInfo> processStartInfos = new List <ProcessStartInfo>(); foreach (var tokenProvider in visualStudioTokenProviderFile.TokenProviders) { // If file does not exist, the version of Visual Studio that set the token provider may be uninstalled. if (File.Exists(tokenProvider.Path)) { string arguments = $"{ResourceArgumentName} {resource} "; if (tenant != default(string)) { arguments += $"{TenantArgumentName} {tenant} "; } // Add the arguments set in the token provider file. if (tokenProvider.Arguments?.Count > 0) { arguments += string.Join(" ", tokenProvider.Arguments); } var startInfo = new ProcessStartInfo { FileName = tokenProvider.Path, Arguments = arguments }; processStartInfos.Add(startInfo); } } return(processStartInfos); }
internal VisualStudioAccessTokenProvider(IProcessManager processManager, VisualStudioTokenProviderFile visualStudioTokenProviderFile = null) { _visualStudioTokenProviderFile = visualStudioTokenProviderFile; _processManager = processManager; PrincipalUsed = new Principal { Type = "User" }; }
/// <summary> /// Gets the token provider file from user's local appdata folder. /// </summary> /// <returns></returns> private VisualStudioTokenProviderFile GetTokenProviderFile() { if (string.IsNullOrEmpty(EnvironmentHelper.GetEnvironmentVariable(LocalAppDataPathEnv))) { throw new Exception(NoAppDataEnvironmentVariableError); } string tokenProviderPath = Path.Combine(EnvironmentHelper.GetEnvironmentVariable(LocalAppDataPathEnv), TokenProviderFilePath); if (!File.Exists(tokenProviderPath)) { throw new Exception($"{TokenProviderFileNotFound} \"{tokenProviderPath}\""); } return(VisualStudioTokenProviderFile.Parse(File.ReadAllText(tokenProviderPath))); }
public override async Task <AppAuthenticationResult> GetAuthResultAsync(string resource, string authority, CancellationToken cancellationToken = default(CancellationToken)) { try { // Validate resource, since it gets sent as a command line argument to Visual Studio token provider. ValidationHelper.ValidateResource(resource); _visualStudioTokenProviderFile = _visualStudioTokenProviderFile ?? GetTokenProviderFile(); // Get process start infos based on Visual Studio token providers var processStartInfos = GetProcessStartInfos(_visualStudioTokenProviderFile, resource, UriHelper.GetTenantByAuthority(authority)); // To hold reason why token could not be acquired per token provider tried. Dictionary <string, string> exceptionDictionary = new Dictionary <string, string>(); foreach (var startInfo in processStartInfos) { try { // For each of them, try to get token string response = await _processManager .ExecuteAsync(new Process { StartInfo = startInfo }, cancellationToken) .ConfigureAwait(false); TokenResponse tokenResponse = TokenResponse.Parse(response); AccessToken token = AccessToken.Parse(tokenResponse.AccessToken); PrincipalUsed.IsAuthenticated = true; if (token != null) { // Set principal used based on the claims in the access token. PrincipalUsed.UserPrincipalName = !string.IsNullOrEmpty(token.Upn) ? token.Upn : token.Email; PrincipalUsed.TenantId = token.TenantId; } return(AppAuthenticationResult.Create(tokenResponse)); } catch (Exception exp) { // If token cannot be acquired using a token provider, try the next one exceptionDictionary[Path.GetFileName(startInfo.FileName)] = exp.Message; } } // Could not acquire access token, throw exception string message = string.Empty; // Include exception details for each token provider that was tried foreach (string key in exceptionDictionary.Keys) { message += Environment.NewLine + $"Exception for Visual Studio token provider {key} : {exceptionDictionary[key]} "; } // Throw exception if none of the token providers worked throw new Exception(message); } catch (Exception exp) { throw new AzureServiceTokenProviderException(ConnectionString, resource, authority, $"{AzureServiceTokenProviderException.VisualStudioUsed} {AzureServiceTokenProviderException.GenericErrorMessage} {exp.Message}"); } }