Introduction
In ASP.NET applications that integrate with secure APIs, JSON Web Tokens (JWT) are commonly used to authenticate requests. A JWT ensures that request data is signed and cannot be modified without detection.
In this scenario, there are two versions of the GenerateJwtToken method. Both share the same core concept: encoding and signing a JWT using the HS256 algorithm, but they differ in flexibility, design, and reusability.
This article explains:
The concept behind JWT generation
The purpose of these methods
Their differences
Which approach is better, depending on the scenario
Understanding the JWT Generation Concept
A JWT consists of three parts:
Header.Payload.Signature
Header
Contains metadata such as:
Algorithm (HS256)
Token type (JWT)
Payload
Contains the request data or claims that need to be securely transmitted.
Signature
Created using HMACSHA256 and a secret key to ensure integrity and authenticity.
JWT Generation Process
Serialize header to JSON.
Serialize payload to JSON.
Base64Url encode both values.
Combine them using a dot separator.
Sign the combined string using HMACSHA256 with a secret key.
Append the signature to produce the final token.
Both methods follow this exact process.
Purpose of GenerateJwtToken in ASP.NET
Generating a JWT in ASP.NET is required:
To securely send request data to an external API.
To allow the API to verify authenticity.
To prevent tampering with request parameters.
To implement stateless authentication.
Without this token generation process, the API cannot verify whether the request is trusted.
First Method: Non-Generic Version
Models
public class RequestRoot
{
public List<PayoutRequest> req { get; set; }
}
public class Request
{
public string ID { get; set; }
public string clientid { get; set; }
}
Method Implementation
private string GenerateJwtToken(RequestRoot requestObj)
{
var header = new { alg = "HS256", typ = "JWT" };
var payload = requestObj;
string headerJson = JsonConvert.SerializeObject(header);
string payloadJson = JsonConvert.SerializeObject(payload);
string headerBase64 = Base64UrlEncode(Encoding.UTF8.GetBytes(headerJson));
string payloadBase64 = Base64UrlEncode(Encoding.UTF8.GetBytes(payloadJson));
string unsignedToken = headerBase64 + "." + payloadBase64;
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
using (var hmac = new HMACSHA256(keyBytes))
{
var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(unsignedToken));
string signature = Base64UrlEncode(signatureBytes);
return unsignedToken + "." + signature;
}
}
This version is tightly coupled to a specific request type.
Characteristics
Accepts only one specific model type.
Explicit header and payload handling.
Slightly more readable for beginners.
Suitable for single-purpose implementations.
Advantages
Clear structure.
Easier debugging.
Strong type safety for a specific business case.
Disadvantages
Not reusable for other request types.
Requires additional methods if new models are introduced.
Less flexible.
Second Method: Generic Version
Usage Example
private async Task GetMaxAmount(string uid)
{
try
{
LogError("API CALL STARTED for UID: " + uid);
var requestObj = new RequestRoot
{
req = new List<Request>
{
new Request
{
ID = uid,
clientid = uid
}
}
};
string jwtToken = GenerateJwtToken(requestObj);
}
}
Generic Method
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;
}
}
This version uses generics and can accept any model type.
Characteristics
Works with any request object.
More reusable.
Cleaner and shorter implementation.
Ideal for scalable applications.
Advantages
Highly reusable.
Reduces duplicate code.
Easier maintenance.
Supports multiple API request models.
Disadvantages
Slightly less explicit for beginners.
Requires understanding of generics in C#.
Are Both Methods Based on the Same Concept?
Yes. Both methods follow the same JWT encoding concept:
JSON serialization
Base64Url encoding
HMACSHA256 signing
Combining header, payload, and signature
The cryptographic logic is identical. The difference lies only in method design and flexibility.
Key Differences Between the Two
Type Handling
First method: Strongly tied to one model.
Second method: Generic and supports any model.
Reusability
First method: Limited scope.
Second method: Reusable across the entire project.
Scalability
First method: Requires duplication for new request types.
Second method: Easily extendable without modification.
Code Maintainability
First method: May lead to repetitive code.
Second method: Reduces redundancy and improves maintainability.
Which One Is Better?
For small applications with only one request model, the non-generic method is acceptable.
For scalable applications, enterprise systems, or projects that call multiple APIs, the generic version is better.
The generic version follows better software design principles:
DRY (Don't Repeat Yourself)
Reusability
Clean architecture
Maintainability
In most professional scenarios, the generic method is the better choice.
Important Security Consideration
Although both methods manually implement JWT creation, in production environments it is recommended to use official libraries such as:
System.IdentityModel.Tokens.Jwt
Using a standard library reduces the risk of cryptographic mistakes and ensures compliance with JWT standards.
Conclusion
Both versions of GenerateJwtToken are built on the same JWT encoding and signing concept using HS256 and HMACSHA256. The real difference lies in flexibility and reusability.
The non-generic method is suitable for single-purpose implementations.
The generic method is more scalable, reusable, and aligned with modern ASP.NET development practices.
If your application is expected to grow or handle multiple request types, the generic GenerateJwtToken method is the more professional and future-ready approach.

Join the conversation! Your thoughts help the community grow.