To create a React login system that interacts with a C# .NET API, you’ll go through a series of steps involving both the frontend (React) and the backend (.NET Core API).
This example assumes you have a .NET Core API with an endpoint for authentication and a SQL Server database to store user credentials securely.
Step 1: Setting Up the .NET Core API
- Create the User Model
First, define a model for your users in the .NET Core API.
public class ApplicationUser
{
public int Id { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
}
- Create the Authentication Controller
Then, create a controller with an action to handle login requests.
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly YourDbContext _context;
private readonly IConfiguration _configuration;
public AuthController(YourDbContext context, IConfiguration configuration)
{
_context = context;
_configuration = configuration;
}
[HttpPost("login")]
public async Task<ActionResult> Login([FromBody] LoginDto loginDto)
{
// Find the user by username
var user = await _context.ApplicationUsers
.FirstOrDefaultAsync(u => u.Username == loginDto.Username);
if (user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.PasswordHash))
{
return BadRequest("Username or password is incorrect");
}
// Generate a JWT token
var token = GenerateJwtToken(user);
return Ok(new { Token = token });
}
private string GenerateJwtToken(ApplicationUser user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["JwtConfig:Secret"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username)
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
Make sure you have BCrypt.Net
installed for password hashing and comparison, and configure your JWT settings in appsettings.json
.
- Configure JWT Authentication in Startup.cs
In Startup.cs
, add JWT authentication to the ConfigureServices
method.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Configure JWT authentication
var key = Encoding.ASCII.GetBytes(Configuration["JwtConfig:Secret"]);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
// Add other services like DbContext
// services.AddDbContext<YourDbContext>(options => ...);
}
And in the Configure
method, enable authentication middleware.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Other configurations...
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Step 2: Creating the React Frontend
- Set Up a Login Form in React
In your React application, create a simple login form.
// LoginForm.js
import React, { useState } from 'react';
import axios from 'axios';
const LoginForm = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post('http://localhost:5000/api/auth/login', { username, password });
console.log('Login success:', data);
// Save the token, handle login success (e.g., redirect, state update)
} catch (error) {
setError('Login failed');
console.error(error);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" value={username} onChange={e => setUsername(e.target.value)} placeholder="Username" />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="