# New App Validation Failure

**URL:** <https://devforum.zoom.us/t/new-app-validation-failure/96420>\
**Category:** Authentication\
**Created:** [October 9, 2023, 12:26am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420 "2023-10-09T00:26:19Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![benkatz](https://avatars.discourse-cdn.com/v4/letter/b/eb9ed0/32.png) [@benkatz](https://devforum.zoom.us/u/benkatz)\
**Post date:** [October 9, 2023, 12:26am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/1 "2023-10-09T00:26:19Z")

</div>

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:

> **[Using webhooks](https://developers.zoom.us/docs/api/rest/webhook-reference/)**
>
> The Zoom Developer Platform is an open platform that allows third-party developers to build applications and integrations upon Zoom’s video-first unified communications platform.

I have attempted to implement this and have used the discussion here for reference:

> [@Can't validate event notification endpoint URL](https://devforum.zoom.us/t/cant-validate-event-notification-endpoint-url/80380):
>
> Hello, How to validate the ‘event notification endpoint URL’?

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

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 9, 2023, 8:25am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/2 "2023-10-09T08:25:26Z")

</div>

@benkatz , could you share your validation code here?

---

<div class="post-metadata">

**Author:** ![benkatz](https://avatars.discourse-cdn.com/v4/letter/b/eb9ed0/32.png) [@benkatz](https://devforum.zoom.us/u/benkatz)\
**Post date:** [October 9, 2023, 3:00pm UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/3 "2023-10-09T15:00:45Z")

</div>

## Thanks @chunsiong.zoom

```auto
public async Task<IHttpActionResult> ZoomApi()
{
	string content = await Request.Content.ReadAsStringAsync();
	JObject jsonObject = JObject.Parse(content);
	JObject payload = (JObject)jsonObject["payload"];
	string plainToken = payload["plainToken"].ToString();
	string encryptedToken = GetHash("plainToken", StringHelpers.ZoomStsSecretToken);
	return Json(new { plainToken, encryptedToken });
}

private string GetHash(String text, String key)
{
	var encoding = new System.Text.ASCIIEncoding();
	var sha256 = new System.Security.Cryptography.HMACSHA256();
	sha256.Key = encoding.GetBytes(key);
	var hash = sha256.ComputeHash(encoding.GetBytes(text));
	var hashed = ToHex(hash, false);
	return hashed;
}

private 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();
}

```

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 10, 2023, 3:50am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/4 "2023-10-10T03:50:27Z")

</div>

@benkatz the code looks fine. Are you using the secret token instead of validation token?

 ![Screenshot 2023-10-10 at 11.49.17 AM](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/b/f/bf38be2177711ebaac8a157fadd368a84b6f37e8.png)

---

<div class="post-metadata">

**Author:** ![benkatz](https://avatars.discourse-cdn.com/v4/letter/b/eb9ed0/32.png) [@benkatz](https://devforum.zoom.us/u/benkatz)\
**Post date:** [October 10, 2023, 4:29am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/5 "2023-10-10T04:29:00Z")

</div>

@chunsiong.zoom I have tried both. In both cases, I’m getting the exact same response.

Is there any way to get a more detailed response as to the problem or another way to get validated?

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 10, 2023, 6:02am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/6 "2023-10-10T06:02:25Z")

</div>

@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.

```auto
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();
  }
}

```

---

<div class="post-metadata">

**Author:** ![benkatz](https://avatars.discourse-cdn.com/v4/letter/b/eb9ed0/32.png) [@benkatz](https://devforum.zoom.us/u/benkatz)\
**Post date:** [October 10, 2023, 2:23pm UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/7 "2023-10-10T14:23:01Z")

</div>

@chunsiong.zoom But you’re telling me that my code looks fine. What am I supposed to do at this point?

Again, is there any way to get a more detailed error message or another way to validate?

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 11, 2023, 2:43am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/8 "2023-10-11T02:43:59Z")

</div>

@benkatz ,

Here’s what I’ll do if i was debugging.

Run the code on debug mode, use postman to do a HTTP Post to my localhost debug port with this specific payload

```auto
{
  "payload": {
    "plainToken": "qgg8vlvZRS6UYooatFL8Aw"
  },
  "event_ts": 1654503849680,
  "event": "endpoint.url_validation"
}

```

Make sure I distinguish between validation event type and actual webhook events.

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 11, 2023, 4:20am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/9 "2023-10-11T04:20:31Z")

</div>

@benkatz ,

I’ve just tried draft up a quick sample code (not perfect) on [ASP.NET](http://ASP.NET) core based on my recommendations above, and have validated it successfully  
I hope this helps

```auto
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();

```

---

<div class="post-metadata">

**Author:** ![benkatz](https://avatars.discourse-cdn.com/v4/letter/b/eb9ed0/32.png) [@benkatz](https://devforum.zoom.us/u/benkatz)\
**Post date:** [October 18, 2023, 5:20pm UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/10 "2023-10-18T17:20:05Z")

</div>

@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:

{  
“plainToken”:“qgg8vlvZRS6UYooatFL8Aw”,  
“encryptedToken”:“fa771a1e8ab142631dba12864aac2129a8f74326c473c841dc3f00fe38d2ead5”  
}

Two question:

1. 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.

2. 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.

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [October 19, 2023, 12:56am UTC](https://devforum.zoom.us/t/new-app-validation-failure/96420/11 "2023-10-19T00:56:06Z")

</div>

@benkatz ,

you should be using secret token, in addition do ensure that the content type returned i “application/json”;
