C
C#6mo ago
prodijay

Unable to get logged in user when using React SPA

I'm trying to get the logged in user so that I can add them to my Study model instances, to then add to my database. I get the logged in user in my controller like so: var user = await _userManager.GetUserAsync(HttpContext.User); When accessing my controller via Swagger, user correctly returns the logged in user. However when accessing my controller via my React SPA (after logging in and returning a cookie), it returns null. Is there something I'm missing? For context, I am currently using cookie-based authentication with my React SPA. My fetch requests look like this: Login fetch; query is required to set useCookies to true.
export async function fetchWithQuery(endpoint, method, data, query) {
try {
const response = await fetch(
`${import.meta.env.VITE_BACKEND_DOMAIN}${endpoint}?${new URLSearchParams(
query
).toString()}`,
{
method,
body: data,
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
return response;
} catch (err) {
if (err) return err;
}
}
export async function fetchWithQuery(endpoint, method, data, query) {
try {
const response = await fetch(
`${import.meta.env.VITE_BACKEND_DOMAIN}${endpoint}?${new URLSearchParams(
query
).toString()}`,
{
method,
body: data,
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
return response;
} catch (err) {
if (err) return err;
}
}
Fetch function used to get all studies made by a user.
export async function getDataFromFetch(endpoint) {
try {
const response = await fetch(
`${import.meta.env.VITE_BACKEND_DOMAIN}${endpoint}`,
{
mode: "cors",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
return response;
} catch (err) {
if (err) return err;
}
}
export async function getDataFromFetch(endpoint) {
try {
const response = await fetch(
`${import.meta.env.VITE_BACKEND_DOMAIN}${endpoint}`,
{
mode: "cors",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
}
);
return response;
} catch (err) {
if (err) return err;
}
}
I think I've set up CORS correctly, as when I login from the React SPA a cookie is set.
c#
builder.Services.AddCors(options =>
{
options.AddPolicy(
name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins(["http://localhost:5173"])
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
c#
builder.Services.AddCors(options =>
{
options.AddPolicy(
name: MyAllowSpecificOrigins,
policy =>
{
policy.WithOrigins(["http://localhost:5173"])
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
The repo for the backend code: https://github.com/jasonHYLam/csharp-test
GitHub
GitHub - jasonHYLam/csharp-test
Contribute to jasonHYLam/csharp-test development by creating an account on GitHub.
7 Replies
prodijay
prodijayOP6mo ago
StudyController.cs (https://github.com/jasonHYLam/csharp-test/blob/main/Controllers/StudyController.cs)
c#
[ApiController]
[Route("[controller]")]
public class StudyController : ControllerBase
{
private readonly Cloudinary _cloudinary;
private readonly UserManager<User> _userManager;
private readonly ApplicationDbContext _context;

public StudyController(
ApplicationDbContext context,
UserManager<User> userManager,
Cloudinary cloudinary
)
{
_context = context;
_userManager = userManager;
_cloudinary = cloudinary;
}

\\ ...

[HttpGet("allStudies")]
public async Task<ActionResult<IEnumerable<StudyPreviewDTO>>> GetAllStudies()
{

var user = await _userManager.GetUserAsync(HttpContext.User);
Console.WriteLine("checking user");
Console.WriteLine(HttpContext.User); // returns null
c#
[ApiController]
[Route("[controller]")]
public class StudyController : ControllerBase
{
private readonly Cloudinary _cloudinary;
private readonly UserManager<User> _userManager;
private readonly ApplicationDbContext _context;

public StudyController(
ApplicationDbContext context,
UserManager<User> userManager,
Cloudinary cloudinary
)
{
_context = context;
_userManager = userManager;
_cloudinary = cloudinary;
}

\\ ...

[HttpGet("allStudies")]
public async Task<ActionResult<IEnumerable<StudyPreviewDTO>>> GetAllStudies()
{

var user = await _userManager.GetUserAsync(HttpContext.User);
Console.WriteLine("checking user");
Console.WriteLine(HttpContext.User); // returns null
Do HttpContext.User and _userManager work differently when using a SPA? Thank you!
tera
tera5mo ago
did you verify cookie is actually sent? either debug backend app or check requests in browser devtools network tab
prodijay
prodijayOP5mo ago
Yes a cookie is being sent when I login through my React SPA which fetches the backend "/login" endpoint.
No description
tera
tera5mo ago
network tab > specific request > check headers also you should take look at official auth (middleware) docs. most likely you want to add [Authorize] to all endpoints/controllers that require authenticated users. so you don't check if user is auth'd yourself in each one manually
prodijay
prodijayOP5mo ago
This is what I see for the login request's response header.
No description
prodijay
prodijayOP5mo ago
I've read through the ASPNET Core Identity docs a few times already: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-8.0&tabs=visual-studio Is there something specifically I should be looking for? I've added the useCookies and useSessionCookies query strings to the login request because of that, but that still didn't solve my issue of not getting the logged in user. Actually I notice the yellow warning symbol, let me investigate that. It's complaining about the sameSite=lax not agreeing with the cross site response. I think I managed to fix it! I think it was due to an error with my cookie; the SameSite property was set to lax, which works for when testing with Swagger, but not with React because SameSite needs to be set to none when working with cross-site responses. Specifically configuring the cookie policy such that SameSite=none and Secure=true allowed me to get the logged in user in the corresponding backend controller action. Thank you for pointing me in that direction. If you hadn't told me to check the cookie again I would have missed the detail about SameSite needing to be none. By the way did you have that in mind when you read through my problem? Did you know that there was an issue with my cookies? I seriously doubt I would have found this solution on my own, and I don't think the docs would necessarily help in this situation either.
tera
tera5mo ago
i meant request (not response) headers for the request you were having issues with (not login request as you said that was ok) yea i had some suspicion but wasn't too sure that's why i go: is the client sending what it should? is the server receiving it? then middleware troubleshooting next mozilla docs has some good pointers about cookie flags and in general might be useful to go over some of the settings might only be needed in local dev... different than e.g. when you deploy and have API and SPA behind a reverse proxy on same domain
Want results from more Discord servers?
Add your server