Skip to content
Snippets Groups Projects
Commit 27413871 authored by Klaus Fischer's avatar Klaus Fischer
Browse files

Problems with Mocking WebRequest due to internal contructor

parent ac4efef7
No related branches found
No related tags found
1 merge request!6Routing Api
......@@ -10,7 +10,6 @@ using FitConnect.Models;
using FitConnect.Models.v1.Api;
using FitConnect.Services.Models.v1.Submission;
using IdentityModel;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NJsonSchema;
......@@ -202,34 +201,20 @@ public class Subscriber : FitConnectClient,
Logger?.LogInformation("Submission completed {status}", result);
}
public static string VerifyCallback(string callbackSecret,
long timestamp, string body) {
public static bool VerifyCallback(WebRequest request) {
var timestamp = long.Parse(request.Headers["callback-timestamp"] ?? "0");
if (timestamp < DateTime.Now.AddMinutes(-5).ToEpochTime())
throw new ArgumentException("Request is too old");
var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(callbackSecret))
.ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}.{body}"));
return Convert.ToHexString(hmac).ToLower();
}
public static bool VerifyCallback(string callbackSecret, HttpRequest request) {
if (!request.Headers.ContainsKey("callback-timestamp"))
throw new ArgumentException("Missing callback-timestamp header");
var timeStampString = request.Headers["callback-timestamp"].ToString();
if (!long.TryParse(timeStampString, out var timestamp)) {
throw new ArgumentException("Invalid callback-timestamp header");
}
var authentication = request.Headers["callback-authentication"];
using var requestStream = request.Body;
var content = new StreamReader(requestStream).ReadToEnd().Trim();
var secret = request.Headers["callback-authentication"] ?? "";
using var requestStream = request.GetRequestStream();
var content = new StreamReader(requestStream).ReadToEnd();
var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(secret)).ComputeHash(
Encoding.UTF8.GetBytes(request.Headers["callback-timestamp"] + "." + content));
var hmacString = Convert.ToHexString(hmac);
var result = VerifyCallback(callbackSecret, timestamp, content);
if (result != authentication)
if (hmacString != secret)
throw new ArgumentException("Request is not authentic");
return true;
}
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using Autofac;
using FluentAssertions;
using IdentityModel;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using MockContainer;
using Moq;
using NUnit.Framework;
......@@ -17,8 +11,7 @@ namespace IntegrationTests;
[TestFixture]
public class CallbackTest {
private HttpRequest Request;
private string _callbackSecret = "";
private WebRequest Request;
[SetUp]
public void Setup() {
......@@ -28,13 +21,13 @@ public class CallbackTest {
//
// {"type":"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions","submissionIds":["f39ab143-d91a-474a-b69f-b00f1a1873c2"]}
// HttpRequest request = null!;
// request.Headers
// request.Headers.Add("callback-authentication",
// "798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df");
// request.Headers.Add("callback-timestamp", DateTime.Now.ToEpochTime().ToString());
// request.Method = "POST";
// request.ContentType = "application/json";
var request = HttpWebRequest.Create(
"https://fachverfahren.beispielstadt.example.org/callbacks/fit-connect");
request.Headers.Add("callback-authentication",
"798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df");
request.Headers.Add("callback-timestamp", DateTime.Now.ToEpochTime().ToString());
request.Method = "POST";
request.ContentType = "application/json";
var memoryStream = new MemoryStream();
var streamWriter = new StreamWriter(memoryStream);
......@@ -44,49 +37,24 @@ public class CallbackTest {
streamWriter.Flush();
memoryStream.Position = 0;
// Request = new DefaultHttpRequest(new DefaultHttpContext()) {
// Body = new StreamBody(memoryStream)
// };
var headers = new HeaderDictionary(new Dictionary<string, StringValues>() {
{ "callback-timestamp", "1672527599" }, {
"callback-authentication",
"798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df"
}
});
var mock =
new Mock<HttpRequest>();
new Mock<HttpWebRequest>(
"https://fachverfahren.beispielstadt.example.org/callbacks/fit-connect");
mock.Setup(w => w.ContentType).Returns("application/json");
mock.Setup(w => w.Headers).Returns(headers);
mock.Setup(w => w.Headers).Returns(request.Headers);
mock.Setup(w => w.Method).Returns("POST");
mock.Setup(w => w.Body).Returns(memoryStream);
mock.Setup(w => w.GetRequestStream()).Returns(memoryStream);
mock.Setup(w => w.RequestUri)
.Returns(new Uri(
"https://fachverfahren.beispielstadt.example.org/callbacks/fit-connect"));
Request = mock.Object;
_callbackSecret = MockContainer.Container.Create().Resolve<MockSettings>().CallbackSecret;
}
[Test]
public void ValidRequest_WithSingeValues() {
// Arrange
//Act
var authentication = FitConnect.Subscriber.VerifyCallback(_callbackSecret, 1672527599,
"{\"type\":\"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions\",\"submissionIds\":[\"f39ab143-d91a-474a-b69f-b00f1a1873c2\"]}"
);
// Assert
authentication.Should()
.Be(
"798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df");
}
[Test]
public void ValidRequest() {
// Assert
FitConnect.Subscriber.VerifyCallback(_callbackSecret, Request).Should().Be(true);
FitConnect.Subscriber.VerifyCallback(Request).Should().Be(true);
}
[Test]
......@@ -96,9 +64,7 @@ public class CallbackTest {
// Atc
// Assert
Assert.Throws<ArgumentException>(() => {
FitConnect.Subscriber.VerifyCallback(_callbackSecret, Request);
})
Assert.Throws<ArgumentException>(() => { FitConnect.Subscriber.VerifyCallback(Request); })
.Message.Should().Be("Request is too old");
}
......@@ -110,9 +76,7 @@ public class CallbackTest {
// Atc
// Assert
Assert.Throws<ArgumentException>(() => {
FitConnect.Subscriber.VerifyCallback(_callbackSecret, Request);
})
Assert.Throws<ArgumentException>(() => { FitConnect.Subscriber.VerifyCallback(Request); })
.Message.Should().Be("Request is not authentic");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment