// Compute content hash.
computedChecksum = ComputeSHA256Hash(request.Body).ToBase64();
// Prepare string to sign.
timestamp = request.Headers["Cm-Date"];
// Example:
// POST
// /api/cm/get_game_account
// 2021-11-09T13:52:27.4637477+00:00;example.com;t2jaQHi3fQt0FQ2HPtUeY/TGVNgQmspupcaUUYytrYI=
stringToSign = "{request.Method}\n{request.PathAndQuery}\n{timestamp};{request.Authority};{computedChecksum}";
// Compute and validate signature.
computedSignature = Base64Encode(HMACSHA256.Compute(stringToSign, PreSharedKey));
claimedSignature = request.Headers.Authorization.Split("Signature=")[1];
if (claimedSignature != computedSignature)
{
return AuthenticateResult.Fail("Invalid HMAC signature");
}
Authorize();// Validate expiry.
if (DateTime.UtcNow - DateTime.ParseIso8601(timestamp) > Lifespan)
{
return AuthenticateResult.Fail("Timestamp is too old");
}
// Validate checksum.
claimedChecksum = request.Headers["Content-SHA256"];
if (claimedChecksum != computedChecksum)
{
return AuthenticateResult.Fail("Incorrect checksum");
}
// Validate timestamp uniqueness.
if (Cache.Contains(timestamp))
{
return AuthenticateResult.Fail("Timestamp not unique");
}
Cache.Add(timestamp, DateTime.UtcNow + Lifespan);