2
votes

In my application I am getting exception when my application fetches value of first key vault secret.

The exception I am only getting when I turn on "Common Language Run-time Exceptions" from exception settings.

Exception that I am getting is- Microsoft.Rest.TransientFaultHandling.HttpRequestWithStatusException: 'Response status code indicates server error: 401 (Unauthorized).'

StackTrace:-

at Microsoft.Rest.RetryDelegatingHandler.<>c__DisplayClass11_0.<<SendAsync>b__1>d.MoveNext()

My code to fetch the key vault secret is given below-

public async Task<string> GetSecretValue(string clientId, string appKey, string secretIdentifier)
{
    IAdAuthentication authToken = new AdAuthentication
    {
        ClientId = clientId,
        AppKey = appKey
    };
    KeyVaultClient keyVaultClient = new KeyVaultClient(authToken.GetAuthenticationTokenAsync);

    // Get secret from the KeyVault.
    SecretBundle secret = await keyVaultClient.GetSecretAsync(secretIdentifier);

    string secretValue = string.Empty;
    if (secret?.Value != null)
    {
        secretValue = secret.Value.Trim();
    }
    return secretValue;
}

Interface IAdAuthentication

public interface IAdAuthentication
{
    string ClientId { get; set; }

    string AppKey { get; set; }

    /// <summary>
    /// Get Authentication Token
    /// </summary>
    /// <param name="authority"></param>
    /// <param name="resource"></param>
    /// <param name="scope"></param>
    /// <returns></returns>
    Task<string> GetAuthenticationTokenAsync(string authority, string resource, string scope);
}

Implementation of interface IAdAuthentication is in class AdAuthentication

public class AdAuthentication : IAdAuthentication
{
    public string ClientId { get; set; }

    public string AppKey { get; set; }

    /// <summary>
    /// Get Authentication Token
    /// </summary>
    /// <param name="authority"></param>
    /// <param name="resource"></param>
    /// <param name="scope"></param>
    /// <returns></returns>
    public async Task<string> GetAuthenticationTokenAsync(string authority, string resource, string scope)
    {
        if (string.IsNullOrEmpty(authority))
            throw new ArgumentNullException(nameof(authority));
        if (string.IsNullOrEmpty(resource))
            throw new ArgumentNullException(nameof(resource));
        if (string.IsNullOrEmpty(ClientId))
            throw new ArgumentNullException(nameof(ClientId));
        if (string.IsNullOrEmpty(AppKey))
            throw new ArgumentNullException(nameof(AppKey));

        ClientCredential clientCredential = new ClientCredential(ClientId, AppKey);
        AuthenticationContext context = new AuthenticationContext(authority, false, TokenCache.DefaultShared);
        AuthenticationResult result = await context.AcquireTokenAsync(resource, clientCredential);
        return result.AccessToken;
    }
}

Above given exception is being thrown when I fetch the value of first key vault secret for the application instance and it doesn't matter what is the value of first secret identifier. For all next key vault secret exception doesn't occur. Along with exception value of first key vault secret is also being fetched but I want to mitigate this exception from my application. It seems issue is around AuthenticationCallback which is passed to initialize KeyVaultClient. Please let me know what I am missing here.

Adding screenshot of fiddler tracing and also added detailed fiddler tracing- enter image description here

-------------------------------------------------------------
CONNECT mykeyvault.vault.azure.net:443 HTTP/1.0
Host: mykeyvault.vault.azure.net:443
Content-Length: 0
Proxy-Connection: Keep-Alive
Pragma: no-cache

A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.

