コード例 #1
0
        public async Task MessageHandlerSignsRequests()
        {
            var algorithm = new HttpSignatureAlgorithm(TestKeyConstants.TestKey, new TestClock());
            var handler   = new SignatureAuthorizationHandler(TestKeyConstants.ValidKeyId, algorithm,
                                                              new RequireSignatureHandler());

            using (var client = new HttpClient(handler))
            {
                var response = await client.GetAsync("http://localhost:5000/api/test/1?value=2011-12-20T12:13:21Z");

                response.StatusCode.Should().Be(HttpStatusCode.OK);
            }
        }
        /// <summary>
        /// Determines whether the signature is valid for the specified message.
        /// </summary>
        /// <param name="signature">The signature to validate.</param>
        /// <param name="method">The HTTP method of the message.</param>
        /// <param name="uri">The requested URI of the message.</param>
        /// <param name="body">The message body.</param>
        /// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
        /// <returns>A value indicating the result of the validation.</returns>
        public virtual async Task <SignatureValidationResult> ValidateAsync(
            HttpSignature signature, string method, string uri, Stream body,
            CancellationToken cancellationToken)
        {
            var timeDiff = Clock.UtcNow - signature.Timestamp;

            if (timeDiff.Duration() > Options.ClockSkewMargin)
            {
                Logger?.LogInformation("The time difference {TimeDiff} between the signature timestamp {Timestamp} and the current time exceeds {Margin}.",
                                       timeDiff, signature.Timestamp, Options.ClockSkewMargin);
                return(SignatureValidationResult.Expired);
            }

            var entry = new NonceCacheEntry(signature.Nonce);

            if (Cache.TryGetValue(entry, out _))
            {
                Logger?.LogInformation("The nonce '{Nonce}' is not unique and has been used before in the past {Expiration}.",
                                       signature.Nonce, Options.NonceExpiration);
                return(SignatureValidationResult.Duplicate);
            }

            var key = await KeyLookup.GetKeyOrDefaultAsync(signature.KeyId).ConfigureAwait(false);

            if (key == null)
            {
                throw KeyNotFoundException.WithId(signature.KeyId);
            }

            var algorithm = new HttpSignatureAlgorithm(key, Clock, Logger);
            var newHash   = await algorithm.CalculateHashAsync(method, uri, body, signature.Nonce,
                                                               signature.Timestamp, cancellationToken).ConfigureAwait(false);

            if (!newHash.HashEquals(signature.Hash))
            {
                Logger?.LogInformation("The signature for {Method} {Uri} with nonce '{Nonce}' and timestamp {Timestamp} does not match.",
                                       method, uri, signature.Nonce, signature.Timestamp);
                return(SignatureValidationResult.Invalid);
            }

            Cache.Set(entry, true, Options.NonceExpiration);
            return(SignatureValidationResult.OK);
        }
コード例 #3
0
        public async Task SignedRequestContainsValidAuthorizationHeader()
        {
            var algorithm = new HttpSignatureAlgorithm(TestKeyConstants.TestKey, new TestClock());
            var request   = new HttpRequestMessage
            {
                Method     = HttpMethod.Get,
                RequestUri = new Uri("http://localhost:5000/api/test/1?value=2011-12-20T12:13:21Z")
            };

            await request.SignAsync(algorithm, TestKeyConstants.ValidKeyId);

            request.Headers.Authorization.Should().NotBeNull();
            request.Headers.Authorization.Parameter.Should().NotBeNull();
            var param = HttpSignature.Parse(request.Headers.Authorization.Parameter);

            param.KeyId.Should().Be(TestKeyConstants.ValidKeyId);
            param.Nonce.Should().NotBeNull();
            param.Timestamp.Should().Be(TestClock.TestValue);
            param.Hash.Should().NotBeEmpty();
        }