Closed hobbykitjr closed 2 years ago
👋 Hi there! Thanks for your contribution to the project by posting your first issue!
I hope this helps someone else.
First in your startup.cs enable buffering in your config. This is for .net core 3.1, if you have something else, try here: https://stackoverflow.com/questions/40494913/how-to-read-request-body-in-an-asp-net-core-webapi-controller
app.Use((context, next) =>
{
context.Request.EnableBuffering();
return next();
});
Then you'll need a verification method like so:
private static async Task<bool> ValidateRequest(HttpRequest request, SkillRequest skillRequest)
{
request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
if (string.IsNullOrWhiteSpace(signatureChainUrl))
{
Trace.TraceError("Validation failed. Empty SignatureCertChainUrl header");
return false;
}
Uri certUrl;
try
{
certUrl = new Uri(signatureChainUrl);
}
catch
{
Trace.TraceError($"Validation failed. SignatureChainUrl not valid: {signatureChainUrl}");
return false;
}
request.Headers.TryGetValue("Signature", out var signature);
if (string.IsNullOrWhiteSpace(signature))
{
Trace.TraceError("Validation failed - Empty Signature header");
return false;
}
request.Body.Seek(0, SeekOrigin.Begin);
string body;
using (StreamReader stream = new StreamReader(request.Body))
{
body = stream.ReadToEnd();
}
if (string.IsNullOrWhiteSpace(body))
{
Trace.TraceError("Validation failed - the JSON is empty");
return false;
}
bool isTimestampValid = RequestVerification.RequestTimestampWithinTolerance(skillRequest);
bool valid = await RequestVerification.Verify(signature, certUrl, body);
if (!valid || !isTimestampValid)
{
Trace.TraceError("Validation failed - RequestVerification failed");
return false;
}
else
{
return true;
}
}
Finally, at the start of your handle request. Get the HttpRequest out of the HttpContext
[HttpPost]
public ActionResult<SkillResponse> HandleRequest([FromBody] SkillRequest skillRequest) {
var request = HttpContext.Request;
bool isValid = AlexaController.ValidateRequest(request, skillRequest).Result;
if (!isValid)
{
return new BadRequestResult();
}
....
the validation method will rewind the body stream and check the whole thing for the cert.
Related discussion #184
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Sorry, I don't see where/how to get the httpRequest object to validate the skill request?
the project starts w/ SkillRequest which has all the HTTP header stripped already. How do you get the HttpRequest object to validate the request so the skill can be published (Amazon is rejecting my skill using this project because of this)
all requests to your api must validate they came from amazon and are recent if you want to publish it. Thanks,