nopSolutions/nopCommerce · error · NopException
Hash validation failed
Error message
Hash validation failed
What it means
Thrown by FacebookDataDeletionController.DataDeletionCallback as a NopException when the HMAC-SHA256 of split[1] (the payload) computed with the app secret does not match the provided signature. This is the cryptographic integrity check for Facebook signed requests.
Source
Thrown at src/Plugins/Nop.Plugin.ExternalAuth.Facebook/Controllers/FacebookDataDeletionController.cs:85
{
string signed_request = form["signed_request"];
if (string.IsNullOrEmpty(signed_request))
throw new NopException("Request data is missing");
var split = signed_request.Split('.');
var signatureRaw = DecodeUrlBase64(split[0]);
var dataRaw = DecodeUrlBase64(split[1]);
if (string.IsNullOrEmpty(signatureRaw) || string.IsNullOrEmpty(dataRaw))
throw new NopException("Part of the request data is missing");
var signature = Convert.FromBase64String(signatureRaw);
var dataBuffer = Convert.FromBase64String(dataRaw);
var json = Encoding.UTF8.GetString(dataBuffer);
var appSecretBytes = Encoding.UTF8.GetBytes(_facebookExternalAuthSettings.ClientSecret);
HMAC hmac = new HMACSHA256(appSecretBytes);
var expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(split[1]));
if (!expectedHash.SequenceEqual(signature))
throw new NopException("Hash validation failed");
var fbUser = JsonConvert.DeserializeObject<FacebookUserDTO>(json);
var authenticationParameters = new ExternalAuthenticationParameters
{
ProviderSystemName = FacebookAuthenticationDefaults.SystemName,
AccessToken = await HttpContext.GetTokenAsync(FacebookDefaults.AuthenticationScheme, "access_token"),
ExternalIdentifier = fbUser.UserId
};
var externalAuthenticationRecord = await _externalAuthenticationService.GetExternalAuthenticationRecordByExternalAuthenticationParametersAsync(authenticationParameters);
if (externalAuthenticationRecord is not null)
{
await _logger.InformationAsync($"{FacebookAuthenticationDefaults.SystemName} data deletion completed. " +
$"CustomerId: {externalAuthenticationRecord.CustomerId}, " +
$"CustomerEmail: {externalAuthenticationRecord.Email}, " +
$"ExternalAuthenticationRecordId: {externalAuthenticationRecord.Id}");
await _externalAuthenticationService.DeleteExternalAuthenticationRecordAsync(externalAuthenticationRecord);
}View on GitHub (pinned to 64bdf2ff08)
Solutions
- Update _facebookExternalAuthSettings.ClientSecret to the current Facebook App Secret for the app that issued the callback.
- After rotating a Facebook app secret, immediately update the plugin configuration for all stores/environments.
- Confirm the request was not modified by a proxy (HTTPS termination, body rewriting).
Example fix
// before: ClientSecret is stale / from another app // after: set current secret from developers.facebook.com > App Settings > Advanced settings.ClientSecret = "<current app secret>"; await _settingService.SaveSettingAsync(settings, storeScope);
Defensive patterns
Strategy: validation
Validate before calling
var expected = new HMACSHA256(Encoding.UTF8.GetBytes(secret)).ComputeHash(Encoding.UTF8.GetBytes(payload));
if (!expected.SequenceEqual(signature))
// secret mismatch — alert ops to rotate/update config Try / catch
try { return await DataDeletionCallback(form); }
catch (NopException ex) when (ex.Message.Contains("Hash validation failed"))
{ logger.Error("Facebook signature mismatch — check app secret config.", ex); return Unauthorized(); } Prevention
- Keep the configured ClientSecret in sync with the Facebook app secret.
- Update config immediately after rotating secrets.
- Treat signature mismatch as a security event, not a transient error.
When it happens
Trigger: The signature in signed_request does not match HMAC-SHA256(payload, appSecret). Causes: the configured ClientSecret is wrong/different from the app that signed the request, the payload was tampered with, or the app has multiple secrets and the wrong one is configured.
Common situations: Rotated the Facebook app secret but did not update the plugin config; copied config from a different Facebook app; payload altered in transit; using the wrong environment's secret.
Related errors
- Request data is missing
- Part of the request data is missing
- Facebook authentication module not configured
- Facebook authentication module cannot be loaded
- Azure connection string for Blob is not specified
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/fe8f767ad08632e6.
Report an issue: GitHub.