RO EN
Authentication and Authorization in React + .NET Core: Identity + JWT + Route Protection
Doru Bulubasa
18 June 2025

In this article, we continue developing the blog-type application, focusing on implementing authentication and authorization. We will use:

  • ASP.NET Core Identity for user management

  • JWT (JSON Web Tokens) for stateless authentication

  • React Context + localStorage to maintain authentication on the frontend

  • Protecting routes and API calls based on authentication

🧩 Why JWT? Why stateless?

JWT-based authentication is stateless, which means the server does not need to store sessions. The signed token is sufficient to prove the user's identity. Advantages:

  • Increased scalability

  • Ideal for SPA applications (React, Angular)

  • Easy to extend with role/permission-based authorization


1️⃣ Identity + JWT in .NET Core

✅ Package installation

Add to the WebAPI project:

dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

✅ Configuration in Program.cs

builder.Services.AddIdentity<ApplicationUser, IdentityRole>()

    .AddEntityFrameworkStores<AppDbContext>()

    .AddDefaultTokenProviders();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)

    .AddJwtBearer(options =>

    {

        options.TokenValidationParameters = new TokenValidationParameters

        {

            ValidateIssuer = true,

            ValidateAudience = true,

            ValidateLifetime = true,

            ValidateIssuerSigningKey = true,

            ValidIssuer = "ludo.blog",

            ValidAudience = "ludo.blog",

            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your_secret_key_123456"))

        };

    });

🔐 Make sure the JWT secret is saved in appsettings.json or in UserSecrets.


✅ Token generation

private string GenerateJwtToken(ApplicationUser user)

{

    var claims = new[]

    {

        new Claim(JwtRegisteredClaimNames.Sub, user.Email),

        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),

        new Claim(ClaimTypes.NameIdentifier, user.Id)

    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfig.Secret));

    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(

        issuer: _jwtConfig.Issuer,

        audience: _jwtConfig.Audience,

        claims: claims,

        expires: DateTime.Now.AddHours(2),

        signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);

}


2️⃣ Login in React + Token storage

✅ API call from React

const login = async (email: string, password: string) => {

  try {

    const res = await axios.post("/api/auth/login", { email, password });

    localStorage.setItem("token", res.data.token);

    setUser(jwtDecode(res.data.token)); // decode token & extract user info

  } catch (err) {

    setError("Login failed!");

  }

};

✅ AuthContext

export const AuthContext = createContext<AuthState>(null);

export const AuthProvider = ({ children }) => {

  const [user, setUser] = useState(null);

  useEffect(() => {

    const token = localStorage.getItem("token");

    if (token) setUser(jwtDecode(token));

  }, []);

  return (

    <AuthContext.Provider value={{ user, login, logout }}>

      {children}

    </AuthContext.Provider>

  );

};


3️⃣ Protecting routes in React

✅ PrivateRoute

const PrivateRoute = ({ children }) => {

  const { user } = useAuth();

  return user ? children : <Navigate to="/login" />;

};

✅ Usage in App.tsx

<Routes>

  <Route path="/posts" element={<PrivateRoute><UserPosts /></PrivateRoute>} />

  <Route path="/login" element={<LoginPage />} />

</Routes>


4️⃣ Displaying personal posts

✅ Backend: Secured endpoint

[Authorize]

[HttpGet("me")]

public async Task<IActionResult> GetMyPosts()

{

    var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);

    var posts = await _postService.GetPostsByUser(userId);

    return Ok(posts);

}

✅ Frontend: Call with token

const token = localStorage.getItem("token");

const res = await axios.get("/api/posts/me", {

  headers: { Authorization: `Bearer ${token}` }

});


✅ Conclusion

We have implemented a complete authentication and authorization flow for our blog application. The JWT token allows secure communication between frontend and