Cannot read local stored cookie on http api requests after redirect

Hi, I’m trying to build a conversion tracking app with Anvil using local browser cookies. The logic is simple:

  1. The app generates a campaign_url and has a destination url where to redirect traffic. When the campaign_url is called, the app stores a local cookie with a generated uuid on the browser and the stores the same on the database. Then it redirects to the destination site.

  2. When the user reachs the thank you page on the destination site, a request is fired through an iframe which tells the app a conversion was made. The app checks the browser for the cookie it stored before, and if it finds a cookie, then a conversion is saved on the database

What is working:

The app stores the cookie on the browser and on the database
Redirects to the landing page

What is not working:

When the request on the iframe tries to read the cookie value, the value is empty. When I check on the browser, the cookie exists and is sent on the request, but I don’t know why the app cannot access it

Browser showing stored cookie on thank you page:

Cookie beign sent by the http request on thank you page to the app

image

Code used to read cookie and write cookie:

image

As you can see on the image, when I write the cookie, I’m re-reading the cookie it and the information is there. But when I try to read it on the conversion api endpoint I get “null”

image

I’m new to Anvil so maybe I’m missing something here. I would appreciate any help.

By the way, If I remove the redirection on step one, and paste the conversion endpoint to the same browser window, everything works fine!

Adding to my previous tests, I did a manual test using Postman (which stores cookies on the cilent side) instead of a Browser and it worked! There must be something going on with the redirection.

After several unsuccessful tests, I tried to simplify the code to the minimum to see if anyone can help me with this issue:

@anvil.server.http_endpoint("/tr2/")
def record_cookie():
  anvil.server.cookies.local.set(3, session_id='1234')  
  response = anvil.server.HttpResponse(302, "Redirecting...")
  response.headers['Location'] = "https://www...."

  return response

@anvil.server.http_endpoint("/cv/")
def read_cookie(**params):
  session_id = anvil.server.cookies.local.get("session_id", "null")
  return session_id

On the landing page, the code that fires the request is implemented as an iframe

The returned session_id is always null

I keep testing, and I see that shared cookies have the same behaviour in this case.

I would appreciate any comment or help regarding this issue.

Thanks!

I don’t understand why you are trying to use cookies. Perhaps you are trying to use Anvil as you would use another framework?

I remember trying long time ago, but if I remember I gave up because Anvil’s cookies are encrypted and can only be used on the server side.

When I need to store something about an user on the server side, I store it on a data table.
When I need to store something on the client side, I use local_storage from Anvil Extras.

HI Stefano, thank you for your reply. I’m gonna read the docs for local_storage but I think that this is only accesible on the client side. I need to be able to retrieve the information from the browser on the server side.

The steps that the app should follow are:

  1. The user navigates to a certain landing page. The app stores a cookie with the session_id on the clients browser and on the db
  2. Sometime before the cookie expires, lets say 48hs later, the user comes back to the site and I need to check if the user was the same as on step1, so I read the cookie and check if the session_id is the same. If its the same, I record the situation on the db , if its a new user, I’m back in step 1

Hope this helps to understand why I need a cookie. If there is another way to do it, I’ll be happy to test.

Thanks again you for your help

Hi @sergio2,

Looks like this is Anvil’s built-in cross-site request protection kicking in!

The pattern you’re using – a request initiated by a separate site, which performs an action based on the cookies set by a previous visit to the app – is indistinguishable from a common malicious technique called Cross-Site Request Forgery (CSRF or XSRF). This is where an attacker gets someone who is already logged into your app to visit their malicious site, which triggers malicious HTTP requests to your app that perform actions in the user’s account.

To protect against this, Anvil runs “cross-origin” requests – that is, requests triggered by a site that isn’t your app – in an isolated session by default, without access to session state, login status or cookies. This makes Anvil safe by default, even for developers who have never thought of this issue before!

In this case, you do want to process these requests in the same session, with the same cookies, so you can take the safety catch off and use cross_site_session=True in your http_endpoint decorator (see that link for details).

2 Likes

Thank you @meredydd for your answer!

Indeed, when I turned on the cross_site_session it started working fine. Didn´t know about this feature in Anvil!