Version: 3.3 (TLS/1.2)
Random: 5B D6 D9 74 4F 81 32 0A 1D CB 8F DF E2 1F 2A 87 EC C2 98 A7 CA 6F EF DF 50 4E 1F 11 7D D7 7D 8F
"Time": 2/15/2032 10:17:23 AM
SessionID: empty
Extensions: 
    server_name mykeyvault.vault.azure.net
    status_request  OCSP - Implicit Responder
    elliptic_curves unknown [0x1D), secp256r1 [0x17], secp384r1 [0x18]
    ec_point_formats    uncompressed [0x0]
    signature_algs  sha256_rsa, sha384_rsa, sha1_rsa, sha256_ecdsa, sha384_ecdsa, sha1_ecdsa, sha1_dsa, sha512_rsa, sha512_ecdsa
    SessionTicket   empty
    ALPN        h2, http/1.1
    extended_master_secret  empty
    0x0018      00 10 03 02 01 00
    renegotiation_info  00
Ciphers: 
    [C02C]  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    [C02B]  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    [C030]  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    [C02F]  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    [C024]  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    [C023]  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    [C028]  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    [C027]  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    [C00A]  TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    [C009]  TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    [C014]  TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
    [C013]  TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
    [009D]  TLS_RSA_WITH_AES_256_GCM_SHA384
    [009C]  TLS_RSA_WITH_AES_128_GCM_SHA256
    [003D]  TLS_RSA_WITH_AES_256_CBC_SHA256
    [003C]  TLS_RSA_WITH_AES_128_CBC_SHA256
    [0035]  TLS_RSA_AES_256_SHA
    [002F]  TLS_RSA_AES_128_SHA
    [000A]  SSL_RSA_WITH_3DES_EDE_SHA

Compression: 
    [00]    NO_COMPRESSION



HTTP/1.1 200 Connection Established
Proxy-Agent: Zscaler/5.6

Encrypted HTTPS traffic flows through this CONNECT tunnel. HTTPS Decryption is enabled in Fiddler, so decrypted sessions running in this tunnel will be shown in the Web Sessions list.

Secure Protocol: Tls12
Cipher: Aes256 256bits
Hash Algorithm: Sha384 ?bits
Key Exchange: RsaKeyX 2048bits

== Server Certificate ==========
[Subject]
  CN=vault.azure.net

[Issuer]
  [email protected], CN=Zscaler Intermediate Root CA (zscaler.net), OU=Zscaler Inc., O=Zscaler Inc., S=California, C=US

[Serial Number]
  7B00004CD55FB23FA0B68D46B8000000009CD5

[Not Before]
  9/13/2017 6:31:29 AM

[Not After]
  9/13/2019 6:31:29 AM

[Thumbprint]
  BE3A3F50134F9E3989C4200C751X473D5235F4C2

[SubjectAltNames]
vault.azure.net, *.vault.azure.net, *.vaultcore.azure.net


------------------------------------------------------------------
GET https://mykeyvault.vault.azure.net/secrets/ContactManager-AppApiUrl/?api-version=7.0 HTTP/1.1
User-Agent: FxVersion/4.6.00001.0 OSName/Windows OSVersion/MicrosoftWindows Microsoft.Azure.KeyVault.KeyVaultClient/3.0.1.0
Host: mykeyvault.vault.azure.net
Connection: Keep-Alive
Cache-Control: no-cache


HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/10.0
WWW-Authenticate: Bearer authorization="https://login.windows.net/e41ed7bb-472e-4682-9ac0-dd00dfe1aa40", resource="https://vault.azure.net"
x-ms-keyvault-region: eastus2
x-ms-request-id: b3baba90-222c-4412-b57e-b5500ff95572
x-ms-keyvault-service-version: 1.1.0.858
x-ms-keyvault-network-info: addr=165.225.34.51;act_addr_fam=InterNetwork;
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Strict-Transport-Security: max-age=31536000;includeSubDomains
X-Content-Type-Options: nosniff
Date: Mon, 29 Oct 2018 09:57:08 GMT
Content-Length: 0
Proxy-Support: Session-Based-Authentication



------------------------------------------------------------------
CONNECT login.windows.net:443 HTTP/1.0
Host: login.windows.net:443
Content-Length: 0
Proxy-Connection: Keep-Alive
Pragma: no-cache

A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.

