internal static HttpRequestForVerification ToHttpRequestForVerification(this IOwinRequest owinRequest, Signature signature) { if (owinRequest == null) { return(null); } if (signature == null) { throw new ArgumentNullException(nameof(signature)); } var request = new HttpRequestForVerification { Method = new HttpMethod(owinRequest.Method), RequestUri = owinRequest.Uri, Signature = signature }; foreach (var header in owinRequest.Headers) { request.Headers[header.Key] = header.Value; } if (ShouldReadBody(owinRequest, signature) && owinRequest.Body != null) { using (var memoryStream = new MemoryStream()) { owinRequest.Body.CopyTo(memoryStream); request.Body = memoryStream.ToArray(); owinRequest.Body?.Dispose(); owinRequest.Body = new MemoryStream(request.Body); } } return(request); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { var compositionRequest = _stringCompositionRequestFactory.CreateForVerification(signedRequest, client, signature); var signingString = _signingStringComposer.Compose(compositionRequest); _logger?.LogDebug("Composed the following signing string for request verification: {0}", signingString); byte[] receivedSignature; try { receivedSignature = _base64Converter.FromBase64(signature.String); } catch (FormatException ex) { return(SignatureVerificationFailure.InvalidSignatureString(ex.Message, ex)); } var isValidSignature = client.SignatureAlgorithm.VerifySignature(signingString, receivedSignature); _logger?.LogDebug("The verification of the signature {0}.", isValidSignature ? "succeeded" : "failed"); if (!isValidSignature) { return(SignatureVerificationFailure.InvalidSignatureString("The signature string does not match the expected value.")); } return(null); }
public async Task VerifiesUsingSignatureManipulatedByCallback() { A.CallTo(() => _signatureParser.Parse(_httpRequest, _options)) .Returns(new SignatureParsingSuccess(_requestForVerification.Signature)); HttpRequestForVerification intercepted = null; A.CallTo(() => _requestSignatureVerificationOrchestrator.VerifySignature(A <HttpRequestForVerification> ._)) .Invokes(call => intercepted = call.GetArgument <HttpRequestForVerification>(0)) .Returns(_verificationSuccessResult); _options.OnSignatureParsed = (request, sig) => { sig.KeyId = new KeyId("xyz"); return(Task.CompletedTask); }; await _sut.VerifySignature(_httpRequest, _options); var expectedSignature = (Signature)_requestForVerification.Signature.Clone(); expectedSignature.KeyId = new KeyId("xyz"); intercepted.Should().NotBeNull(); intercepted.Signature.Should().NotBeNull(); intercepted.Signature.Should().BeEquivalentTo(expectedSignature); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = (Client)TestModels.Client.Clone(); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = (Client)TestModels.Client.Clone(); _method = (request, signature, client) => _sut.Verify(request, signature, client); _now = new DateTimeOffset(2020, 3, 20, 11, 52, 23, TimeSpan.Zero); A.CallTo(() => _systemClock.UtcNow).Returns(_now); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = (Client)TestModels.Client.Clone(); _method = (request, signature, client) => _sut.Verify(request, signature, client); _now = _signature.Created.Value.AddSeconds(3); A.CallTo(() => _systemClock.UtcNow).Returns(_now); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { if ( signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Created) && AlgorithmNamesThatDoNotAllowCreatedValue.Any(alg => signature.Algorithm.StartsWith(alg, StringComparison.OrdinalIgnoreCase))) { return(SignatureVerificationFailure.InvalidCreatedHeader( $"It is not allowed to take the {HeaderName.PredefinedHeaderNames.Created} into account, when the signature algorithm is {signature.Algorithm}.")); } return(null); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signature.Headers = _signature.Headers.Concat(new[] { HeaderName.PredefinedHeaderNames.Expires }).ToArray(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = new Client( TestModels.Client.Id, TestModels.Client.Name, new CustomSignatureAlgorithm("RSA"), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1), RequestTargetEscaping.RFC3986); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = new Client( TestModels.Client.Id, TestModels.Client.Name, new HMACSignatureAlgorithm("s3cr3t", HashAlgorithmName.MD5), TestModels.Client.NonceLifetime, TestModels.Client.ClockSkew, TestModels.Client.RequestTargetEscaping, TestModels.Client.Claims); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { if (signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Created) && !signature.Created.HasValue) { return(SignatureVerificationFailure.InvalidCreatedHeader($"The signature does not contain a value for the {nameof(signature.Created)} property, but it is required.")); } if (signature.Created.HasValue && signature.Created.Value > _systemClock.UtcNow.Add(client.ClockSkew)) { return(SignatureVerificationFailure.InvalidCreatedHeader("The signature is not valid yet. Its creation time is in the future.")); } return(null); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { if (signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Expires) && !signature.Expires.HasValue) { return(SignatureVerificationFailure.HeaderMissing($"The signature does not contain a value for the {nameof(signature.Expires)} property, but it is required.")); } if (signature.Expires.HasValue && signature.Expires.Value < _systemClock.UtcNow.Add(-client.ClockSkew)) { return(SignatureVerificationFailure.SignatureExpired("The signature is expired.")); } return(null); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { // Algorithm parameter is not required if (string.IsNullOrEmpty(signature.Algorithm)) { _logger?.LogDebug("Algorithm verification is not required, because there is no algorithm specified in the signature."); return(null); } // hs2019 is always allowed if (signature.Algorithm == Signature.DefaultSignatureAlgorithm) { return(null); } var algorithmParts = new List <string>(); if (!string.IsNullOrEmpty(signature.Algorithm)) { var separatorIndex = signature.Algorithm.IndexOf('-'); if (separatorIndex < 0 || separatorIndex >= signature.Algorithm.Length - 1) { algorithmParts.Add(signature.Algorithm); } else { algorithmParts.Add(signature.Algorithm.Substring(0, separatorIndex)); algorithmParts.Add(signature.Algorithm.Substring(separatorIndex + 1)); } } if (algorithmParts.Count < 2) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified signature algorithm ({signature.Algorithm}) is not supported.")); } if (!SupportedSignatureAlgorithmNames.Contains(algorithmParts[0])) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified signature algorithm ({signature.Algorithm}) is not supported.")); } if (!SupportedHashAlgorithmNames.Contains(algorithmParts[1].ToUpperInvariant())) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified hash algorithm ({algorithmParts[1]}) is not supported.")); } return(null); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { // Algorithm parameter is not required if (string.IsNullOrEmpty(signature.Algorithm)) { _logger?.LogDebug("Algorithm match verification is not required, because there is no algorithm specified in the signature."); return(null); } // hs2019 is always ok if (signature.Algorithm == Signature.DefaultSignatureAlgorithm) { return(null); } var algorithmParts = new List <string>(); if (!string.IsNullOrEmpty(signature.Algorithm)) { var separatorIndex = signature.Algorithm.IndexOf('-'); if (separatorIndex < 0 || separatorIndex >= signature.Algorithm.Length - 1) { algorithmParts.Add(signature.Algorithm); } else { algorithmParts.Add(signature.Algorithm.Substring(0, separatorIndex)); algorithmParts.Add(signature.Algorithm.Substring(separatorIndex + 1)); } } if (algorithmParts.Count < 2) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified signature algorithm ({signature.Algorithm}) is not supported.")); } if (!client.SignatureAlgorithm.Name.Equals(algorithmParts[0], StringComparison.OrdinalIgnoreCase)) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified signature algorithm ({algorithmParts[0]}) does not match the registered signature algorithm for the client with id {client.Id}.")); } if (!client.SignatureAlgorithm.HashAlgorithm.Name.Equals(algorithmParts[1], StringComparison.OrdinalIgnoreCase)) { return(SignatureVerificationFailure.InvalidSignatureAlgorithm($"The specified hash algorithm ({algorithmParts[1]}) does not match the registered hash algorithm for the client with id {client.Id}.")); } return(null); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _client = (Client)TestModels.Client.Clone(); _method = (request, signature, client) => _sut.Verify(request, signature, client); _signedRequest.Body = Encoding.UTF8.GetBytes("I am the body payload"); using (var hashAlgorithm = HashAlgorithm.Create("SHA-384")) { var digestBytes = hashAlgorithm.ComputeHash(_signedRequest.Body); var digestString = new Base64Converter().ToBase64(digestBytes); _signedRequest.Headers.Add(HeaderName.PredefinedHeaderNames.Digest, "SHA-384=" + digestString); } _signature.Headers = _signature.Headers.Concat(new[] { HeaderName.PredefinedHeaderNames.Digest }).ToArray(); }
internal static async Task <HttpRequestForVerification> ToHttpRequestForVerification(this HttpRequest request, Signature signature) { if (signature == null) { throw new ArgumentNullException(nameof(signature)); } if (request == null) { return(null); } var requestMessage = new HttpRequestForVerification { RequestUri = new Uri(request.GetDisplayUrl(), UriKind.Absolute), Method = string.IsNullOrEmpty(request.Method) ? HttpMethod.Get : new HttpMethod(request.Method), Signature = signature }; foreach (var header in request.Headers) { requestMessage.Headers[header.Key] = new StringValues((string[])header.Value); } if (ShouldReadBody(request, signature) && request.Body != null) { request.EnableBuffering(); // ReSharper disable once UseAwaitUsing // ReSharper disable once ConvertToUsingDeclaration using (var memoryStream = new MemoryStream()) { await request.Body.CopyToAsync(memoryStream).ConfigureAwait(false); requestMessage.Body = memoryStream.ToArray(); request.Body.Seek(0, SeekOrigin.Begin); } } return(requestMessage); }
public override async Task <SignatureVerificationFailure> Verify(HttpRequestForVerification signedRequest, Signature signature, Client client) { if (string.IsNullOrEmpty(signature.Nonce)) { return(null); } var previousNonce = await _nonceStore.Get(client.Id, signature.Nonce).ConfigureAwait(false); if (previousNonce != null && previousNonce.Expiration >= _systemClock.UtcNow) { return(SignatureVerificationFailure.ReplayedRequest($"The nonce '{previousNonce.Value}' for client {client.Id} ({client.Name}) is not unique and has been used before. It expires at {previousNonce.Expiration:R}.")); } var nonce = new Nonce( clientId: client.Id, value: signature.Nonce, expiration: _systemClock.UtcNow.Add(client.NonceLifetime)); await _nonceStore.Register(nonce).ConfigureAwait(false); return(null); }
public Verify() { _now = new DateTimeOffset(2020, 2, 24, 10, 20, 14, TimeSpan.FromHours(0)); _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForVerification)TestModels.RequestForVerification.Clone(); _signatureAlgorithm = new CustomSignatureAlgorithm("TEST"); _client = new Client( TestModels.Client.Id, TestModels.Client.Name, _signatureAlgorithm, TestModels.Client.NonceLifetime, TestModels.Client.ClockSkew, TestModels.Client.RequestTargetEscaping, TestModels.Client.Claims); _method = (request, signature, client) => _sut.Verify(request, signature, client); _composedSignatureString = "abc123"; _composeCall = () => A.CallTo(() => _signingStringComposer.Compose(A <SigningStringCompositionRequest> ._)); _composeCall().Returns(_composedSignatureString); _signature.String = _base64Converter.ToBase64(_client.SignatureAlgorithm.ComputeHash(_composedSignatureString)); }
public VerifySignature() { _httpRequest = new DefaultHttpContext().Request; _httpRequest.Method = "POST"; _httpRequest.Scheme = "https"; _httpRequest.Host = new HostString("unittest.com", 9000); _options = new SignedRequestAuthenticationOptions(); _requestForVerification = new HttpRequestForVerification { Method = HttpMethod.Post, RequestUri = "https://unittest.com:9000".ToUri(), Signature = (Signature)TestModels.Signature.Clone() }; _verificationSuccessResult = new RequestSignatureVerificationResultSuccess( new Client( _requestForVerification.Signature.KeyId, "Unit test app", new HMACSignatureAlgorithm("s3cr3t", HashAlgorithmName.SHA256), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1), RequestTargetEscaping.RFC3986), _requestForVerification, new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", "john.doe") }))); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { if (signature.Headers.Contains(HeaderName.PredefinedHeaderNames.RequestTarget) && !signature.Headers.Contains(HeaderName.PredefinedHeaderNames.RequestTarget)) { return(SignatureVerificationFailure.HeaderMissing($"The {HeaderName.PredefinedHeaderNames.RequestTarget} header is required to be included in the signature.")); } foreach (var headerName in signature.Headers) { var isPresent = PseudoHeaders.Contains(headerName); if (!isPresent) { isPresent = signedRequest.Headers.Contains(headerName); } if (!isPresent) { return(SignatureVerificationFailure.HeaderMissing($"The request header {headerName} is missing, but it is required to validate the signature.")); } } return(null); }
public UnknownResult(Client client, HttpRequestForVerification requestForVerification) : base(client, requestForVerification) { }
public virtual Task <SignatureVerificationFailure> Verify(HttpRequestForVerification signedRequest, Signature signature, Client client) { return(VerifySync(signedRequest, signature, client).ToTask()); }
public virtual SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { throw new System.NotSupportedException(); }
public override SignatureVerificationFailure VerifySync(HttpRequestForVerification signedRequest, Signature signature, Client client) { if (signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Digest) && !signedRequest.Headers.Contains(HeaderName.PredefinedHeaderNames.Digest)) { return(SignatureVerificationFailure.HeaderMissing($"The {HeaderName.PredefinedHeaderNames.Digest} header is indicated as part of the signature, but it is not included in the request.")); } if (!signedRequest.Headers.Contains(HeaderName.PredefinedHeaderNames.Digest)) { _logger?.LogDebug("{0} header verification is not required, because it is not present in the request to verify.", HeaderName.PredefinedHeaderNames.Digest); return(null); } if (signedRequest.Body == null) { return(SignatureVerificationFailure.InvalidDigestHeader($"The {HeaderName.PredefinedHeaderNames.Digest} header verification failed. The request has no body.")); } var digestHeaderValue = signedRequest.Headers.GetValues(HeaderName.PredefinedHeaderNames.Digest).FirstOrDefault(); var digestParams = new List <string>(); if (!string.IsNullOrEmpty(digestHeaderValue)) { var separatorIndex = digestHeaderValue.IndexOf('='); if (separatorIndex < 0 || separatorIndex >= digestHeaderValue.Length - 1) { digestParams.Add(digestHeaderValue); } else { digestParams.Add(digestHeaderValue.Substring(0, separatorIndex)); digestParams.Add(digestHeaderValue.Substring(separatorIndex + 1)); } } if (digestParams.Count < 2) { return(SignatureVerificationFailure.InvalidDigestHeader($"The {HeaderName.PredefinedHeaderNames.Digest} request header is invalid.")); } if (!Constants.DigestHashAlgorithms.TryGetValue(digestParams[0], out var digestAlgorithmName)) { return(SignatureVerificationFailure.InvalidDigestHeader($"The {HeaderName.PredefinedHeaderNames.Digest} algorithm name ({digestParams[0] ?? "[null]"}) is invalid.")); } using (var hashAlgorithm = HashAlgorithmFactory.Create(new HashAlgorithmName(digestAlgorithmName))) { if (hashAlgorithm == null) { return(SignatureVerificationFailure.InvalidDigestHeader($"The {HeaderName.PredefinedHeaderNames.Digest} algorithm name ({digestParams[0] ?? "[null]"}) is currently not supported.")); } var payloadBytes = hashAlgorithm.ComputeHash(signedRequest.Body); var calculatedDigest = _base64Converter.ToBase64(payloadBytes); var receivedDigest = digestParams[1]; if (calculatedDigest != receivedDigest) { return(SignatureVerificationFailure.InvalidDigestHeader("The digest header verification failed.")); } } return(null); }
/// <summary> /// Creates a new instance of this class. /// </summary> /// <param name="client">The client for which the verification happened.</param> /// <param name="requestForVerification">The data of the request that was used to verify.</param> protected RequestSignatureVerificationResult(Client client, HttpRequestForVerification requestForVerification) { Client = client; // Can be null, because a failure might have occurred when looking up the client RequestForVerification = requestForVerification; // Can be null, because a failure might have occurred before extracting the data }