public SignedHttpRequestAuthenticationOptionsTests() { _sut = new SignedHttpRequestAuthenticationOptions { Realm = "UnitTests", Scheme = "TestScheme", RequestSignatureVerifier = A.Fake <IRequestSignatureVerifier>() }; }
public VerifySignature() { _httpRequest = new FakeOwinRequest { Method = "POST", Scheme = "https", Host = new HostString("unittest.com:9000") }; _options = new SignedHttpRequestAuthenticationOptions(); }
public HttpRequestSignatureAuthenticationMiddlewareTests() { _options = new SignedHttpRequestAuthenticationOptions { Realm = "UnitTests", Scheme = "TestScheme", RequestSignatureVerifier = A.Fake <IRequestSignatureVerifier>() }; _next = new FakeOwinMiddleware(); _sut = new HttpRequestSignatureAuthenticationMiddleware(_next, _options); }
public Parse() { _request = new OwinRequest(); _now = new DateTimeOffset(2020, 2, 25, 10, 29, 29, TimeSpan.Zero); _expires = _now.AddMinutes(10); _nowEpoch = _now.ToUnixTimeSeconds(); _expiresEpoch = _expires.ToUnixTimeSeconds(); _options = new SignedHttpRequestAuthenticationOptions { Scheme = "TestScheme" }; }
public SignedHttpRequestAuthenticationHandlerTests() { _sut = new SignedHttpRequestAuthenticationHandler(); _options = new SignedHttpRequestAuthenticationOptions { Realm = "UnitTests", Scheme = "TestScheme", RequestSignatureVerifier = A.Fake <IRequestSignatureVerifier>() }; _request = new OwinRequest { Host = new HostString("unittest.com:9000") }; _response = new OwinResponse(); var owinContext = A.Fake <IOwinContext>(); A.CallTo(() => owinContext.Request).Returns(_request); A.CallTo(() => owinContext.Response).Returns(_response); var init = _sut.GetType().GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); init.Invoke(_sut, new object[] { _options, owinContext }); }
public VerifySignature() { _httpRequest = new OwinRequest { Method = "POST", Scheme = "https", Host = new HostString("unittest.com:9000") }; _options = new SignedHttpRequestAuthenticationOptions(); _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 async Task <RequestSignatureVerificationResult> VerifySignature(IOwinRequest request, SignedHttpRequestAuthenticationOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var signatureParsingResult = _signatureParser.Parse(request, options); if (signatureParsingResult is SignatureParsingFailure parsingFailure) { var failure = SignatureVerificationFailure.InvalidSignature(parsingFailure.Description, parsingFailure.Failure); _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Code, failure.Message); return(new RequestSignatureVerificationResultFailure(client: null, requestForVerification: null, failure)); } var parsedSignature = ((SignatureParsingSuccess)signatureParsingResult).Signature; var eventTask = options.OnSignatureParsed; if (eventTask != null) { await eventTask.Invoke(request, parsedSignature).ConfigureAwait(continueOnCapturedContext: false); } var requestForVerification = request.ToHttpRequestForVerification(parsedSignature); return(await _verificationOrchestrator.VerifySignature(requestForVerification).ConfigureAwait(continueOnCapturedContext: false)); }
public SignatureParsingResult Parse(IOwinRequest request, SignedHttpRequestAuthenticationOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } var authHeader = request.Headers[AuthorizationHeaderName]; if (string.IsNullOrEmpty(authHeader)) { return(new SignatureParsingFailure($"The specified request does not specify a value for the {AuthorizationHeaderName} header.")); } var separatorIndex = authHeader.IndexOf(' '); if (separatorIndex < 0) { return(new SignatureParsingFailure( $"The specified request does not specify a valid authentication parameter in the {AuthorizationHeaderName} header.")); } var authScheme = authHeader.Substring(0, separatorIndex); if (authScheme != options.Scheme && authScheme != options.Scheme) { return(new SignatureParsingFailure( $"The specified request does not specify the expected {options.Scheme} scheme in the {AuthorizationHeaderName} header.")); } if (separatorIndex >= authHeader.Length - 1) { return(new SignatureParsingFailure( $"The specified request does not specify a valid authentication parameter in the {AuthorizationHeaderName} header.")); } var authParam = authHeader.Substring(separatorIndex + 1); _logger?.LogDebug("Parsing authorization header parameter for verification: {0}.", authParam); var authParamParts = authParam.Split(','); var keyId = KeyId.Empty; var algorithm = string.Empty; var createdString = string.Empty; var expiresString = string.Empty; var headersString = string.Empty; string nonce = null; var signature = string.Empty; foreach (var authParamPart in authParamParts) { var keyIdSelector = "keyId="; if (authParamPart.StartsWith(keyIdSelector, StringComparison.Ordinal)) { if (keyId != KeyId.Empty) { return(new SignatureParsingFailure($"Duplicate '{keyIdSelector}' found in signature.")); } var value = authParamPart.Substring(keyIdSelector.Length).Trim('"'); keyId = new KeyId(value); } var algorithmSelector = "algorithm="; if (authParamPart.StartsWith(algorithmSelector, StringComparison.Ordinal)) { if (algorithm != string.Empty) { return(new SignatureParsingFailure($"Duplicate '{algorithmSelector}' found in signature.")); } var value = authParamPart.Substring(algorithmSelector.Length).Trim('"'); algorithm = value; } var createdSelector = "created="; if (authParamPart.StartsWith(createdSelector, StringComparison.Ordinal)) { if (createdString != string.Empty) { return(new SignatureParsingFailure($"Duplicate '{createdSelector}' found in signature.")); } var value = authParamPart.Substring(createdSelector.Length).Trim('"'); createdString = value; } var expiresSelector = "expires="; if (authParamPart.StartsWith(expiresSelector, StringComparison.Ordinal)) { if (expiresString != string.Empty) { return(new SignatureParsingFailure($"Duplicate '{expiresSelector}' found in signature.")); } var value = authParamPart.Substring(expiresSelector.Length).Trim('"'); expiresString = value; } var headersSelector = "headers="; if (authParamPart.StartsWith(headersSelector, StringComparison.Ordinal)) { if (headersString != string.Empty) { return(new SignatureParsingFailure($"Duplicate '{headersSelector}' found in signature.")); } var value = authParamPart.Substring(headersSelector.Length).Trim('"'); headersString = value; } var nonceSelector = "nonce="; if (authParamPart.StartsWith(nonceSelector, StringComparison.Ordinal)) { if (!string.IsNullOrEmpty(nonce)) { return(new SignatureParsingFailure($"Duplicate '{nonceSelector}' found in signature.")); } var value = authParamPart.Substring(nonceSelector.Length).Trim('"'); nonce = value; } var signatureSelector = "signature="; if (authParamPart.StartsWith(signatureSelector, StringComparison.Ordinal)) { if (signature != string.Empty) { return(new SignatureParsingFailure($"Duplicate '{signatureSelector}' found in signature.")); } var value = authParamPart.Substring(signatureSelector.Length).Trim('"'); signature = value; } } DateTimeOffset?created = null; if (long.TryParse(createdString, out var createdEpoch)) { created = DateTimeOffset.FromUnixTimeSeconds(createdEpoch); } DateTimeOffset?expires = null; if (long.TryParse(expiresString, out var expiresEpoch)) { expires = DateTimeOffset.FromUnixTimeSeconds(expiresEpoch); } var headerNames = Array.Empty <HeaderName>(); if (!string.IsNullOrEmpty(headersString)) { headerNames = headersString .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) .Select(s => new HeaderName(s)).ToArray(); } var parsedSignature = new Signature { KeyId = keyId, Algorithm = string.IsNullOrEmpty(algorithm) ? null : algorithm.Trim(), Created = created, Expires = expires, Headers = headerNames.Any() ? headerNames : null, Nonce = nonce, String = signature }; try { parsedSignature.Validate(); } catch (ValidationException ex) { return(new SignatureParsingFailure( $"The specified request does not specify a valid signature in the {AuthorizationHeaderName} header. See inner exception.", ex)); } return(new SignatureParsingSuccess(parsedSignature)); }
public static IAppBuilder UseHttpRequestSignatureAuthentication(this IAppBuilder app, SignedHttpRequestAuthenticationOptions options) { if (app == null) { throw new ArgumentNullException(nameof(app)); } app.Use <HttpRequestSignatureAuthenticationMiddleware>(options); app.UseStageMarker(PipelineStage.Authenticate); return(app); }
public async Task <RequestSignatureVerificationResult> VerifySignature(IOwinRequest request, SignedHttpRequestAuthenticationOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } Client client = null; Signature signature = null; try { signature = _signatureParser.Parse(request, options); var eventTask = options.OnSignatureParsed; if (eventTask != null) { await eventTask.Invoke(request, signature).ConfigureAwait(false); } try { signature.Validate(); } catch (ValidationException ex) { throw new InvalidSignatureException( "The signature is invalid. See inner exception.", ex); } client = await _clientStore.Get(signature.KeyId).ConfigureAwait(false); if (client == null) { var failure = SignatureVerificationFailure.InvalidClient($"No {nameof(Client)}s with id '{signature.KeyId}' are registered in the server store."); _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Code, failure.Message); return(new RequestSignatureVerificationResultFailure(client, signature, failure)); } var requestForSigning = request.ToHttpRequestForSigning(); var verificationFailure = await _signatureVerifier.VerifySignature(requestForSigning, signature, client).ConfigureAwait(false); var verificationResultCreator = _verificationResultCreatorFactory.Create(client, signature); var result = verificationFailure == null ? verificationResultCreator.CreateForSuccess() : verificationResultCreator.CreateForFailure(verificationFailure); if (result is RequestSignatureVerificationResultSuccess success) { _logger?.LogDebug($"Request signature verification succeeded for principal {success.Principal?.Identity?.Name ?? "[null]"}."); } else if (result is RequestSignatureVerificationResultFailure failure) { _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Failure.Code, failure.Failure.Message); } return(result); } catch (InvalidSignatureException ex) { var failure = SignatureVerificationFailure.InvalidSignature(ex.Message, ex); _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Code, failure.Message); return(new RequestSignatureVerificationResultFailure(client, signature, failure)); } }
public async Task <RequestSignatureVerificationResult> VerifySignature(IOwinRequest request, SignedHttpRequestAuthenticationOptions options) { if (request == null) { throw new ArgumentNullException(nameof(request)); } Client client = null; Signature signature = null; try { signature = _signatureParser.Parse(request); client = await _clientStore.Get(signature.KeyId); var requestForSigning = request.ToHttpRequestForSigning(); var verificationFailure = await _signatureVerifier.VerifySignature(requestForSigning, signature, client); var verificationResultCreator = _verificationResultCreatorFactory.Create(client, signature); var result = verificationFailure == null ? verificationResultCreator.CreateForSuccess() : verificationResultCreator.CreateForFailure(verificationFailure); if (result is RequestSignatureVerificationResultSuccess success) { _logger?.LogDebug($"Request signature verification succeeded for principal {success.Principal?.Identity?.Name ?? "[null]"}."); } else if (result is RequestSignatureVerificationResultFailure failure) { _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Failure.Code, failure.Failure.Message); } return(result); } catch (InvalidClientException ex) { var failure = SignatureVerificationFailure.InvalidClient(ex.Message, ex); _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Code, failure.Message); return(new RequestSignatureVerificationResultFailure(client, signature, failure)); } catch (InvalidSignatureException ex) { var failure = SignatureVerificationFailure.InvalidSignature(ex.Message, ex); _logger?.LogWarning("Request signature verification failed ({0}): {1}", failure.Code, failure.Message); return(new RequestSignatureVerificationResultFailure(client, signature, failure)); } }