Authentication is a fundamental requirement in modern web applications built with React on the frontend and ASP.NET Core on the backend. A secure authentication mechanism ensures that only authorized users can access protected APIs and application resources. In enterprise-grade applications, JSON Web Token (JWT) based authentication is commonly used because it is stateless, scalable, and suitable for distributed systems.
This article explains how to implement authentication in a React application with a .NET Core backend using JWT tokens, secure API endpoints, and role-based authorization.
Architecture Overview
In a typical React and ASP.NET Core authentication flow:
The user submits login credentials from the React frontend.
The ASP.NET Core Web API validates credentials.
If valid, the backend generates a JWT token.
The React app securely stores the token.
The token is sent in the Authorization header for protected API requests.
The backend validates the token before granting access.
This stateless authentication approach improves scalability and works well for cloud-native and microservices-based systems.
Step 1: Configure Authentication in ASP.NET Core Backend
Install required NuGet packages:
Configure JWT authentication in Program.cs:
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
});
builder.Services.AddAuthorization();
Add middleware:
app.UseAuthentication();
app.UseAuthorization();
Step 2: Generate JWT Token After Login
Create a login endpoint in your controller:
[HttpPost("login")]
public IActionResult Login(LoginModel model)
{
if (model.Username == "admin" && model.Password == "password")
{
var claims = new[]
{
new Claim(ClaimTypes.Name, model.Username),
new Claim(ClaimTypes.Role, "Admin")
};
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes(60),
signingCredentials: creds);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token)
});
}
return Unauthorized();
}
Step 3: Protect API Endpoints
Use the Authorize attribute to secure endpoints:
[Authorize]
[HttpGet("secure-data")]
public IActionResult GetSecureData()
{
return Ok("This is protected data");
}
For role-based authorization:
[Authorize(Roles = "Admin")]
Step 4: Implement Login in React Frontend
Install axios for API communication:
npm install axios
Create login function:
import axios from "axios";
const login = async (username, password) => {
const response = await axios.post("https://localhost:5001/api/auth/login", {
username,
password
});
localStorage.setItem("token", response.data.token);
};
Step 5: Send Token in API Requests
Attach JWT token to request headers:
const token = localStorage.getItem("token");
axios.get("https://localhost:5001/api/auth/secure-data", {
headers: {
Authorization: `Bearer ${token}`
}
});
This allows the ASP.NET Core backend to validate the request.
Step 6: Create Protected Routes in React
Example of a simple protected route component:
import { Navigate } from "react-router-dom";
const PrivateRoute = ({ children }) => {
const token = localStorage.getItem("token");
return token ? children : <Navigate to="/login" />;
};
Use it in routing:
<Route path="/dashboard" element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
} />
Security Best Practices
Store JWT securely (consider HTTP-only cookies in production)
Use HTTPS for all API communication
Set reasonable token expiration time
Implement refresh tokens for long sessions
Validate user roles and claims on backend
Avoid storing sensitive information in JWT payload
Common Authentication Mistakes to Avoid
Not validating token lifetime
Storing tokens insecurely
Exposing secret keys in frontend
Not implementing proper CORS configuration
Skipping server-side authorization checks
Proper implementation of authentication ensures application security, protects sensitive APIs, and enables scalable user management in React and ASP.NET Core applications.
Summary
Implementing authentication in a React application with a .NET Core backend typically involves configuring JWT-based authentication in ASP.NET Core, generating secure tokens after validating user credentials, protecting API endpoints with authorization attributes, and sending the token from the React frontend in the Authorization header for protected requests. By following secure coding practices such as using HTTPS, validating claims, implementing role-based authorization, and handling token storage carefully, developers can build scalable, secure, and production-ready full-stack applications using React and ASP.NET Core.