How to get svelte to save a JWT cookie
This has been plaguing me all day, so I’m saving some instructions here for future reference.
For my project i’m creating a Svelte front end and a Go backend. I’m using JWT for authentication and I want to store the JWT in a cookie. The flow should go like this:
- User logs in by sending a POST request to my sign in endpoint.
- The backend checks the credentials and if they’re valid, it creates a JWT and sends it back in a cookie
as
Set-Cookie
. - The front end receives the cookie and stores it in the browser.
- The front end sends the JWT cookie with every request to the backend.
I’ve been trying to get the cookie to save in the browser for ages and I finally figured it out.
Debugging steps:
The requests made by the client should have credentials: 'include',
set.
You’ll need to make sure you’ve got credentials: 'include',
set on your requests.
This will allow the browser to send the cookie with every request.
NOTE: You also need to send this with the request that sets the cookie.
1
2
3
4
5
6
7
8
9
10
11
const res = await fetch(API_ENDPOINTS.LOGIN, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email.value,
password: password.value
})
});
You need to set the CORS headers on the backend.
This is pretty easy in golang with gin. NOTE: You can’t use wildcards for a request that contains credentials.
r := gin.Default()
config := cors.DefaultConfig()
// config.AllowOrigins = []string{"http://localhost:5000"}
if APIHandler.Config.LocalDev {
config.AllowOrigins = APIHandler.Config.TestConfig.CORSOrigins
} else {
config.AllowOrigins = APIHandler.Config.CORSOrigins
}
config.AllowCredentials = true
r.Use(cors.New(config))
You need to make sure HTTPS is set to false when you’re doing local dev.
In short, locally developing your frontend with a backend deployed and using HTTPS is a massive pain. I’d recommend running both your F/E and B/E locally and setting HTTPS to false on the backend for development.
c.SetCookie(
"bearer",
tokenString,
h.Config.TokenExpirationTimeMinutes*60,
"/", // This is important, sets the cookie for the whole domain.
h.Config.SiteDomain, // This is important too, your frontend and backend need to be on the same domain.
h.Config.UseSSL, // Set this to false for local dev.
true, // This decides whether your JS can access the cookie. Bad for security if false, se to true.
)