Reputation: 4572
Creating a webhook handler in MVC 4 to handle EasyPost webhook calls. I have it all working but now want to add in some authentication.
Easypost suggests a method of including a user name or secret key in the webhook handler url such as: https://username:[email protected]/easypost-webhook
reference. Then I presume extracting that secret key value and comparing to an expected value. I'm attempting to do this via regex.
The problem is I cannot find how to retrieve the username:secret@
portion of the url in the controller. Tried Request.RawUrl
and searched all data in the Request Object, to no avail.
My Code:
public class ParcelShippingWebHooksController : Controller
{
[ValidateInput(false)]
[HttpPost]
public ActionResult ParcelTrackingWebHookHandler()
{
//Authenticate request
string key = AppSettings.ParcelTrackingWebhookSecretKey;
string url = Request.RawUrl; <---- how get raw url
string strPattern = @"secretkey:(.*)\@";
Match match = Regex.Match(url, strPattern);
if(!match.Success) return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
if(match.Value != key) return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
//Convert request to string
byte[] param = Request.BinaryRead(Request.ContentLength);
string strWebHookDataRequest = Encoding.ASCII.GetString(param);
//perform tracking updates
var webhookAppServ = new ParcelShippingWebHooksAppServ(new InventoryMgmtContext());
var updateTrackingResult = webhookAppServ.UpdateParcelTrackingStatusFromWebHook(strWebHookDataRequest);
if (updateTrackingResult.WasSuccessful)
{
return new HttpStatusCodeResult(HttpStatusCode.OK); // OK = 200
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
}
}
Upvotes: 0
Views: 1698
Reputation: 5689
The Easypost reference you are referencing is implying that you use Basic Authentication + SSL.
You'll need to setup MVC to check for that authentication. Here is a sample, taken from this article - Basic Authentication in MVC 5:
BasicAuthenticationAttribute
public class BasicAuthenticationAttribute : ActionFilterAttribute
{
public string BasicRealm { get; set; }
protected string Username { get; set; }
protected string Password { get; set; }
public BasicAuthenticationAttribute(string username, string password)
{
this.Username = username;
this.Password = password;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var req = filterContext.HttpContext.Request;
var auth = req.Headers["Authorization"];
if (!String.IsNullOrEmpty(auth))
{
var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
var user = new { Name = cred[0], Pass = cred[1] };
if (user.Name == Username && user.Pass == Password) return;
}
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
/// thanks to eismanpat for this line: http://www.ryadel.com/en/http-basic-authentication-asp-net-mvc-using-custom-actionfilter/#comment-2507605761
filterContext.Result = new HttpUnauthorizedResult();
}
}
Sample Controler
[BasicAuthenticationAttribute("your-username", "your-password", BasicRealm = "your-realm")]
public class HomeController : BaseController
{
...
}
Upvotes: 1