Version: 3.3 (TLS/1.2)
Random: 5B D6 D9 7C 94 3B 8E 2B 32 4F 6F 70 3F 85 EC C0 53 27 5D C8 5C 3E 33 8F CF 38 30 A4 91 F8 AE 16
"Time": 5/17/2036 8:59:31 PM
SessionID: empty
Extensions: 
    server_name login.windows.net
    status_request  OCSP - Implicit Responder
    elliptic_curves unknown [0x1D), secp256r1 [0x17], secp384r1 [0x18]
    ec_point_formats    uncompressed [0x0]
    signature_algs  sha256_rsa, sha384_rsa, sha1_rsa, sha256_ecdsa, sha384_ecdsa, sha1_ecdsa, sha1_dsa, sha512_rsa, sha512_ecdsa
    SessionTicket   empty
    ALPN        h2, http/1.1
    extended_master_secret  empty
    0x0018      00 10 03 02 01 00
    renegotiation_info  00
Ciphers: 
    [C02C]  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    [C02B]  TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    [C030]  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    [C02F]  TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    [C024]  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    [C023]  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    [C028]  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    [C027]  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    [C00A]  TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    [C009]  TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    [C014]  TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA
    [C013]  TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA
    [009D]  TLS_RSA_WITH_AES_256_GCM_SHA384
    [009C]  TLS_RSA_WITH_AES_128_GCM_SHA256
    [003D]  TLS_RSA_WITH_AES_256_CBC_SHA256
    [003C]  TLS_RSA_WITH_AES_128_CBC_SHA256
    [0035]  TLS_RSA_AES_256_SHA
    [002F]  TLS_RSA_AES_128_SHA
    [000A]  SSL_RSA_WITH_3DES_EDE_SHA

Compression: 
    [00]    NO_COMPRESSION



HTTP/1.1 200 Connection Established
Proxy-Agent: Zscaler/5.6

Encrypted HTTPS traffic flows through this CONNECT tunnel. HTTPS Decryption is enabled in Fiddler, so decrypted sessions running in this tunnel will be shown in the Web Sessions list.

Secure Protocol: Tls12
Cipher: Aes256 256bits
Hash Algorithm: Sha384 ?bits
Key Exchange: RsaKeyX 2048bits

== Server Certificate ==========
[Subject]
  CN=graph.windows.net

[Issuer]
  [email protected], CN=Zscaler Intermediate Root CA (zscaler.net), OU=Zscaler Inc., O=Zscaler Inc., S=California, C=US

[Serial Number]
  200003E3D42591706F9A74181400000003E3D4

[Not Before]
  8/29/2018 12:38:12 PM

[Not After]
  8/29/2020 12:38:12 PM

[Thumbprint]
  27242CE7B9E88BD32DE00CB02BF2033B3AX47DDD

[SubjectAltNames]
*.accesscontrol.windows.net, *.accesscontrol.windows-ppe.net, *.b2clogin.com, *.cpim.windows.net, *.microsoftaik.azure.net, *.microsoftaik-int.azure-int.net, *.windows-ppe.net, aadg.windows.net, aadgv6.ppe.windows.net, aadgv6.windows.net, account.live.com, account.live-int.com, api.password.ccsctp.com, api.passwordreset.microsoftonline.com, autologon.microsoftazuread-sso.com, becws.ccsctp.com, clientconfig.microsoftonline-p.net, clientconfig.microsoftonline-p-int.net, companymanager.ccsctp.com, companymanager.microsoftonline.com, cpim.windows.net, device.login.microsoftonline.com, device.login.windows-ppe.net, directoryproxy.ppe.windows.net, directoryproxy.windows.net, graph.ppe.windows.net, graph.windows.net, graphstore.windows.net, login.live.com, login.live-int.com, login.microsoft.com, login.microsoftonline.com, login.microsoftonline-p.com, login.microsoftonline-pst.com, login.microsoft-ppe.com, login.windows.net, logincert.microsoftonline.com, logincert.microsoftonline-int.com, login-us.microsoftonline.com, microsoftaik.azure.net, microsoftaik-int.azure-int.net, nexus.microsoftonline-p.com, nexus.microsoftonline-p-int.com, pas.windows.net, pas.windows-ppe.net, password.ccsctp.com, passwordreset.activedirectory.windowsazure.us, passwordreset.microsoftonline.com, provisioning.microsoftonline.com, signup.live.com, signup.live-int.com, sts.windows.net, xml.login.live.com, xml.login.live-int.com, *.login.microsoftonline.com, login.microsoftonline-int.com, accesscontrol.aadtst3.windows-int.net, *.accesscontrol.aadtst3.windows-int.net


