Пример #1
0
        private async Task SignRequest(HttpRequestMessage request)
        {
            if (StringExtensions.IsIgnoredPath(IgnoredPaths, request.RequestUri.AbsolutePath, request.Method.Method))
            {
                return;
            }
            var content       = request.Content != null ? (await request.Content.ReadAsByteArrayAsync()) : new byte[0];
            var validationKey = Credential.Key as X509SecurityKey;
            var pathAndQuery  = Uri.UnescapeDataString(request.RequestUri.AbsolutePath) + request.RequestUri.Query;
            var headersToSign = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            foreach (var name in HeaderNames)
            {
                if (HttpRequestTarget.HeaderName.Equals(name, StringComparison.OrdinalIgnoreCase))
                {
                    headersToSign.Add(HttpRequestTarget.HeaderName, new HttpRequestTarget(request.Method.Method, pathAndQuery).ToString());
                    continue;
                }
                else if (HttpDigest.HTTPHeaderName.Equals(name, StringComparison.OrdinalIgnoreCase))
                {
                    headersToSign.Add(HttpDigest.HTTPHeaderName, new HttpDigest(Credential.Algorithm, content).ToString());
                    request.Headers.Add(HttpDigest.HTTPHeaderName, headersToSign[name]);
                    continue;
                }
                else if (HeaderFieldNames.Created.Equals(name, StringComparison.OrdinalIgnoreCase))
                {
                    headersToSign.Add(HeaderFieldNames.Created, request.Headers.TryGetValues(RequestCreatedHeaderName, out var createdDate) ? createdDate.First() : DateTimeOffset.UtcNow.ToString("r"));
                    if (!request.Headers.Contains(RequestCreatedHeaderName))
                    {
                        request.Headers.Add(RequestCreatedHeaderName, headersToSign[HeaderFieldNames.Created]);
                    }
                    continue;
                }
                else
                {
                    if (request.Headers.Contains(name))
                    {
                        var value = request.Headers.GetValues(name).FirstOrDefault();
                        if (headersToSign.ContainsKey(name))
                        {
                            headersToSign[name] = value;
                        }
                        else
                        {
                            headersToSign.Add(name, value);
                        }
                        Debug.WriteLine($"HttpSignature: Include '{name}: {value}'");
                    }
                    else
                    {
                        throw new Exception($"HttpSignature: Cannot include header'{name}' it is missing from the request payload");
                    }
                }
            }
            var signature = new HttpSignature(Credential, headersToSign, DateTime.UtcNow, null);

            request.Headers.Add(HttpSignature.HTTPHeaderName, signature.ToString());
            Debug.WriteLine($"HttpSignature: {HttpSignature.HTTPHeaderName} Header: {signature}");
            request.Headers.Add(RequestSignatureCertificateHeaderName, Convert.ToBase64String(validationKey.Certificate.Export(X509ContentType.Cert)));
        }
Пример #2
0
 /// <summary>
 /// constructs the token for sending a request with http signature.
 /// </summary>
 /// <param name="signingCredentials"></param>
 /// <param name="requestBody"></param>
 /// <param name="includedHeaders"></param>
 /// <param name="createdDate"></param>
 /// <param name="expirationDate"></param>
 public HttpSignatureSecurityToken(SigningCredentials signingCredentials, byte[] requestBody, IDictionary <string, string> includedHeaders, DateTime?createdDate = null, DateTime?expirationDate = null)
 {
     Digest = new HttpDigest(signingCredentials.Algorithm, requestBody);
     includedHeaders.Add(HttpDigest.HTTPHeaderName, Digest.ToString());
     Signature = new HttpSignature(signingCredentials, includedHeaders, createdDate, expirationDate);
     RequestId = includedHeaders["X-Request-Id"];
 }
Пример #3
0
 /// <summary>
 /// Constructs the token for validating an incoming request.
 /// </summary>
 public HttpSignatureSecurityToken(string rawDigest, string rawSignature)
 {
     RawDigest    = rawDigest;
     RawSignature = rawSignature;
     Digest       = HttpDigest.Parse(rawDigest);
     Signature    = HttpSignature.Parse(rawSignature);
 }
Пример #4
0
        private async Task ValidateResponse(HttpRequestMessage request, HttpResponseMessage response)
        {
            if (IgnoreResponseValidation)
            {
                return;
            }
            if (StringExtensions.IsIgnoredPath(IgnoredPaths, request.RequestUri.AbsolutePath, request.Method.Method))
            {
                return;
            }
            if (!response.Headers.TryGetValues(HttpSignature.HTTPHeaderName, out var signatureValues) || signatureValues.Count() == 0)
            {
                return;
            }
            if (!response.Headers.TryGetValues(ResponseSignatureCertificateHeaderName, out var certValues) || certValues.Count() == 0)
            {
                var error = $"Missing certificate in HTTP header '{ResponseSignatureCertificateHeaderName}'. Cannot validate signature.";
                throw new Exception(error);
            }
            var rawSignature   = signatureValues.First();
            var rawCertificate = certValues.First();

            Debug.WriteLine($"{nameof(HttpSignatureDelegatingHandler)}: Raw Signature: {rawSignature}");
            Debug.WriteLine($"{nameof(HttpSignatureDelegatingHandler)}: Raw Certificate: {rawCertificate}");
            X509Certificate2 certificate;

            try {
                certificate = new X509Certificate2(Convert.FromBase64String(rawCertificate));
            } catch (Exception inner) {
                var error = $"Signature Certificate not in a valid format. Expected a base64 encoded x509.";
                throw new Exception(error, inner);
            }
            var validationKey = new X509SecurityKey(certificate);

            Debug.WriteLine($"{nameof(HttpSignatureDelegatingHandler)}: Validation Key: {validationKey.KeyId}");
            var httpSignature = HttpSignature.Parse(rawSignature);

            if (response.Headers.TryGetValues(HttpDigest.HTTPHeaderName, out var digestValues) && digestValues.Count() > 0)
            {
                var rawDigest = digestValues.First();
                Debug.WriteLine($"{nameof(HttpSignatureDelegatingHandler)}: Raw Digest: {rawDigest}");
                var httpDigest = HttpDigest.Parse(rawDigest);
                Debug.WriteLine($"{nameof(HttpSignatureDelegatingHandler)}: Validated Token Digest: {httpDigest}");
                var responseBody = await response.Content.ReadAsByteArrayAsync();

                // Validate the request.
                var disgestIsValid = httpDigest.Validate(responseBody);
                if (!disgestIsValid)
                {
                    var error = $"Response digest validation failed.";
                    throw new Exception(error);
                }
            }
            response.Headers.TryGetValues(ResponseCreatedHeaderName, out var createdFieldValue);
            var signatureIsValid = httpSignature.Validate(validationKey, request.RequestUri, request.Method.Method, createdFieldValue.First(), response.Headers);

            if (!signatureIsValid)
            {
                var error = $"Response signature validation failed.";
                throw new Exception(error);
            }
        }