i-n-g-m-a-r
Does anyone know what is the point of:
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
when mount/3 in the LiveView receives a session containing another "_csrf_token" ?
And why are those tokens not the same, I am confused.
inspect Plug.Conn.get_session(assigns.conn, "_csrf_token")
>>> "Xebn1wL063P33DzixqzBBT6I"
document.querySelector("meta[name='csrf-token']").getAttribute("content")
>>> "EyMMBGcPHAMEez8BBCsKEA4HNjsNZncfKFnjVxP32Ho27opyvvLyO2AV"
def mount(%{} = _params, %{"_csrf_token" => csrf_token}, socket) do
>>> "Xebn1wL063P33DzixqzBBT6I"
socket |> Phoenix.LiveView.get_connect_params |> Map.get("_csrf_token")
>>> "EyMMBGcPHAMEez8BBCsKEA4HNjsNZncfKFnjVxP32Ho27opyvvLyO2AV"
What’s going on here?
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
Hey guys,
I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly
Do you guys have any suggestions what is the best prac...
New
Hello!
Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app.
I creat...
New
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Hello,
I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter).
The diffic...
New
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
I think I’ve found a small improvement I could contribute to <%= web_namespace %>.CoreComponents (installer/templates/phx_web/compo...
New
Other Trending Topics
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
There are three potential reasons for members of this forum to have a look at https://vutuv.de
You are tired or annoyed of LinkedIn.
Yo...
New
Aludel - LLM Evaluation Workbench
Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New
Latest Phoenix Threads
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #phoenix_html
- #elixirconf-us
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
i-n-g-m-a-r
Related to:
Exadra37
Anything in the session cannot be accessed by javascript in the browser, because the session cookie as the
SecureandHttpOnlyflags set on them, and you can read more about it here:So this means that in order to protect the fist call from LiveView to the server we need to give it another CSRF token, otherwise you would be leaking the session CSRF token to the html document, thus compromising the security of the session cookie, because any javascript on your page would be able to read it, just as the LiveView javascript is able to do.
i-n-g-m-a-r
It makes sense that you don’t want any javascript to be able to access session (or any other) cookies.
The csrf token that is sent to the liveview is copied from a meta tag that is rendered in the html source code just like a token would be rendered in a hidden form field.
I guess that meta tag was generated from session data right?
I would think that I would be able to validate the csrf token I get by calling
Phoenix.LiveView.get_connect_params/1against the one I get from the session argument inmount/3.That way I could be sure the socket connection is safe just like I would know a post request came from my server.
Is that not the purpose of the csrf token?
Exadra37
The purpose of CSRF tokens are to give you some confidence that the request comes indeed from your browser app, but once they are used from an html tag, they are indeed a weak assurance for that purpose, but are better then nothing.
Anyway the ones used by Phoenix can be improved by using their encrypted tokens feature, and then checking in the backend that the token is correctly signed and not older then x amount of seconds, lets say 10 seconds.
With this approach you have more confidence that the request is indeed from your browser app, but 10 seconds is still plenty of time for it to be stolen and reused from malicious javascript code in your web page.
Now you can enhance the CSRF token even more by treating it as a
nonce, aka it can be only used once, but this requires some logic in your backend to keep an:etstable with all CSRF tokens not expired, that you will check for in each request to see if it was already used, and if so you deny the request, despite the encrypted CSRF token be correctly signed and have not expired.Once more this not guarantees you that the malicious javascript in your page was not the first one to use the encrypted CSRF token to make a request to your backend.
If you do all this then you are in a much safer place then the current standard approach, but remember that in the end of the day you cannot find a bullet proof solution, just one that is hard to bypass.
i-n-g-m-a-r
Thank you for your effort to help clearing things up.
So lets say that the purpose of CSRF tokens is to give me some confidence that the request comes from my browser app.
That’s exactly how I understand this technique so in this respect we are on the same page.
But what kind of request are we talking about?
a) mounting the liveview
b) liveview → render form → post stuff → got request
I am assuming that I should use this token:
get_connect_params |> Map.get("_csrf_token")to validatemount/3(option a), something along the lines of:Suppose the actual purpose is option b then I am misunderstanding all of this completely.
Probably someone can think of some obscure use case for option b.
To me that would be an edge case, so I would guess the purpose is option a.
so… how do I get rid of
:bad_news?I did (finally) find a relation between the two csrf tokens:
So I can validate mounting the liveview:
However, if this is correct, why is it not in the manual?
So probably it’s not correct.
And if it’s not correct, then what is the purpose of the csrf token?
Exadra37
The option a) refers to the CSRF token you mentioned here:
and my reply was base on that scope.
Now my suggested improvements may also be added to CSRF tokens for forms, but obviously there you cannot use a very short expire time for it.
I am still new to Elixir and Phoenix and just 1 month ago I decided to build a real project with it, thus I am still in the exploratory phase of all its security mechanisms, thus I welcome your findings regarding the CSRF token and I will explore them too.
To bear in mind that Phoenix Phoenix will check the Phoenix tokens for your in the incoming requests, but I have not explored the internals of it to see how it works and see if we have room for hardening it.
Well web-sockets can be attacked as anything else exposed to the internet, and if your site as some value for attackers you can bet that they will try to hack it, no matter if over web-sockets or regular http requests.
You can read more about testing web-sockets for security in this OWASP guide, that includes some examples with the OWASP Zed Attack Proxy.
i-n-g-m-a-r
You will not regret your decision to start a real project using Elixir and Phoenix
I am not new to Elixir and a huge fan, but when it comes to LiveView I’m also in the exploratory phase.
Unlike many other Elixir projects Phoenix has a lot of magic goblins walking around.
When I see stuff “pop up” (like
%{"_csrf_token" => _} = session) I want to know all about it.Sometimes it’s not easy to follow the money.
I think Phoenix and LiveView are works of genius.
Some things are a little unfortunate in my opinion, like for example non-specific variable names (“params”) and aliases imported by macros.
Using Phoenix seems simple, but there’s lots of stuff you need to know to make sense of the docs.
Anyway, Phoenix is absolutely awesome, so it’s worth it.
i-n-g-m-a-r
And if you haven’t already, please setup ci/cd and create tests for every public function.
Maybe it’s a lot of overhead but you will be very happy you did once your project becomes more complex.
adamu
I’m also curious about this. Not sure if I’ve completely understood, either.
My understanding that by default Phoenix does this:
get_csrf_token()call inroot.html.heexcauses the server to generate a CSRF token, which it stores in the process dictionary.Plug.CSRFProtectionwill also put the CSRF token in the session.The result is that the HTML response contains a session cookie with the CSRF token (the first time), and also in the response body (every time), so it can be read by JS.
For LiveView, I’m also unsure. It looks like most of the components handle generating CSRF tokens themselves. The docs say:
But the CSRF token inside the
sessionthemountcall receives is not the one from the session cookie, it’s one generated by the live viewadamu
I had some time to look into this more.
It turns out this was all a misunderstanding, caused by getting confused by how Plug.CSRFProtection handles CSRF tokens internally.
How Plug.CSRFProtection handles CSRF tokens internally
Plug.CSRFProtectionhas an internal concept of “masked” (long) and “unmasked” (short) CSRF token. The one you get when you callget_csrf_token/0is the masked one, but the one it stores in the session (which you see if manually getting the session or looking at themountcall, or inspecting the cookie) is the unmasked one. However, these are the same and you can check that they match as ingmar already did above:I guess the masking is something to do with preventing timing attacks.
LiveView Components add the CSRF token automatically
formwill automatically add the CSRF token (which it gets from the process dictionary, which is populated from the session cookie, as described in the previous post) to the form if it contains anactionparameter. A form generated bymix phx.gen.livedoesn’t containactionby default, as it’s assumed the form will be submitted via LiveView, but if you add it, the CSRF token will be added. For exampleThis form will include the masked/long CSRF token in a
_csrf_tokenfield by default, due to the presence of theactionparam.Additionally, while looking into this, I also found this post which confused me, because what it described is all unnecessary - maybe it was an issue on older versions:
Now the issue described in that article also works out of the box with a link like this:
This generates a link with the relevant CSRF token included automatically.
To go full circle, the only thing I’m not sure about, is what the purpose of this is, considering components make their own calls to
Plug.CSRFProtectionto get the csrf token, so there doesn’t seem to be a need to pass it back from the browser: