I have a spring boot backend running in a separate docker container that uses a JSESSIONID cookie for authentication, which I can see in the browser. However when my frontend svelte.js container running on a different port makes a request to my backend using fetch() , it doesn’t appear as if the cookie from the browser is being attached. This is despite setting {credentials:’include’} as found on another stack overflow post here . How can I attach the cookie in my browser when I am sending a request from my frontend svelte docker container to my backend spring container?
Here is my server side svelte code (this does not run on the browser, but rather inside of the docker container)
/** @type {import('./$types').PageServerLoad} */
export async function load({ params }) {
const response = await fetch(`${getBaseUrl()}/api/draftgroups`,{credentials:'include',method:'get'});
let txt = await response.text()
if(response.headers.get("content-type") != "application/json") {
// this will determine if user is logged in. If not logged in, the user will be redirected to sign in with // google through OAuth, and thus the response type will be html rather than json for the redirection
console.log("NOT SIGNED IN")
throw redirect('302',`http://localhost:6868/login`)
}
if (!response.ok) {
throw new Error(`Error! status: ${response.status}`);
}
let responseJSON = await response.json()
return responseJSON
}
The if statement that checks the content type of the text will determine whether the user is logged in or not, as they will be prompted to sign in with google with OAuth if they are not signed in, which will give an html response. I would only expect the if condition to fire the first time the user visits the page, since they haven’t authenticated with OAuth. However I found that each subsequent time they visited the page, it appeared that the html response directing the user to sign in through google was printed, which means that the user’s authenticated cookie wasn’t attached to the request.
Does this have to do with the two different docker containers being different origins for the cookie (i.e. the spring boot container and the svelte container)? And how can I fix this
Here is my docker-compose.yml to show my infrastructure:
# Based off of https://github.com/bezkoder/docker-compose-nodejs-mongodb/tree/master/bezkoder-app
# https://www.bezkoder.com/docker-compose-nodejs-mongodb/
version: "3.8"
services:
mongodb:
image: mongo:5.0.2
restart: unless-stopped
ports:
- 27017:27017
volumes:
- db:/data/db
spring-boot:
image: bracket_backend
build:
context: ./backend
dockerfile: Dev.Dockerfile
depends_on:
- mongodb
ports:
- 6868:8080
stdin_open: true
tty: true
volumes:
- ./backend/src:/app/src
frontend-svelte:
image: bracket_frontend
build:
context: ./frontend-svelte
dockerfile: Dev.Dockerfile
ports:
- 1234:8080
stdin_open: true
tty: true
volumes:
- ./frontend-svelte/src:/app/src
depends_on:
- spring-boot
volumes:
db:
2
Answers
Thanks to John Williams for the idea! Here is full working code:
A few clarifications based on things I ran into while implementing his solution that should hopefully help others facing the same thing:
Hope this helps!
The response from svelte load function is not passing the
JSESSIONID
back to the browser. Also, thecredentials include
solution is for the scenario where the browser is communicating directly with the cookie origin. That is not the case here because you have an intervening layer (the svelte server) and two separate sets of credentials so almost everything you get from SO searches does not apply.You are stripping everything but the JSON body from the response. You need to get the end-server cookie back to the browser. This is difficult but I can provide pointers.
In order for svelte to pass back the cookie your load function needs a signature like this
load({ request, cookies })
The svelte load function must pass-through the JSESSIONID cookie received by it’s call here:
Get the cookie contents, unless it’s marked as httpOnly, with the following:
The
JSESSIONID
cookie should be here.Include it in svelte load function response:
That’s only half of the solution. The
JSESSIONID
cookie now on the oncoming request from the browser needs to be added to the request toapi/draftgroups
:Get it from the cookies argument of the load function and add to to the fetch to the server by setting a cookie header. This may not be possible with fetch so you may need to use XMLHttpRequest