I am attempting to set up a new " Server-to-Server OAuth" app before full depreciation of JWT apps takes effect.
I’m working on the endpoint validation per the specifications here:
I have attempted to implement this and have used the discussion here for reference:
However, this is not working. I receive the unspecific error message: “URL validation failed. Try again later.”
How can I get more information about why this is failing?
I am not sure if:
(a) I’m using the wrong token.
(b) There is a flaw in my hash code.
(c) There is another requirement of the response that is not clearly documented.
(d) There is
(e) Something else
@benkatz , I don’t have sample code in C#, but here’s how I’m doing it in nodejs JavaScript.
It will check the POST request body, for key value pair where event = ‘endpoint.url_validation’,
There after it does something similar to your code.
if (req.method === 'POST') {
// Check if the event type is "endpoint.url_validation"
if (req.body.event === 'endpoint.url_validation') {
const hashForValidate = crypto.createHmac('sha256', secretToken)
.update(req.body.payload.plainToken)
.digest('hex');
res.status(200).json({
"plainToken": req.body.payload.plainToken,
"encryptedToken": hashForValidate
});
} else {
// Write the request data to a file
fs.writeFile(filePath, JSON.stringify(req.body), 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log(`The file ${filePath} was saved!`);
});
res.status(200).send();
}
}
I’ve just tried draft up a quick sample code (not perfect) on ASP.NET core based on my recommendations above, and have validated it successfully
I hope this helps
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.MapPost("/webhook", async context =>
{
// Get the request content as a string asynchronously
string requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
try
{
JObject jsonObject = JObject.Parse(requestBody);
JObject payload = (JObject)jsonObject["payload"];
string plainToken = payload["plainToken"].ToString();
string encryptedToken = GetHash(plainToken, "yoursecrettokenhere");
var response = new
{
plainToken,
encryptedToken
};
context.Response.ContentType = "application/json";
// Write the JSON response
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
}
catch (Exception ex)
{
await context.Response.WriteAsync("Error: " + ex.ToString());
}
});
string GetHash(string text, string key)
{
using (HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(text));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
app.Run();
@chunsiong.zoom Thank you for your continued help, but I am still not able to get this to work. My test post is returning a response in what appears to be the proper format:
Should I be using the “Secret Token” or the “Verification Token”. I’ve been trying both but having a clear answer on that would eliminate a bit of uncertainty.
Is there any way to get more information about why this is failing? In particular it would be useful to know if Zoom is not getting values for the returned tokens or if there is a problem with the returned values.