Hey I want a help to solve why I’m getting the error: URL Validation Failed!, always
I’m following up the example posted here: https://developers.zoom.us/docs/api/rest/webhook-reference/#validate-your-webhook-endpoint , just in my case is from C#, using Azure function to validate the URL
I have configured ngrok to validate my endpoint but I’m not sure what happens really
[FunctionName("Events")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.User, "post", Route = "Zoom")] HttpRequest req,
ILogger log)
{
var eventSecretToken = "Here my secret token goes";
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var data = JsonConvert.DeserializeObject<DataResponse>(requestBody);
var sha256 = new System.Security.Cryptography.HMACSHA256();
sha256.Key = Encoding.ASCII.GetBytes(eventSecretToken);
var hash = sha256.ComputeHash(System.Text.Encoding.ASCII.GetBytes(data.PayLoad.PlainToken));
var hashString = ToHex(hash, false);
return new OkObjectResult(new
{
plainToken = data.PayLoad.PlainToken,
encryptedToken = hash,
});
}
private static string ToHex(byte[] bytes, bool upperCase)
{
StringBuilder result = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < bytes.Length; i++)
result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));
return result.ToString();
}
Hi @vladimir.rivera
Thanks for reaching out to us!
Have you taken a look at this sample app?
const message = `v0:${req.headers['x-zm-request-timestamp']}:${JSON.stringify(req.body)}`
const hashForVerify = crypto.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET_TOKEN).update(message).digest('hex')
// hash the message string with your Webhook Secret Token and prepend the version semantic
const signature = `v0=${hashForVerify}`
// you validating the request came from Zoom https://marketplace.zoom.us/docs/api-reference/webhook-reference#notification-structure
if (req.headers['x-zm-signature'] === signature) {
// Zoom validating you control the webhook endpoint https://marketplace.zoom.us/docs/api-reference/webhook-reference#validate-webhook-endpoint
if(req.body.event === 'endpoint.url_validation') {
const hashForValidate = crypto.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET_TOKEN).update(req.body.payload.plainToken).digest('hex')
response = {
message: {
plainToken: req.body.payload.plainToken,
encryptedToken: hashForValidate
},
status: 200
}
It looks like in your function you are not listening to the endpoint.url_validation event
Hi Elisa,
I convert that code into C# code and I have the same problem.
if (!(payload.Event.IsNullOrDefault()) && payload.Event == “endpoint.url_validation”)
{
var hashForValidate = new System.Security.Cryptography.HMACSHA256(Encoding.UTF8.GetBytes(secretToken)).ComputeHash(Encoding.UTF8.GetBytes(payload.payload.plainToken));
//hmac.ComputeHash(Encoding.UTF8.GetBytes(payload.payload.plainToken));
var hashed = ToHex(hashForValidate, false);
var validationResponse = new
{
message = new
{
plainToken = payload.payload.plainToken,
encryptedToken = hashed
},
status = 200
};
log.LogInformation($"Validation Response: {JsonConvert.SerializeObject(validationResponse)}");
return new OkObjectResult(validationResponse);
}
Any update on the above request?
Hi All, this way I fix the problem:
[FunctionName(“Events”)]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.User, “post”)] HttpRequest req,
ILogger log)
{
log.LogInformation(“C# Zoom Webhook function processed a request.”);
string hashed = "";
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var data = JsonConvert.DeserializeObject<ZoomWebhookPayload>(requestBody);
//To validate EndPoint in Zoom MarketPlace
if (!(string.IsNullOrEmpty(data.Event)) && data.Event == "endpoint.url_validation")
{
var encoding = new System.Text.ASCIIEncoding();
var sha256 = new System.Security.Cryptography.HMACSHA256();
sha256.Key = encoding.GetBytes(Environment.GetEnvironmentVariable("ZOOM_WEBHOOK_SECRET_TOKEN"));
var hash = sha256.ComputeHash(encoding.GetBytes(data.payload.plainToken));
hashed = ToHex(hash, false);
return new OkObjectResult(new
{
plainToken = data.payload.plainToken,
encryptedToken = hashed
});
}
}
private static string ToHex(byte bytes, bool upperCase)
{
StringBuilder result = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < bytes.Length; i++)
result.Append(bytes[i].ToString(upperCase ? “X2” : “x2”));
return result.ToString();
}
protected class ZoomWebhookPayload
{
public ZoomWebhookEventPayload payload { get; set; }
public string Event { get; set; }
}
protected class ZoomWebhookEventPayload
{
public string plainToken { get; set; }
}