< Summary

Class:Azure.Identity.VisualStudioCodeCredential
Assembly:Azure.Identity
File(s):C:\Git\azure-sdk-for-net\sdk\identity\Azure.Identity\src\VisualStudioCodeCredential.cs
Covered lines:48
Uncovered lines:9
Coverable lines:57
Total lines:156
Line coverage:84.2% (48 of 57)
Covered branches:46
Total branches:54
Branch coverage:85.1% (46 of 54)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor()-100%100%
.ctor(...)-0%100%
.ctor(...)-100%100%
GetTokenAsync()-100%100%
GetToken(...)-100%100%
GetTokenImplAsync()-100%100%
IsRefreshTokenString(...)-100%100%
GetUserSettings(...)-100%100%
GetVscAdapter()-28.57%16.67%
GetAzureCloudInstance(...)-62.5%62.5%

File(s)

C:\Git\azure-sdk-for-net\sdk\identity\Azure.Identity\src\VisualStudioCodeCredential.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.IO;
 6using System.Linq;
 7using System.Runtime.InteropServices;
 8using System.Text.Json;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using Azure.Core;
 12using Azure.Core.Pipeline;
 13using Microsoft.Identity.Client;
 14
 15namespace Azure.Identity
 16{
 17    /// <summary>
 18    /// Enables authentication to Azure Active Directory using data from Visual Studio Code.
 19    /// </summary>
 20    public class VisualStudioCodeCredential : TokenCredential
 21    {
 22        private const string CredentialsSection = "VS Code Azure";
 23        private const string ClientId = "aebc6443-996d-45c2-90f0-388ff96faa56";
 24        private readonly IVisualStudioCodeAdapter _vscAdapter;
 25        private readonly IFileSystemService _fileSystem;
 26        private readonly CredentialPipeline _pipeline;
 27        private readonly string _tenantId;
 28        private readonly MsalPublicClient _client;
 29
 30        /// <summary>
 31        /// Creates a new instance of the <see cref="VisualStudioCodeCredential"/>.
 32        /// </summary>
 6433        public VisualStudioCodeCredential() : this(default, default, default, default, default) { }
 34
 35        /// <summary>
 36        /// Creates a new instance of the <see cref="VisualStudioCodeCredential"/> with the specified options.
 37        /// </summary>
 38        /// <param name="options">Options for configuring the credential.</param>
 039        public VisualStudioCodeCredential(VisualStudioCodeCredentialOptions options) : this(options, default, default, d
 40
 9841        internal VisualStudioCodeCredential(VisualStudioCodeCredentialOptions options, CredentialPipeline pipeline, Msal
 42        {
 9843            _tenantId = options?.TenantId ?? "common";
 9844            _pipeline = pipeline ?? CredentialPipeline.GetInstance(options);
 9845            _client = client ?? new MsalPublicClient(_pipeline, options?.TenantId, ClientId, null, null);
 9846            _fileSystem = fileSystem ?? FileSystemService.Default;
 9847            _vscAdapter = vscAdapter ?? GetVscAdapter();
 9848        }
 49
 50        /// <inheritdoc />
 51        public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken
 4652            => await GetTokenImplAsync(requestContext, true, cancellationToken).ConfigureAwait(false);
 53
 54        /// <inheritdoc />
 55        public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
 4856            => GetTokenImplAsync(requestContext, false, cancellationToken).EnsureCompleted();
 57
 58        private async ValueTask<AccessToken> GetTokenImplAsync(TokenRequestContext requestContext, bool async, Cancellat
 59        {
 9460            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("VisualStudioCodeCredential.GetToken", 
 61
 62            try
 63            {
 9064                GetUserSettings(out var tenant, out var environmentName);
 65
 9066                var cloudInstance = GetAzureCloudInstance(environmentName);
 9067                var storedCredentials = _vscAdapter.GetCredentials(CredentialsSection, environmentName);
 68
 7269                if (!IsRefreshTokenString(storedCredentials))
 70                {
 871                    throw new CredentialUnavailableException("Need to re-authenticate user in VSCode Azure Account.");
 72                }
 73
 6474                var result = await _client.AcquireTokenByRefreshToken(requestContext.Scopes, storedCredentials, cloudIns
 6075                return scope.Succeeded(new AccessToken(result.AccessToken, result.ExpiresOn));
 76            }
 477            catch (MsalUiRequiredException e)
 78            {
 479                throw scope.FailWrapAndThrow(new CredentialUnavailableException($"{nameof(VisualStudioCodeCredential)} a
 80            }
 2681            catch (Exception e)
 82            {
 2683                throw scope.FailWrapAndThrow(e);
 84            }
 6085        }
 86
 87        private static bool IsRefreshTokenString(string str)
 88        {
 475289            for (var index = 0; index < str.Length; index++)
 90            {
 231291                var ch = (uint)str[index];
 231292                if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && ch != '_' && ch != '-'
 93                {
 894                    return false;
 95                }
 96            }
 97
 6498            return true;
 99        }
 100
 101        private void GetUserSettings(out string tenant, out string environmentName)
 102        {
 90103            var path = _vscAdapter.GetUserSettingsPath();
 90104            tenant = _tenantId;
 90105            environmentName = "Azure";
 106
 107            try
 108            {
 90109                var content = _fileSystem.ReadAllText(path);
 78110                var root = JsonDocument.Parse(content).RootElement;
 111
 74112                if (root.TryGetProperty("azure.tenant", out JsonElement tenantProperty))
 113                {
 74114                    tenant = tenantProperty.GetString();
 115                }
 116
 74117                if (root.TryGetProperty("azure.cloud", out JsonElement environmentProperty))
 118                {
 48119                    environmentName = environmentProperty.GetString();
 120                }
 74121            }
 24122            catch (IOException) { }
 8123            catch (JsonException) { }
 90124        }
 125
 126        private static IVisualStudioCodeAdapter GetVscAdapter()
 127        {
 58128            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
 129            {
 58130                return new WindowsVisualStudioCodeAdapter();
 131            }
 132
 0133            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
 134            {
 0135                return new MacosVisualStudioCodeAdapter();
 136            }
 137
 0138            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
 139            {
 0140                return new LinuxVisualStudioCodeAdapter();
 141            }
 142
 0143            throw new PlatformNotSupportedException();
 144        }
 145
 146        private static AzureCloudInstance GetAzureCloudInstance(string name) =>
 90147            name switch
 90148            {
 132149                "Azure" => AzureCloudInstance.AzurePublic,
 0150                "AzureChina" => AzureCloudInstance.AzureChina,
 0151                "AzureGermanCloud" => AzureCloudInstance.AzureGermany,
 0152                "AzureUSGovernment" => AzureCloudInstance.AzureUsGovernment,
 138153                _ => AzureCloudInstance.AzurePublic
 90154            };
 155    }
 156}