------------------------------------------------------------------
GET https://login.windows.net/common/discovery/instance?api-version=1.1&authorization_endpoint=https://login.windows.net/e41ed7bb-472e-4682-9ac0-dd00dfe1aa40/oauth2/authorize HTTP/1.1
client-request-id: dc9c444d-5a14-4e0c-a8af-fa5ad44930e0
return-client-request-id: true
x-client-DM: VMware Virtual Platform
Accept: application/json
x-client-Ver: 4.3.0.0
x-ms-PKeyAuth: 1.0
x-client-CPU: x64
x-client-SKU: PCL.UAP
Host: login.windows.net
Connection: Keep-Alive
Cache-Control: no-cache


HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
client-request-id: dc9c444d-5a14-4e0c-a8af-fa5ad44930e0
x-ms-request-id: cbd2d6c4-57af-4e90-8e8c-fec278b74b00
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"
Set-Cookie: esctx=AQABAAAAAAC5una0EUFgTIF8ElaxtWjTyrZcJfJlYlmLZhgPyiVeColz5g03S9fX_lMIQxsDqOLcD48dBrq1lzrwm_R5KQ0aQwBpyf41EMKYybbS9bJF1EARNWl5u68rj09wRyg8VoIcIntNSzLIVCP-M-GM1o5BdHUfESmTTmFObRSnAewkoTTHEyeILstPRJxRPWUFlxkgAA; domain=.login.windows.net; path=/; secure; HttpOnly
Set-Cookie: x-ms-gateway-slice=003; path=/; secure; HttpOnly
Set-Cookie: stsservicecookie=ests; path=/; secure; HttpOnly
Date: Mon, 29 Oct 2018 09:57:15 GMT
Content-Length: 967

{"tenant_discovery_endpoint":"https://login.windows.net/e41ed7bb-472e-4682-9ac0-dd00dfe1aa40/.well-known/openid-configuration","api-version":"1.1","metadata":[{"preferred_network":"login.microsoftonline.com","preferred_cache":"login.windows.net","aliases":["login.microsoftonline.com","login.windows.net","login.microsoft.com","sts.windows.net"]},{"preferred_network":"login.partner.microsoftonline.cn","preferred_cache":"login.partner.microsoftonline.cn","aliases":["login.partner.microsoftonline.cn","login.chinacloudapi.cn"]},{"preferred_network":"login.microsoftonline.de","preferred_cache":"login.microsoftonline.de","aliases":["login.microsoftonline.de"]},{"preferred_network":"login.microsoftonline.us","preferred_cache":"login.microsoftonline.us","aliases":["login.microsoftonline.us","login.usgovcloudapi.net"]},{"preferred_network":"login-us.microsoftonline.com","preferred_cache":"login-us.microsoftonline.com","aliases":["login-us.microsoftonline.com"]}]}

