< Summary

Class:Azure.Data.AppConfiguration.AuthenticationPolicy
Assembly:Azure.Data.AppConfiguration
File(s):C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\AuthenticationPolicy.cs
Covered lines:43
Uncovered lines:0
Coverable lines:43
Total lines:98
Line coverage:100% (43 of 43)
Covered branches:4
Total branches:4
Branch coverage:100% (4 of 4)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-100%100%
Process(...)-100%100%
ProcessAsync()-100%100%
CreateContentHash(...)-100%100%
CreateContentHashAsync()-100%100%
AddHeaders(...)-100%100%
GetAuthorizationHeader(...)-100%100%
ComputeHash(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\appconfiguration\Azure.Data.AppConfiguration\src\AuthenticationPolicy.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Globalization;
 6using System.IO;
 7using System.Security.Cryptography;
 8using System.Text;
 9using System.Threading.Tasks;
 10using Azure.Core;
 11using Azure.Core.Pipeline;
 12
 13namespace Azure.Data.AppConfiguration
 14{
 15    internal class AuthenticationPolicy : HttpPipelinePolicy
 16    {
 17        private readonly string _credential;
 18        private readonly byte[] _secret;
 19
 32020        public AuthenticationPolicy(string credential, byte[] secret)
 21        {
 32022            _credential = credential;
 32023            _secret = secret;
 32024        }
 25
 26        public override void Process(HttpMessage message, ReadOnlyMemory<HttpPipelinePolicy> pipeline)
 27        {
 39228            string contentHash = CreateContentHash(message);
 39229            AddHeaders(message, contentHash);
 39230            ProcessNext(message, pipeline);
 39231        }
 32
 33        public override async ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory<HttpPipelinePolicy> pipeline)
 34        {
 39235            string contentHash = await CreateContentHashAsync(message).ConfigureAwait(false);
 39236            AddHeaders(message, contentHash);
 39237            await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
 39238        }
 39
 40        private static string CreateContentHash(HttpMessage message)
 41        {
 39242            using var alg = SHA256.Create();
 43
 39244            using (var memoryStream = new MemoryStream())
 39245            using (var contentHashStream = new CryptoStream(memoryStream, alg, CryptoStreamMode.Write))
 46            {
 39247                message.Request.Content?.WriteTo(contentHashStream, message.CancellationToken);
 14648            }
 49
 39250            return Convert.ToBase64String(alg.Hash);
 39251        }
 52
 53        private static async ValueTask<string> CreateContentHashAsync(HttpMessage message)
 54        {
 39255            using var alg = SHA256.Create();
 56
 39257            using (var memoryStream = new MemoryStream())
 39258            using (var contentHashStream = new CryptoStream(memoryStream, alg, CryptoStreamMode.Write))
 59            {
 39260                if (message.Request.Content != null)
 61                {
 14662                    await message.Request.Content.WriteToAsync(contentHashStream, message.CancellationToken).ConfigureAw
 63                }
 39264            }
 65
 39266            return Convert.ToBase64String(alg.Hash);
 39267        }
 68
 69        private void AddHeaders(HttpMessage message, string contentHash)
 70        {
 78471            var utcNowString = DateTimeOffset.UtcNow.ToString("r", CultureInfo.InvariantCulture);
 78472            var authorization = GetAuthorizationHeader(message.Request, contentHash, utcNowString);
 73
 78474            message.Request.Headers.SetValue("x-ms-content-sha256", contentHash);
 78475            message.Request.Headers.SetValue(HttpHeader.Names.Date, utcNowString);
 78476            message.Request.Headers.SetValue(HttpHeader.Names.Authorization, authorization);
 78477        }
 78
 79        private string GetAuthorizationHeader(Request request, string contentHash, string date) {
 80            const string signedHeaders = "date;host;x-ms-content-sha256"; // Semicolon separated header names
 81
 78482            var uri = request.Uri.ToUri();
 78483            var host = uri.Host;
 78484            var pathAndQuery = uri.PathAndQuery;
 78485            var method = request.Method.Method;
 86
 78487            var stringToSign = $"{method}\n{pathAndQuery}\n{date};{host};{contentHash}";
 78488            var signature = ComputeHash(stringToSign); // Calculate the signature
 78489            return $"HMAC-SHA256 Credential={_credential}&SignedHeaders={signedHeaders}&Signature={signature}";
 90        }
 91
 92        private string ComputeHash(string value)
 93        {
 78494            using var hmac = new HMACSHA256(_secret);
 78495            return Convert.ToBase64String(hmac.ComputeHash(Encoding.ASCII.GetBytes(value)));
 78496        }
 97    }
 98}