コード例 #1
0
        public async Task ItShouldSign()
        {
            var parameters = new SignatureBodyParameters(Array.Empty <byte>(), "clientSecret");
            var signer     = new HashAlgorithmSignatureBodySigner();

            var result = await signer.Sign(parameters);

            result.Should().NotBeEmpty();

            var bytes = Convert.FromBase64String(result);

            bytes.Should().HaveCount(32);
        }
コード例 #2
0
        private async Task SignRequest(HttpRequestMessage request)
        {
            request.Headers.Remove(_options.HeaderName);

            var signatureBodySourceComponents = _options.SignatureBodySourceComponents.Any()
                ? _options.SignatureBodySourceComponents
                : DefaultConstants.SignatureBodySourceComponents;

            byte[] body = null;
            if (request.Content != null && signatureBodySourceComponents.Contains(SignatureBodySourceComponents.Body))
            {
                body = await request.Content.ReadAsByteArrayAsync();
            }

            var signatureBodySourceParameters = new SignatureBodySourceParameters(
                request.Method.ToString(),
                request.RequestUri,
                request.Headers.ToDictionary(x => x.Key, x => x.Value.ToString()),
                Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
                GetTimestamp(request),
                _options.ClientId,
                signatureBodySourceComponents,
                body);

            var signatureBodySource = await _signatureBodySourceBuilder.Build(signatureBodySourceParameters);

            var signatureBodyParameters = new SignatureBodyParameters(signatureBodySource, _options.ClientSecret);
            var signatureBody           = await _signatureBodySigner.Sign(signatureBodyParameters);

            var signature = _options.SignaturePattern
                            .Replace("{ClientId}", _options.ClientId)
                            .Replace("{Nonce}", signatureBodySourceParameters.Nonce)
                            .Replace("{Timestamp}", signatureBodySourceParameters.Timestamp.ToString(CultureInfo.InvariantCulture))
                            .Replace("{SignatureBody}", signatureBody);

            request.Headers.TryAddWithoutValidation(_options.HeaderName, signature);
        }
コード例 #3
0
        /// <inheritdoc />
        public async Task <SignatureValidationResult> Validate(HttpRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var serverTimestamp = _clock.UtcNow.ToUnixTimeSeconds();
            SignatureValidationResult result;

            if (_options.Disabled)
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.Disabled,
                    serverTimestamp);
                _logger.SignatureValidationIgnored(result);
                return(result);
            }

            var headerValue = request.Headers[_options.HeaderName];

            if (string.IsNullOrWhiteSpace(headerValue))
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.HeaderNotFound,
                    serverTimestamp);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            var signatureValue = headerValue.ToString().Trim();
            var headerMatch    = _signaturePatternParser.Match(signatureValue);

            if (!headerMatch.Success)
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.HeaderParseError,
                    serverTimestamp,
                    signatureValue: signatureValue);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            var signatureComponents = new SignatureValueComponents
            {
                ClientId      = headerMatch.Groups["ClientId"]?.Value,
                Nonce         = headerMatch.Groups["Nonce"]?.Value,
                Timestamp     = long.Parse(headerMatch.Groups["Timestamp"]?.Value ?? "0", CultureInfo.InvariantCulture),
                SignatureBody = headerMatch.Groups["SignatureBody"]?.Value,
            };

            var clientOptions = _options.Clients.FirstOrDefault(x => string.Equals(x.ClientId, signatureComponents.ClientId, StringComparison.Ordinal));

            if (clientOptions == null)
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.ClientIdNotFound,
                    serverTimestamp,
                    signatureValue: signatureValue,
                    clientId: signatureComponents.ClientId);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            if (await _nonceRepository.Exists(signatureComponents.Nonce))
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.NonceHasBeenUsedBefore,
                    serverTimestamp,
                    signatureValue: signatureValue,
                    clientId: clientOptions.ClientId);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            if (Math.Abs(serverTimestamp - signatureComponents.Timestamp) > _options.ClockSkew.TotalSeconds)
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.TimestampIsOff,
                    serverTimestamp,
                    signatureValue: signatureValue,
                    clientId: clientOptions.ClientId);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            var signatureBodySourceComponents = clientOptions.SignatureBodySourceComponents.Any()
                ? clientOptions.SignatureBodySourceComponents
                : DefaultConstants.SignatureBodySourceComponents;

            byte[] body = null;
            if (signatureBodySourceComponents.Contains(SignatureBodySourceComponents.Body))
            {
#if NETCOREAPP2_1
                request.EnableRewind();
#endif
#if NETCOREAPP3_0
                request.EnableBuffering();
#endif
                request.Body.Seek(0, SeekOrigin.Begin);
                using (var memoryStream = _memoryStreamManager.GetStream())
                {
                    await request.Body.CopyToAsync(memoryStream);

                    body = memoryStream.ToArray();
                }

                request.Body.Seek(0, SeekOrigin.Begin);
            }

            var signatureBodySourceParameters = new SignatureBodySourceParameters(
                request.Method,
                new Uri($"{request.Scheme}://{request.Host}{request.Path}{request.QueryString}"),
                request.Headers.ToDictionary(x => x.Key, x => x.Value.ToString()),
                signatureComponents.Nonce,
                signatureComponents.Timestamp,
                clientOptions.ClientId,
                signatureBodySourceComponents,
                body);

            var signatureBodySource = await _signatureBodySourceBuilder.Build(signatureBodySourceParameters);

            var signatureBodyParameters = new SignatureBodyParameters(signatureBodySource, clientOptions.ClientSecret);
            var signature = await _signatureBodySigner.Sign(signatureBodyParameters);

            if (!string.Equals(signature, signatureComponents.SignatureBody, StringComparison.Ordinal))
            {
                result = new SignatureValidationResult(
                    SignatureValidationResultStatus.SignatureDoesntMatch,
                    serverTimestamp,
                    signatureValue: signatureValue,
                    clientId: clientOptions.ClientId,
                    computedSignature: signature,
                    signatureBodySource: signatureBodySource);
                _logger.SignatureValidationFailed(result);
                return(result);
            }

            await _nonceRepository.Add(signatureComponents.Nonce);

            result = new SignatureValidationResult(
                SignatureValidationResultStatus.OK,
                serverTimestamp,
                signatureValue: signatureValue,
                clientId: clientOptions.ClientId,
                computedSignature: signature);
            _logger.SignatureValidationSucceeded(result);
            return(result);
        }