JWT is a modern way of authorizing a user’s access to protected sources, accepted by a server. Server generates a special token after authenticating a user. React app sends a login credentials e.g. username and password which are checked by a server. If both of them are correct, logged in user gets a “VIP ticket” which can be used all across the same web or mobile app. Generated token can be configured to expire which will make React app to ask for another token so the user can with no interruptions continue to use the app.
In this example a server is Web API and client is, as you could already see, a React.
- We should register a JWT configuration in Program.cs file like this:
using Microsoft.AspNetCore.Authentication.JwtBearer;
//CORS POLICY
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowOrigin", policy =>
{
policy.WithOrigins("http://localhost:5173")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
var env = Environment.GetEnvironmentVariable("UserAccessToken");
if (string.IsNullOrEmpty(env))
{
throw new InvalidOperationException("Environment variable 'UserAccessToken' is not set.");
}
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://localhost:7171",
ValidAudience = "https://localhost:7171",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(env))
};
});
app.UseAuthentication();
app.UseAuthorization();
“UserAccessToken” is a 512 hash code that I’ve put in as a ENV property of this project (VS Studio 2022 Toolbar: Project tab > [Your Solution name] Properties > search for a env keyword)
- A function which will create a token and return it
private string GenerateJwtToken(string username)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
//var superKey = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
var env = Environment.GetEnvironmentVariable("UserAccessToken");
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(env));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512);
var token = new JwtSecurityToken(
issuer: "https://localhost:7171",
audience: "https://localhost:7171",
claims: claims,
expires: DateTime.Now.AddMinutes(60),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
We will call this function in our login function if the user credentials are correct.
After receiving a 200 response from our server with a generated token, our React app will send that token whenever it wants to make another API call. But, we need to be careful! If the server set the token as a cookie (see the above example), React does not need to send a token at all.
I’ll show you the difference where token is set to localStorage by a client app and when it’s stored as a cookie by a server. Both of these are visible in our Application tab of the browser but not accessible in a same way. localStorage is vulnerable because of XSS attacks so it’s not recommended at all!
- When the token is set in a localStorage, React app sends API requests like this:
const res = await axios.get("https://localhost:7171/authentication/ControllerName/anotherapireq", {
headers: {
Authorization: `Bearer ${tokenSifra}`
}
});
- When the token is set by a server:
axios.defaults.withCredentials = true;
Top comments (0)