118 lines
4.7 KiB
C#
118 lines
4.7 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.AspNetCore.Authentication.Facebook;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Newtonsoft.Json;
|
|
using Nop.Core;
|
|
using Nop.Plugin.ExternalAuth.Facebook.Models;
|
|
using Nop.Services.Authentication.External;
|
|
using Nop.Services.Logging;
|
|
|
|
namespace Nop.Plugin.ExternalAuth.Facebook.Controllers;
|
|
|
|
public class FacebookDataDeletionController : Controller
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly FacebookExternalAuthSettings _facebookExternalAuthSettings;
|
|
protected readonly IExternalAuthenticationService _externalAuthenticationService;
|
|
protected readonly ILogger _logger;
|
|
protected readonly IWebHelper _webHelper;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public FacebookDataDeletionController(FacebookExternalAuthSettings facebookExternalAuthSettings,
|
|
IExternalAuthenticationService externalAuthenticationService,
|
|
ILogger logger,
|
|
IWebHelper webHelper)
|
|
{
|
|
_facebookExternalAuthSettings = facebookExternalAuthSettings;
|
|
_externalAuthenticationService = externalAuthenticationService;
|
|
_logger = logger;
|
|
_webHelper = webHelper;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Utilities
|
|
|
|
/// <summary>
|
|
/// Convert string to a valid Base64 encoded string
|
|
/// </summary>
|
|
protected static string DecodeUrlBase64(string str)
|
|
{
|
|
if (string.IsNullOrEmpty(str))
|
|
return null;
|
|
|
|
str = str.Replace("-", "+").Replace("_", "/");
|
|
var paddingToAdd = (str.Length % 4) == 3 ? 1 : (str.Length % 4);
|
|
var charToAdd = new string('=', paddingToAdd);
|
|
|
|
return str += charToAdd;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
[HttpPost]
|
|
public async Task<IActionResult> DataDeletionCallback(IFormCollection form)
|
|
{
|
|
try
|
|
{
|
|
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);
|
|
}
|
|
|
|
var notificationUrl = Url.RouteUrl(FacebookAuthenticationDefaults.DataDeletionStatusCheckRoute,
|
|
new { earId = externalAuthenticationRecord?.Id ?? 0 },
|
|
_webHelper.GetCurrentRequestProtocol());
|
|
|
|
return Ok(new { url = notificationUrl, confirmation_code = $"{externalAuthenticationRecord?.Id ?? 0}" });
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
await _logger.ErrorAsync($"{FacebookAuthenticationDefaults.SystemName} data deletion error: {exception.Message}.", exception);
|
|
return BadRequest();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
} |