Introduction
JSON Web Token (JWT) is an open standard defined in RFC 7519 used for securely transmitting information between parties as a JSON object. JWT is widely used for authentication and authorization in modern API-based systems.
This article explains:
What JWT is
How JWT encoding works (Header + Payload + Signature)
Real-time example using HS256
How to generate JWT in ASP.NET C#
How to create a reusable GenerateJwtToken method
How to call an API using the generated token
How to handle API responses (array or object) with proper error handling
What is JWT?
JWT (JSON Web Token) is a compact, URL-safe string made of three parts:
Header.Payload.Signature
Example JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0
.
KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
JWT Structure Explained
JWT contains three components:
Header – Algorithm & Token Type
{
"alg": "HS256",
"typ": "JWT"
}
HS256 means HMAC with SHA-256 using a secret key.
Payload – Data (Claims)
{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}
Common claims:
sub → Subject (User ID)
name → User name
admin → Role
iat → Issued at time
Important: Payload is encoded, not encrypted.
Signature – Secret
Secret:
a-string-secret-at-least-256-bits-long
Signature is created using:
HMACSHA256(
Base64UrlEncode(header) + "." +
Base64UrlEncode(payload),
secret
)
Final JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0
.
KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
Real-Time ASP.NET C# Implementation (HS256)
Required Libraries
Common JWT Libraries:
Step 1: Create a Model Based on Payload
public class JwtRequestModel
{
public string sub { get; set; }
public string name { get; set; }
public bool admin { get; set; }
public long iat { get; set; }
}
Usage:
var requestObj = new JwtRequestModel
{
sub = "1234567890",
name = "John Doe",
admin = true,
iat = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
};
Step 2: Reusable GenerateJwtToken Method
You can generate one token and reuse it for multiple API calls if it is still valid.
private string GenerateJwtToken<T>(T requestObj)
{
var header = new { alg = "HS256", typ = "JWT" };
string headerBase64 = Base64UrlEncode(
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header)));
string payloadBase64 = Base64UrlEncode(
Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(requestObj)));
string unsignedToken = headerBase64 + "." + payloadBase64;
using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey)))
{
string signature = Base64UrlEncode(
hmac.ComputeHash(Encoding.UTF8.GetBytes(unsignedToken)));
return unsignedToken + "." + signature;
}
}
Base64Url Encode Method:
private static string Base64UrlEncode(byte[] input)
{
return Convert.ToBase64String(input)
.TrimEnd('=')
.Replace('+', '-')
.Replace('/', '_');
}
Generate Token:
string jwtToken = GenerateJwtToken(requestObj);
LogError("JWT GENERATED : " + jwtToken);
Step 3: Call API Using JWT Token
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
var content = new StringContent(jwtToken, Encoding.UTF8, "text/plain");
HttpResponseMessage response = await client.PostAsync(apiUrl, content);
LogError("API STATUS: " + response.StatusCode);
if (!response.IsSuccessStatusCode)
{
ShowApiError("HTTP Error: " + response.StatusCode);
return;
}
string responseData = await response.Content.ReadAsStringAsync();
LogError("API RESPONSE: " + responseData);
}
Step 4: Handle API Response (Array or Object)
try
{
JToken parsedJson = JToken.Parse(responseData);
if (parsedJson.Type == JTokenType.Array)
{
var dataArray = parsedJson.ToObject<List<object>>();
LogError("Array Response Count: " + dataArray.Count);
}
else if (parsedJson.Type == JTokenType.Object)
{
var dataObject = parsedJson.ToObject<Dictionary<string, object>>();
LogError("Object Response Keys: " + dataObject.Count);
}
}
catch (JsonReaderException ex)
{
LogError("Invalid JSON: " + ex.Message);
}
catch (Exception ex)
{
LogError("General Error: " + ex.Message);
}
Full Try-Catch with API Call
try
{
string jwtToken = GenerateJwtToken(requestObj);
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(30);
var content = new StringContent(jwtToken, Encoding.UTF8, "text/plain");
HttpResponseMessage response = await client.PostAsync(apiUrl, content);
if (!response.IsSuccessStatusCode)
{
ShowApiError("HTTP Error: " + response.StatusCode);
return;
}
string responseData = await response.Content.ReadAsStringAsync();
JToken parsedJson = JToken.Parse(responseData);
if (parsedJson.Type == JTokenType.Array)
{
// Handle array
}
else
{
// Handle object
}
}
}
catch (TaskCanceledException)
{
ShowApiError("Request Timeout");
}
catch (HttpRequestException ex)
{
ShowApiError("HTTP Request Error: " + ex.Message);
}
catch (Exception ex)
{
ShowApiError("Unexpected Error: " + ex.Message);
}
Important Notes
You can generate one token and reuse it across multiple API calls if expiration is valid.
Always store secret key securely (AppSettings or environment variable).
Always use HTTPS.
Add expiration (exp claim) in production.
Do not store sensitive data in payload.
Real-World Example Scenario
Imagine a financial payout system:
Your system generates a JWT using merchant ID and timestamp.
The token is signed with HS256.
The token is sent to the payout API.
The payout server validates signature using the shared secret.
If valid → request processed.
If invalid → rejected.
This ensures secure and tamper-proof API communication.
Conclusion
JWT using HS256 in ASP.NET C# is:
Secure
Stateless
Scalable
Easy to integrate
By creating a reusable GenerateJwtToken method, you can generate a single conversation token and use it efficiently across multiple API calls.