Problem Summary
I am currently enhancing my skills in ASP.NET Core Web API by working on implementing a Refresh/Access token-based authentication system with a ReactJS application. While testing with tools like ThunderAPI and Insomnia, everything functions correctly. However, when I attempt to use the same process in my React app, it doesn’t behave as expected.
Login Endpoints Implementation
Here is my frontend code for logging in:
export const logIn = async (credentials) => {
const result = await fetch(`${API_BASE_URL}/api/auth/signin`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials)
});
if (!result.ok) throw new Error('Login failed.');
const data = await result.json();
localStorage.setItem('token', data.accessToken);
return data;
};
And the server-side implementation looks like this:
[HttpPost]
[Route("signin")]
public async Task<IActionResult> SignIn([FromBody] LoginData loginRequest)
{
var user = await _userManager.FindByNameAsync(loginRequest.Username);
if (user == null || !await _userManager.CheckPasswordAsync(user, loginRequest.Password))
return BadRequest("Invalid credentials.");
var refreshToken = _tokenService.GenerateRefreshToken(user);
Response.Cookies.Append("refresh_token", refreshToken, new CookieOptions()
{
HttpOnly = true,
Secure = false,
Expires = DateTime.UtcNow.AddDays(7)
});
var accessToken = _tokenService.GenerateAccessToken(user);
return Ok(new { AccessToken = accessToken });
}
Current Issue
The React app successfully hits the endpoint, receives the access token, but the HttpOnly refresh token isn’t being sent back to the browser. I suspect this could be linked to my CORS settings, or how I’m processing the cookies and bearer tokens.
CORS Configuration
Here’s how I’ve set up my CORS:
public static void ConfigureCors(this IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("MyCorsPolicy", builder =>
{
builder.WithOrigins("http://localhost:5173")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
}
Implementation Steps
builder.Services.ConfigureCors();
app.UseCors("MyCorsPolicy");
JWT Authentication Configuration
In my Program.cs
, I have:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = builder.Configuration["JWT:Issuer"],
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"])),
ValidateLifetime = true,
};
});
Conclusion
The intention behind this setup was to enhance security by utilizing both the access and refresh tokens for authentication. I believe my understanding of HttpOnly cookies and ReactJS may be lacking in this area. Any suggestions, insights, or resources to help resolve this problem would be greatly appreciated. Thank you!