Hi,
how to create JWT token using REST api in c#
Hi,
how to create JWT token using REST api in c#
Hey @vaibhav.bhosale, thanks for posting and using Zoom!
You can reference our JWT with Zoom guide:
https://marketplace.zoom.us/docs/guides/authorization/jwt/jwt-with-zoom
I would suggest using one of the C# libraries here:
Possible duplicate post with more info:
Thanks,
Tommy
As I recall, you need to create the token on Zoom web-page first. Put some future expiration date, then use that date in the code. You should see the same token during debugging.
Thanks @nvanderson, yes you can do that!
@vaibhav.bhosale, go here: https://marketplace.zoom.us/develop/create, create a JWT app, then on the “App Credentials” page you will see an already generated JWT token:
Thanks,
Tommy
Hi ! I used Microsoft.IdentityModel.Tokens and System.IdentityModel.Tokens.Jwt to create C# command line tool that can generate JWT token for Zoom. In payload you have to use “iss” end “exp”. Sorry, I can’t share my code exactly…
using System;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
namespace Zoom
{
public static class ZoomToken
{
public static string ZoomToken(){
// Token will be good for 20 minutes
DateTime Expiry = DateTime.UtcNow.AddMinutes(20);
string ApiKey = "YOUR_API_KEY_HERE");
string ApiSecret = "YOUR_API_SECRET_HERE";
int ts = (int)(Expiry - new DateTime(1970, 1, 1)).TotalSeconds;
// Create Security key using private key above:
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(ApiSecret));
// length should be >256b
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Finally create a Token
var header = new JwtHeader(credentials);
//Zoom Required Payload
var payload = new JwtPayload
{
{ "iss", ApiKey},
{ "exp", ts },
};
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
// Token to String so you can use it in your client
var tokenString = handler.WriteToken(secToken);
return tokenString;
}
}
}
Thanks @k.krylov!
-Tommy
@k.krylov, Thank you!
I created a one-liner to set the expiration date that works for .NET Core 3.1:
var ts = (int)DateTimeOffset.UtcNow.AddMinutes(MINUTES).ToUnixTimeSeconds();
You could replace AddMinutes
with a method of your choosing to set the expiration.
I think the problem is in the c# example code on zooms site… I took all parameters and compared the output between between the builtin signature function and the output do not match. I am going to need to pull the embeded javascript function apart and replicate in c# unless someone has an uptodate function example.
Thanks for sharing @marklackey!
-Tommy
This is what works for me on .Net Core 3.1.4
var setting = GetZoomSetting(); //This is where I picked the API Key and API Secret From
var zone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");
var utcNow = DateTime.UtcNow;
var westNow = TimeZoneInfo.ConvertTimeFromUtc(utcNow, zone);
string s = null;
TimeSpan t = westNow.AddMinutes(Convert.ToInt32(5)) - new DateTime(1970, 1, 1);
int secondsSinceEpoch = (int)t.TotalSeconds;
TimeSpan secpacific = TimeZoneInfo.ConvertTimeFromUtc(utcNow, zone) - new DateTime(1970, 1, 1);
int NowsecondsSinceEpoch = (int)secpacific.TotalSeconds;
var tokenHandler = new JwtSecurityTokenHandler();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.API.APISecret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
//Finally create a Token
var header = new JwtHeader(creds);
//Zoom Required Payload
var payload = new JwtPayload
{
{"aud",s },
{ "iss", setting.API.APIKey},
{ "exp", secondsSinceEpoch },
{"iat",NowsecondsSinceEpoch }
};
var token = new JwtSecurityToken(header, payload);
var authtoken = tokenHandler.WriteToken(token);
return authtoken;
Thanks for sharing your this code snippet @sakosile!
We appreciate you contributing to the Zoom Developer Community!
-Tommy
Hi, with this code I taking token. But, zoom api return it’s invalid token.
zoom link : https://api.zoom.us/v2/users
Hey @biss.hakanzor,
Are you passing in a JWT token or an OAuth access token as the authorization bearer header?
Thanks,
Tommy
Hi @biss.hakanzor, you’re right. I am also getting the Invalid token when I use @k.krylov 's code.
tommy, I’ve passed the JWT token as authorization bearer header but still no luck. I’ve sent an email to developersupport@zoom.us yesterday regarding the issue and looking for the quicker response because its been a couple days I am stuck in it.
My code has been in production for well over a year, and never experienced any problems. Can you show us the whole thing please
Hi @k.krylov,
Here is the sample code(with reference to your code):
private const string apiKey = “MyKey”;
private const string apiSecret = “MyKey”;
public static string ZoomToken()
{
// Token will be good for 20 minutes
DateTime Expiry = DateTime.UtcNow.AddMinutes(20);
int ts = (int)(Expiry - new DateTime(1970, 1, 1)).TotalSeconds;
// Create Security key using private key above:
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(apiSecret));
// I did changes in below line because DLL needed HmacSha256Signature instead of HmacSha256
var credentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
//Finally create a Token
var header = new JwtHeader(credentials);
//Zoom Required Payload
var payload = new JwtPayload
{
{ “iss”, apiKey},
{ “exp”, ts },
};
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
// Token to String so you can use it in your client
var tokenString = handler.WriteToken(secToken);
return tokenString;
}
And following is the code to call the API:
var jwtToken = ZoomToken();
var client = new RestClient(“https://api.zoom.us/v2/users?page_size=300&status=active”);
var request = new RestRequest(Method.GET);
request.AddHeader(“authorization”, String.Format(“Bearer {0}”, jwtToken));
IRestResponse resp = client.Execute(request);
I think the issue is because of latest DLL version, but I am not sure.
Microsoft.IdentityModel.Tokens -> v6.7.1.0
System.IdentityModel.Tokens.Jwt -> v6.7.1.0
What are the DLLs versions you have?
Make sure you are using correct API secret and Key, and your account supports API calls (i.e. not a free one, it may’ve changed lately though)
LogIn Here (https://marketplace.zoom.us/user/build)
Make sure your app is JWT and its active
Here is the class that generates my token
using System;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
namespace ZoomIntegration.Configuration {
public class ZoomToken
{
public ZoomToken(string ZoomApiKey, string ZoomApiSecret )
{
DateTime Expiry = DateTime.UtcNow.AddMinutes(5);
string ApiKey = ZoomApiKey;
string ApiSecret = ZoomApiSecret;
int ts = (int)(Expiry - new DateTime(1970, 1, 1)).TotalSeconds;
// Create Security key using private key above:
// note that latest version of JWT using Microsoft namespace instead of System
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(ApiSecret));
// Also note that securityKey length should be >256b
// so you have to make sure that your private key has a proper length
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Finally create a Token
var header = new JwtHeader(credentials);
//Zoom Required Payload
var payload = new JwtPayload
{
{ "iss", ApiKey},
{ "exp", ts },
};
var secToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
// Token to String so you can use it in your client
var tokenString = handler.WriteToken(secToken);
//string Token = tokenString;
this.Token = tokenString;
}
public string Token { get; set; }
}
}
//Here is the method to get Zoom users
private void GetAccountUsers(string ZoomApiKey, string ZoomApiSecret) {
try
{
ZoomToken zt = new ZoomToken(ZoomApiKey, ZoomApiSecret);
string Token = zt.Token;
//Create new Request
string BaseUrl = "https://api.zoom.us/v2/users?status=active&page_size=300&page_number=1";
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(BaseUrl);
myHttpWebRequest.Method = "GET";
myHttpWebRequest.ContentType = "application/json;";
myHttpWebRequest.Accept = "application/json;";
myHttpWebRequest.Headers.Add("Authorization", String.Format("Bearer {0}", Token));
//Get the associated response for the above request
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
using (StreamReader MyStreamReader = new StreamReader(myHttpWebResponse.GetResponseStream(), true))
{
this.AccountUsers = JsonConvert.DeserializeObject<AccountUsers>(MyStreamReader.ReadToEnd());
}
myHttpWebResponse.Close();
myHttpWebResponse.Dispose();
}
catch (WebException ex)
{
int errorCode = (int)((HttpWebResponse)ex.Response).StatusCode;
if (errorCode != 0)
{
ErrorCode = errorCode;
Stream MyStream = ex.Response.GetResponseStream();
StreamReader MyStreamReader = new StreamReader(MyStream, true);
this.ZoomException = JsonConvert.DeserializeObject<ZoomErrorResponse>(MyStreamReader.ReadToEnd());
//would be nice to check ZoomException for Null before throwing
throw new Exception(this.ZoomException.Message);
}
}
}
//Here are 3 models for the response
[JsonObject]
public class AccountUsers{
[JsonProperty("page_count")]
public Int32 PageCount { get; set; }
[JsonProperty("page_number")]
public Int32 PageNumber { get; set; }
[JsonProperty("page_size")]
public Int32 PageSize { get; set; }
[JsonProperty("total_records")]
public Int32 TotalRecords { get; set; }
[JsonProperty("users")]
public List<User> Users { get; set;}
}
[JsonObject]
public class User{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("type")]
public Int32 Type { get; set; }
[JsonProperty("pmi")]
public string Pmi { get; set; }
[JsonProperty("timezone")]
public string TimeZone { get; set; }
[JsonProperty("verified")]
public Int32 Verified { get; set; }
[JsonProperty("dept")]
public string Department { get; set; }
[JsonProperty("created_at")]
public DateTime CreatedAt { get; set; }
[JsonProperty("last_login_time")]
public DateTime LastLoginTime { get; set; }
[JsonProperty("last_client_version")]
public string LastClientVersion { get; set; }
}
[JsonObject]
public class ZoomErrorResponse {
[JsonProperty("code")]
public String Code { get; set; }
[JsonProperty("message")]
public String Message { get; set; }
}