.NET  

How to Implement Authentication in React with .NET Core Backend?

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:

  1. The user submits login credentials from the React frontend.

  2. The ASP.NET Core Web API validates credentials.

  3. If valid, the backend generates a JWT token.

  4. The React app securely stores the token.

  5. The token is sent in the Authorization header for protected API requests.

  6. 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:

  • Microsoft.AspNetCore.Authentication.JwtBearer

  • Microsoft.IdentityModel.Tokens

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.