Reputation: 8471
I created the project using visual studio 2022 and chose aspnet core 6 web api template. I'm trying to set a cookie in the browser but it seems I am missing something as it is not setting anything under Network > Application > Cookies
My frontend is a react app. No extra library just yet. It's the default project after running the npx create-react-app <project-name>
command.
I can call the /weatherforecast
endpoint no problem. But for some reason, it is not setting the cookie.
frontend call
const getData = async () => {
await axios.get("/weatherforecast");
};
WeatherForecastController.cs
public IActionResult Get()
{
Response.Cookies.Append("myjwt", "ABCDE", new CookieOptions
{
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.None
});
return Ok();
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
const string AllowAllHeadersPolicy = "AllowAllPolicy";
builder.Services.AddCors(options =>
{
options.AddPolicy(AllowAllHeadersPolicy,
builder =>
{
builder
.WithOrigins(new[] { "http://localhost:3000" })
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.UseCors(AllowAllHeadersPolicy);
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
The end goal of what I am trying to do is to store the refresh token in the cookie with the HttpOnly=true
What I tried:
Upvotes: 9
Views: 24548
Reputation: 8471
I just solved my problem. I thought you only need to add withCredentials: true
(using axios btw) whenever you want to send the cookie back to the server. Turns out, you need to add that property if you want to get the cookie from the server as well. Now the browser is storing the cookie in Application > Cookies. Appreciate all the help <3
Upvotes: 1
Reputation: 1619
You can set the cookie in your app.Use section. It can look something like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) =>
{
var cookieOpt = new CookieOptions()
{
Path = "/",
Expires = DateTimeOffset.UtcNow.AddDays(1),
IsEssential = true,
HttpOnly = false,
Secure = false,
};
context.Response.Cookies.Append("MyCookieId", "SomeCookieID", cookieOpt);
await next();
});
}
This will apply the cookie to all calls being made. From there you can request that cookie in the response headers and read from it whatever you need.
You seem to be ok with setting the cookie at the beginning and not after a call is made. If you need to do that comment and I can show you that way too. Its simply modifying the response message back to include a cookie within the response header.
Upvotes: 2
Reputation: 878
Below view is what you technically trying to do:
You can do that in multiple ways
Option 1: Build-in middleware
services.AddSession(options =>
{
options.Cookie.Name = ".AdventureWorks.Session";
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.IsEssential = true;
});
and then you have to instruct to use middleware (this is something that you seems to be missing)
app.UseSession();
Option 2: Manually instruct your API that cookie need to be added:
public HttpResponseMessage Get()
{
var resp = new HttpResponseMessage();
var cookie = new CookieHeaderValue("session-id", "12345");
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
resp.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return resp;
}
Microsoft provides example with MessageHandler (for ASP.Net) and DelegatingHandler (for API inbound or outbound connections in Core - can be attached to HttpClientFactory Implement DelegatingHandler in ASP.NET Core 5.0 Web API?). You also can use normal MiddleWare to intersect and update reguest/response data (example is here ASP .NET Core webapi set cookie in middleware)
Pseudo-code example with DelegatingHandler
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
public class SessionIdHandler : DelegatingHandler
{
public static string SessionIdToken = "session-id";
async protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
string sessionId;
// Try to get the session ID from the request; otherwise create a new ID.
var cookie = request.Headers.GetCookies(SessionIdToken).FirstOrDefault();
if (cookie == null)
{
sessionId = Guid.NewGuid().ToString();
}
else
{
sessionId = cookie[SessionIdToken].Value;
try
{
Guid guid = Guid.Parse(sessionId);
}
catch (FormatException)
{
// Bad session ID. Create a new one.
sessionId = Guid.NewGuid().ToString();
}
}
// Store the session ID in the request property bag.
request.Properties[SessionIdToken] = sessionId;
// Continue processing the HTTP request.
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
// Set the session ID as a cookie in the response message.
response.Headers.AddCookies(new CookieHeaderValue[] {
new CookieHeaderValue(SessionIdToken, sessionId)
});
return response;
}
}
Middleware msdn https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0
Upvotes: 10