private static string GenerateAuthorizationTokenWithHashCore(
            string verb,
            string resourceId,
            string resourceType,
            INameValueCollection headers,
            IComputeHash stringHMACSHA256Helper,
            out MemoryStream payload)
        {
            // resourceId can be null for feed-read of /dbs
            if (string.IsNullOrEmpty(verb))
            {
                throw new ArgumentException(RMResources.StringArgumentNullOrEmpty, nameof(verb));
            }

            if (resourceType == null)
            {
                throw new ArgumentNullException(nameof(resourceType)); // can be empty
            }

            if (stringHMACSHA256Helper == null)
            {
                throw new ArgumentNullException(nameof(stringHMACSHA256Helper));
            }

            if (headers == null)
            {
                throw new ArgumentNullException(nameof(headers));
            }

            // Order of the values included in the message payload is a protocol that clients/BE need to follow exactly.
            // More headers can be added in the future.
            // If any of the value is optional, it should still have the placeholder value of ""
            // OperationType -> ResourceType -> ResourceId/OwnerId -> XDate -> Date
            string verbInput         = verb ?? string.Empty;
            string resourceIdInput   = resourceId ?? string.Empty;
            string resourceTypeInput = resourceType ?? string.Empty;

            string authResourceId = AuthorizationHelper.GetAuthorizationResourceIdOrFullName(resourceTypeInput, resourceIdInput);
            int    capacity       = AuthorizationHelper.ComputeMemoryCapacity(verbInput, authResourceId, resourceTypeInput);

            payload = new MemoryStream(capacity);
            AuthorizationHelper.SerializeMessagePayload(
                payload,
                verbInput,
                authResourceId,
                resourceTypeInput,
                headers);
            payload.Position = 0;

            byte[] hashPayLoad = stringHMACSHA256Helper.ComputeHash(payload);
            payload.Position = 0;
            string authorizationToken = Convert.ToBase64String(hashPayLoad);

            return(authorizationToken);
        }
        private static string GenerateKeyAuthorizationCore(
            string verb,
            string resourceId,
            string resourceType,
            INameValueCollection headers,
            string key,
            out ArraySegment <byte> payload,
            bool bUseUtcNowForMissingXDate = false)
        {
            string authorizationToken;

            // resourceId can be null for feed-read of /dbs
            if (string.IsNullOrEmpty(verb))
            {
                throw new ArgumentException(RMResources.StringArgumentNullOrEmpty, nameof(verb));
            }

            if (resourceType == null)
            {
                throw new ArgumentNullException(nameof(resourceType)); // can be empty
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException(RMResources.StringArgumentNullOrEmpty, nameof(key));
            }

            if (headers == null)
            {
                throw new ArgumentNullException(nameof(headers));
            }

            byte[] keyBytes = Convert.FromBase64String(key);
            using (HMACSHA256 hmacSha256 = new HMACSHA256(keyBytes))
            {
                // Order of the values included in the message payload is a protocol that clients/BE need to follow exactly.
                // More headers can be added in the future.
                // If any of the value is optional, it should still have the placeholder value of ""
                // OperationType -> ResourceType -> ResourceId/OwnerId -> XDate -> Date
                string verbInput         = verb ?? string.Empty;
                string resourceIdInput   = resourceId ?? string.Empty;
                string resourceTypeInput = resourceType ?? string.Empty;

                string authResourceId       = AuthorizationHelper.GetAuthorizationResourceIdOrFullName(resourceTypeInput, resourceIdInput);
                int    memoryStreamCapacity = AuthorizationHelper.ComputeMemoryCapacity(verbInput, authResourceId, resourceTypeInput);
                byte[] buffer = ArrayPool <byte> .Shared.Rent(memoryStreamCapacity);

                using ArrayOwner owner = new ArrayOwner(ArrayPool <byte> .Shared, new ArraySegment <byte>(buffer, 0, buffer.Length));
                Span <byte> payloadBytes = buffer;
                int         length       = AuthorizationHelper.SerializeMessagePayload(
                    payloadBytes,
                    verbInput,
                    authResourceId,
                    resourceTypeInput,
                    headers);

                byte[] hashPayLoad = hmacSha256.ComputeHash(buffer, 0, length);
                authorizationToken = Convert.ToBase64String(hashPayLoad);
            }

            return(authorizationToken);
        }
Example #3
0
        // This function is used by Compute
        internal static string GenerateUrlEncodedAuthorizationTokenWithHashCore(
            string verb,
            string resourceId,
            string resourceType,
            INameValueCollection headers,
            IComputeHash stringHMACSHA256Helper,
            out ArrayOwner payload)
        {
            // resourceId can be null for feed-read of /dbs
            if (string.IsNullOrEmpty(verb))
            {
                throw new ArgumentException(RMResources.StringArgumentNullOrEmpty, nameof(verb));
            }

            if (resourceType == null)
            {
                throw new ArgumentNullException(nameof(resourceType)); // can be empty
            }

            if (stringHMACSHA256Helper == null)
            {
                throw new ArgumentNullException(nameof(stringHMACSHA256Helper));
            }

            if (headers == null)
            {
                throw new ArgumentNullException(nameof(headers));
            }

            // Order of the values included in the message payload is a protocol that clients/BE need to follow exactly.
            // More headers can be added in the future.
            // If any of the value is optional, it should still have the placeholder value of ""
            // OperationType -> ResourceType -> ResourceId/OwnerId -> XDate -> Date
            string verbInput         = verb ?? string.Empty;
            string resourceIdInput   = resourceId ?? string.Empty;
            string resourceTypeInput = resourceType ?? string.Empty;

            string authResourceId = AuthorizationHelper.GetAuthorizationResourceIdOrFullName(resourceTypeInput, resourceIdInput);
            int    capacity       = AuthorizationHelper.ComputeMemoryCapacity(verbInput, authResourceId, resourceTypeInput);

            byte[] buffer = ArrayPool <byte> .Shared.Rent(capacity);

            try
            {
                Span <byte> payloadBytes = buffer;
                int         length       = AuthorizationHelper.SerializeMessagePayload(
                    payloadBytes,
                    verbInput,
                    authResourceId,
                    resourceTypeInput,
                    headers);

                payload = new ArrayOwner(ArrayPool <byte> .Shared, new ArraySegment <byte>(buffer, 0, length));
                byte[] hashPayLoad = stringHMACSHA256Helper.ComputeHash(payload.Buffer);
                return(AuthorizationHelper.OptimizedConvertToBase64string(hashPayLoad));
            }
            catch
            {
                ArrayPool <byte> .Shared.Return(buffer);

                throw;
            }
        }