------------------------------------------------------------------
GET https://mykeyvault.vault.azure.net/secrets/ContactManager-AppApiUrl/?api-version=7.0 HTTP/1.1
x-ms-client-request-id: 639b8a72-c739-48c3-b9c3-f60a5ed8fa86
User-Agent: FxVersion/4.6.00001.0 OSName/Windows OSVersion/MicrosoftWindows Microsoft.Azure.KeyVault.KeyVaultClient/3.0.1.0
accept-language: en-US
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dDI7Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N9SEpsWSJ9.eyJhdWQiOiJodPRwczovL3ZhdWx0LmF6dXJlLm5ldCIsImjzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkyMTEwMmEwLWI2MjEtNDM5Yy04NDY2LTdmZDU0MjE5YWU4Mi8iLCJpYXQiOjE1NDA4MDQyODIsIm5iZiI6MTU0MDgwNDI4MiwiZXhwIjoxNTQwODA4MTgyLCJhaW8iOiI0MlJnWUlnTys5WmZMcjV1cnl6djNUV3Jkd3ZjQXdBPSIsImFwcGlkIjoiZmJmMzdmNDktMTMxMC00N2JjLWE1ZjAtYmY4OWQ4NGUyYmE4IiwiYXBwaWRhY3IiOiIxIiwiZV9leHAiOjI2MjgwMCwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTIxMTAyYTAtYjYyMS00MzljLTg0NjYtN2ZkNTQyMTlhZTgyLyIsIm9pZCI6IjNiNWQ4OVY1LWNlMGItNGI4Ny1hZDVmLTVmNmUyZjM5N2E1ZSIsInN1YiI6IjNiNWQ4OWY1LWNlMGItNGI4Ny1hZDVmLTVmNmUyZjM5N2E1ZSIsInRpZCI6IjkyMTEwMmEwLWI2MjEtNDM5Yy04NDY2LTdmZDU0MjE5YWU4MiIsInV0aSI6IkhDMTJWZVBoV2tTNjJ5Z0Q1aFlfQUEiLCJ2ZXIiOiIxLjAifQ.Q36_4BxTPnvvZPO9LeTOl95u6CXpK1bmctUQfpFKwkrtMneFwqriCGHU9z_CseL-6uhGpUL_1m1MGUANr7r7HUoJwtteFY1SseTyfmvjjbwx9IkjMWwddV-95SVJxnlM54N6ol2Tn11bifDgSPbIPeDvaJ7JZSclk1FuqZItUdKGPwHHpGl2LP5gvtGbl-N_dypofLD1hZtH9DUFEtnt_ArCn_jN8nRblbe3vuLF9-MtiqF-rLt5Wx6s8gBo96boeBF7SL8weFjQfsNr_Q4ntX9o0IouywtW7rYp6Swo0j-OzfkDewuKBhqOheMtModX6xn1nvamVhldabz4Vjracg
Host: mykeyvault.vault.azure.net
Connection: Keep-Alive
Cache-Control: no-cache


HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
x-ms-keyvault-region: eastus2
x-ms-request-id: d08a432e-00b4-4310-ab8b-90035e8e5626
x-ms-keyvault-service-version: 1.1.0.858
x-ms-keyvault-network-info: addr=165.225.34.51;act_addr_fam=InterNetwork;
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Strict-Transport-Security: max-age=31536000;includeSubDomains
X-Content-Type-Options: nosniff
Date: Mon, 29 Oct 2018 09:57:23 GMT
Content-Length: 270

{"value":"https://testserver.net:8476/api/","id":"https://mykeyvault.vault.azure.net/secrets/ContactManager-AppApiUrl/edd10997e4224a7cb756687e6318d972","attributes":{"enabled":true,"created":1535976474,"updated":1535976474,"recoveryLevel":"Purgeable"}}

------------------------------------------------------------------
The token validation on the server expects the exact same string as it returns in the 401 response's WWW-Authenticate header. In general, Key Vault returns 401 for cases where the token is missing or fails validation (three common cases are the token is expired, has an incorrect resource URI, or was issued by a different tenant than the vault is associated with). I test you code and it works well with first keyvault secret. Refer to this article.Joey Cai
Hi @JoeyCai, I have traced request and response of fetching first key vault secret for my app via fiddler and found that first 401 exception occurs because authentication does not occur that time. After successful authentication response code 200 is returned and key vault secret is fetched successfully. I have attached screenshot of fiddler tracing in the issue description. Please let me know if you need anything else here.Narendra Jangir
The exception I am only getting when I turn on "Common Language Run-time Exceptions" from exception settings.Narendra Jangir
Question has been posted to GitHub as well, with more responses: github.com/Azure/azure-sdk-for-net/issues/4924DdW