public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _client = new Client(TestModels.Client.Id, TestModels.Client.Name, new HMACSignatureAlgorithm("s3cr3t", HashAlgorithmName.MD5), TestModels.Client.NonceLifetime, TestModels.Client.ClockSkew, TestModels.Client.Claims); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public override SignatureVerificationFailure VerifySync(HttpRequestForSigning signedRequest, Signature signature, Client client) { if ( signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Created) && AlgorithmNamesThatDoNotAllowCreatedHeader.Contains(client.SignatureAlgorithm.Name, StringComparer.OrdinalIgnoreCase)) { return(SignatureVerificationFailure.InvalidCreatedHeader( $"It is not allowed to take the {HeaderName.PredefinedHeaderNames.Created} into account, when the signature algorithm is {client.SignatureAlgorithm.Name}.")); } if (!signature.Created.HasValue) { return(SignatureVerificationFailure.InvalidCreatedHeader($"The signature does not contain a value for the {nameof(signature.Created)} property, but it is required.")); } var createdHeaderValues = signedRequest.Headers.GetValues(HeaderName.PredefinedHeaderNames.Created); if (createdHeaderValues != StringValues.Empty && signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Created)) { if (!long.TryParse(createdHeaderValues.First(), out var parsedCreatedValue)) { return(SignatureVerificationFailure.InvalidCreatedHeader( $"The request does not contain a valid value for the {HeaderName.PredefinedHeaderNames.Created} header.")); } var createdHeaderValue = DateTimeOffset.FromUnixTimeSeconds(parsedCreatedValue); if (createdHeaderValue != signature.Created.Value) { return(SignatureVerificationFailure.InvalidCreatedHeader( $"The signature creation time does not match the value of the {HeaderName.PredefinedHeaderNames.Created} request header.")); } } return(null); }
public VerifySignature() { _signature = new Signature { KeyId = "client1" }; _signedRequest = new HttpRequestForSigning { Method = HttpMethod.Post, RequestUri = "https://unittest.com:9001" }; _client = new Client("client1", "Unit test app", new HMACSignatureAlgorithm("s3cr3t", HashAlgorithmName.SHA256), TimeSpan.FromMinutes(1)); A.CallTo(() => _knownAlgorithmVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _matchingAlgorithmVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _createdHeaderGuardVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _expiresHeaderGuardVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _allHeadersPresentVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _creationTimeVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _expirationTimeVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _nonceVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _digestVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); A.CallTo(() => _matchingSignatureStringVerificationTask.Verify(A <HttpRequestForSigning> ._, A <Signature> ._, A <Client> ._)).Returns((SignatureVerificationFailure)null); _sanitizedSignature = (Signature)_signature.Clone(); A.CallTo(() => _signatureSanitizer.Sanitize(_signature, _client)) .Returns(_sanitizedSignature); }
public override SignatureVerificationFailure VerifySync(HttpRequestForSigning signedRequest, Signature signature, Client client) { if (!signature.Headers.Contains(HeaderName.PredefinedHeaderNames.RequestTarget)) { return(SignatureVerificationFailure.HeaderMissing($"The {HeaderName.PredefinedHeaderNames.RequestTarget} header is required to be included in the signature.")); } if (client.SignatureAlgorithm.ShouldIncludeDateHeader() && !signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Date)) { return(SignatureVerificationFailure.HeaderMissing($"The inclusion of the {HeaderName.PredefinedHeaderNames.Date} header is required when using security algorithm '{client.SignatureAlgorithm.Name}'.")); } if (client.SignatureAlgorithm.ShouldIncludeCreatedHeader() && !signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Created)) { return(SignatureVerificationFailure.HeaderMissing($"The inclusion of the {HeaderName.PredefinedHeaderNames.Created} header is required when using security algorithm '{client.SignatureAlgorithm.Name}'.")); } if (client.SignatureAlgorithm.ShouldIncludeExpiresHeader() && !signature.Headers.Contains(HeaderName.PredefinedHeaderNames.Expires)) { return(SignatureVerificationFailure.HeaderMissing($"The inclusion of the {HeaderName.PredefinedHeaderNames.Expires} header is required when using security algorithm '{client.SignatureAlgorithm.Name}'.")); } foreach (var headerName in signature.Headers) { if (headerName != HeaderName.PredefinedHeaderNames.RequestTarget) { if (!signedRequest.Headers.Contains(headerName)) { return(SignatureVerificationFailure.HeaderMissing($"The request header {headerName} is missing, but it is required to validate the signature.")); } } } return(null); }
public string Compose(HttpRequestForSigning request, string signatureAlgorithmName, HeaderName[] headerNames, DateTimeOffset timeOfComposing, TimeSpan expires, string nonce) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (signatureAlgorithmName == null) { throw new ArgumentNullException(nameof(signatureAlgorithmName)); } if (headerNames == null) { throw new ArgumentNullException(nameof(headerNames)); } var headerAppender = _headerAppenderFactory.Create(request, signatureAlgorithmName, timeOfComposing, expires); var sb = new StringBuilder(); foreach (var headerName in headerNames.Where(h => h != HeaderName.Empty)) { sb = sb.Append(headerAppender.BuildStringToAppend(headerName)); } sb.Append(_nonceAppender.BuildStringToAppend(nonce)); return(sb.ToString().Trim()); }
public async Task <SignatureVerificationFailure> VerifySignature(HttpRequestForSigning signedRequest, Signature signature, Client client) { if (signedRequest == null) { throw new ArgumentNullException(nameof(signedRequest)); } if (signature == null) { throw new ArgumentNullException(nameof(signature)); } if (client == null) { throw new ArgumentNullException(nameof(client)); } var sanitizedSignature = await _signatureSanitizer.Sanitize(signature, client); var failure = await _knownAlgorithmVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _matchingAlgorithmVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _createdHeaderGuardVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _expiresHeaderGuardVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _allHeadersPresentVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _creationTimeVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _expirationTimeVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _nonceVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _digestVerificationTask.Verify(signedRequest, sanitizedSignature, client) ?? await _matchingSignatureStringVerificationTask.Verify(signedRequest, sanitizedSignature, client); return(failure); }
public async Task CallsSigningStringComposerWithExpectedParameters() { HttpRequestForSigning interceptedRequest = null; string interceptedSignatureAlgorithmName = null; HeaderName[] interceptedHeaderNames = null; DateTimeOffset?interceptedCreated = null; TimeSpan? interceptedExpires = null; A.CallTo(() => _signingStringComposer.Compose(A <HttpRequestForSigning> ._, A <string> ._, A <HeaderName[]> ._, A <DateTimeOffset> ._, A <TimeSpan> ._, A <string> ._)) .Invokes(call => { interceptedRequest = call.GetArgument <HttpRequestForSigning>(0); interceptedSignatureAlgorithmName = call.GetArgument <string>(1); interceptedHeaderNames = call.GetArgument <HeaderName[]>(2); interceptedCreated = call.GetArgument <DateTimeOffset>(3); interceptedExpires = call.GetArgument <TimeSpan>(4); }) .Returns(_composedSignatureString); await _method(_signedRequest, _signature, _client); interceptedCreated.Should().Be(_signature.Created); interceptedSignatureAlgorithmName.Should().Be("TEST"); interceptedExpires.Should().Be(_signature.Expires.Value - _signature.Created.Value); interceptedRequest.Should().Be(_signedRequest); interceptedHeaderNames.Should().Equal(_signature.Headers); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _client = new Client(TestModels.Client.Id, TestModels.Client.Name, new HMACSignatureAlgorithm("s3cr3t", HashAlgorithmName.MD5), TimeSpan.FromMinutes(1)); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _client = (Client)TestModels.Client.Clone(); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
internal static HttpRequestForSigning ToHttpRequestForSigning(this IOwinRequest owinRequest) { var request = new HttpRequestForSigning { Method = new HttpMethod(owinRequest.Method), RequestUri = (owinRequest.Uri.IsAbsoluteUri ? owinRequest.Uri.AbsolutePath : owinRequest.Uri.OriginalString.Split('?')[0]).UrlDecode() }; foreach (var header in owinRequest.Headers) { request.Headers[header.Key] = header.Value; } if (ShouldReadBody(owinRequest) && 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(HttpRequestForSigning signedRequest, Signature signature, Client client) { var expires = signature.Created.HasValue && signature.Expires.HasValue ? signature.Expires.Value - signature.Created.Value : new TimeSpan?(); var signingString = _signingStringComposer.Compose( signedRequest, signature.Headers, signature.Created, expires, signature.Nonce); _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 DefaultHeaderAppenderTests() { _httpRequest = new HttpRequestForSigning { Method = HttpMethod.Post, RequestUri = "http://dalion.eu/api/resource/id1" }; _sut = new DefaultHeaderAppender(_httpRequest); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signature.Headers = _signature.Headers.Concat(new[] { HeaderName.PredefinedHeaderNames.Expires }).ToArray(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _client = new Client(TestModels.Client.Id, TestModels.Client.Name, new CustomSignatureAlgorithm("RSA"), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public RequestTargetHeaderAppenderTests() { _httpRequest = new HttpRequestForSigning { Method = HttpMethod.Post, RequestUri = "/api/resource/id1" }; _sut = new RequestTargetHeaderAppender(_httpRequest); }
public Create() { _timeOfComposing = new DateTimeOffset(2020, 2, 24, 11, 20, 14, TimeSpan.FromHours(1)); _expires = TimeSpan.FromMinutes(5); _httpRequest = new HttpRequestForSigning { Method = HttpMethod.Post, RequestUri = "http://dalion.eu/api/resource/id1" }; }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signature.Algorithm = "hmac-sha256"; _signature.Headers = _signature.Headers.Concat(new[] { HeaderName.PredefinedHeaderNames.Expires }).ToArray(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _signedRequest.Headers.Add(HeaderName.PredefinedHeaderNames.Expires, _signature.Expires.Value.ToUnixTimeSeconds().ToString()); _client = new Client(TestModels.Client.Id, TestModels.Client.Name, new CustomSignatureAlgorithm("hs2019"), TimeSpan.FromMinutes(1)); _method = (request, signature, client) => _sut.Verify(request, signature, client); }
public Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForSigning)TestModels.Request.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 Verify() { _signature = (Signature)TestModels.Signature.Clone(); _signedRequest = (HttpRequestForSigning)TestModels.Request.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 override SignatureVerificationFailure VerifySync(HttpRequestForSigning 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(); _signedRequest = (HttpRequestForSigning)TestModels.Request.Clone(); _signatureAlgorithm = new CustomSignatureAlgorithm("TEST"); _client = new Client(TestModels.Client.Id, TestModels.Client.Name, _signatureAlgorithm, TimeSpan.FromMinutes(1)); _method = (request, signature, client) => _sut.Verify(request, signature, client); _composedSignatureString = "abc123"; A.CallTo(() => _signingStringComposer.Compose(A <HttpRequestForSigning> ._, A <string> ._, A <HeaderName[]> ._, A <DateTimeOffset> ._, A <TimeSpan> ._, A <string> ._)) .Returns(_composedSignatureString); _signature.String = _base64Converter.ToBase64(_client.SignatureAlgorithm.ComputeHash(_composedSignatureString)); }
public IHeaderAppender Create(HttpRequestForSigning request, DateTimeOffset?timeOfComposing, TimeSpan?expires) { if (request == null) { throw new ArgumentNullException(nameof(request)); } return(new CompositeHeaderAppender( new DefaultHeaderAppender(request), new RequestTargetHeaderAppender(request), new CreatedHeaderAppender(timeOfComposing), new ExpiresHeaderAppender(timeOfComposing, expires), new DateHeaderAppender(request))); }
public override SignatureVerificationFailure VerifySync(HttpRequestForSigning 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(HttpRequestForSigning 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(HttpRequestForSigning 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(HttpRequestForSigning 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 = (HttpRequestForSigning)TestModels.Request.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(); }
public IHeaderAppender Create(HttpRequestForSigning request, string signatureAlgorithmName, DateTimeOffset timeOfComposing, TimeSpan expires) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (signatureAlgorithmName == null) { throw new ArgumentNullException(nameof(signatureAlgorithmName)); } return(new CompositeHeaderAppender( new DefaultHeaderAppender(request), new RequestTargetHeaderAppender(request), new CreatedHeaderAppender(signatureAlgorithmName, timeOfComposing), new ExpiresHeaderAppender(signatureAlgorithmName, timeOfComposing, expires), new DateHeaderAppender(request))); }
public Compose() { _timeOfComposing = new DateTimeOffset(2020, 2, 24, 11, 20, 14, TimeSpan.FromHours(1)); _expires = TimeSpan.FromMinutes(5); _httpRequest = new HttpRequestForSigning { Method = HttpMethod.Post, RequestUri = "http://dalion.eu/api/resource/id1" }; _headerNames = new[] { HeaderName.PredefinedHeaderNames.RequestTarget, HeaderName.PredefinedHeaderNames.Date, new HeaderName("dalion_app_id") }; _nonce = "abc123"; FakeFactory.Create(out _headerAppender); A.CallTo(() => _headerAppenderFactory.Create(_httpRequest, _timeOfComposing, _expires)) .Returns(_headerAppender); }
internal static async Task <HttpRequestForSigning> ToRequestForSigning(this HttpRequest request, Signature signature) { if (signature == null) { throw new ArgumentNullException(nameof(signature)); } if (request == null) { return(null); } var requestMessage = new HttpRequestForSigning { RequestUri = GetRequestUri(request), Method = string.IsNullOrEmpty(request.Method) ? HttpMethod.Get : new HttpMethod(request.Method) }; 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); requestMessage.Body = memoryStream.ToArray(); request.Body.Seek(0, SeekOrigin.Begin); } } return(requestMessage); }
public override async Task <SignatureVerificationFailure> Verify(HttpRequestForSigning 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); }