Are web sessions supported

looking a the official guide of elm, i find no information about web sessions
https://guide.elm-lang.org/?q=session

does this mean, this is not possible with elm, (or not advised)?

background: looking at postgrest, i’m looking at what to combine postgrest with to build a webapp where users have to log in and have their own session

Hello Wibrt!

I’m not sure what you mean by web-session? Are you looking for a way to have the app remember that you’re logged in, between reloads? To have it save stuff when the app is closed?

Assuming I’ve understood your question, you can use a combination of ports and localStorage.

If I’ve misunderstood your question, please rephrase ‘web session’ or elaborate on your problem :sunny:

There is no specific support for web sessions, and I don’t even think there is a single definition of what a web session is. Is the kind of thing your are talking about something along the lines of JSESSIONID: https://javarevisited.blogspot.com/2012/08/what-is-jsessionid-in-j2ee-web.html ? This is either a cookie, or if cookies are not supported or possibly for other reasons, it can be set as a query parameter. This is an example of how it is done in a technology (JSP, Servlets) that is becoming obsolete; I don’t know much about how this concept is handled in PHP, Python, or a myriad of other older ways of building web applications where the session is kept on the server side.

A more current approach is to use a JWT token (https://jwt.io/). This is where you have an authentication server to which the users credentials are sent, and which responds with a token, which is thereafter passed in the “Authorization:” HTTP header. Nothing special about this header, its just that is the usual convention, you can pass a JWT token around in a cookie if you really want to. There are good reasons not to use cookies though, I should add.

REST discourages the use of ‘web sessions’ as API calls are stateless - in the sense that there is no need to maintain a common session between any 2 calls; they are independent of each other. So in an old-school JSP app, the web session might track which page a user is on and then a submit call needs to know that context in order to understand how to process the data they entered on that page and not some other page and that is the sort of thing you would use a ‘web session’ for. In a single page application of the kind that you would build in Elm, all of this in-flight user specific state is held in your Model. The Model is an ephemeral store in which the web session state is held.

Note that you can put a lot of session state into a JWT token - it happens but should not and is considered bad practice. Its just to hold a users digitally signed access credentials.

===

There seems to be some documentation here about role based access in PostgREST - it mentions JWT tokens too. https://postgrest.org/en/v4.3/auth.html

1 Like

That is helpfull, thank you

On the postgrest documentation i also read about jwt before and found:
http://postgrest.org/en/v6.0/auth.html?highlight=session#jwt-security
They state: ‘PostgREST uses JWT mainly for authentication and authorization purposes and encourages users to do the same. For web sessions, using cookies over HTTPS is good enough and well catered for by standard web frameworks.’

So what you are saying is: cookies and all that are not needed for creating a “personal experience”, often achieved by login into the web application and than being in that session. So elm keeps this state in local ram-memory by means of the Model.
Or to put it to the extreme: login into a bank application would not require a session in elm, and but would still be secure and personalized?

Background: i’m looking at postgrest and elm as a stack for creating a personalized secure quiz with the ability to add questions and view at historical quizresults, basically two roles (quizmaster, quizparticipant) which in turn would be several individual persons, each with a separate login and experience.

The authentication/authorization state is a shared state between the web application and server side. You could think of it as being the ‘session’ state, but I prefer not to. The reason I prefer not to is that it opens up the temptation to put things other than the auth state in there. This will bloat the size of this state, which with JWT gets passed around on every call. It is also likely to make your web APIs no longer stateless, but for their behaviour to change depending on what the current session state is, which is actually complexity that you can avoid. Of course for security related behaviour this is what you want - not authorized should return a 401 or 403. But this difference in behaviour should really only be for things related to auth, and not for things related to application functionality other than auth.

A cookie is just something that gets put in an HTTP header and sent on every request you make to the domain that issued the cookie. Cookies do have some advantages with respect to browser security, because you can make them ‘secure’ and ‘httponly’. Secure means the browser will only send them over HTTPS and never HTTP. Httponly means the browser won’t let javascript read the cookie, which helps to prevent developers doing stupid things with cookies that are intended to be kept secure, like putting them in local storage. You can put the JWT token in a secure httponly cookie, but you might not want to do this, and it is not the way it is most usually done when working with web APIs.

The reason you likely do not want to put the JWT token in a cookie, is that a cookie is only sent to the domain that issued it. I might have done my login through GitHub, and had a JWT token issued by github.com, but want to access a web API that belongs to Acme, and the browser won’t sent the github.com cookie to acme.com. For that reason the JWT token is usually passed in the HTTP header called ‘Authorization’ by convention, and we take it on faith that the developers won’t do something stupid with the access credentials like passing them over an HTTP connection, or having some rogue Javascript library siphon them off to the bad guys.

An advantage of cookies is that when you open a link in an SPA in a second browser tab, the cookie flows accross automatically to the new tab, taking your auth state with it. This means the user does not have to log in again; single sign-on. With the explicit Authorization header this does not happen and sometimes developers sneak the auth token around into the new tab via local storage, from where some malware could obtain it.

In a single page application you don’t put application state that is not auth related in a shared session between the application and the back-end. In the days before SPAs this was a common thing to do - the server would keep track of which page you were on, what you had in your shopping cart and so on. In an SPA all this ephemeral application state is just held in RAM on the client - although for a shopping cart you could conceivably have an API to which the shopping cart could be saved, so if the user drops off and comes back later it is recovered.

A risk of having more appliciation state in the client is that there is a temptation for business logic to end up there too, where its rules could be subverted. For example, when your banking app moves some money it doesn’t invoke an API that adds $100 to one account and takes $100 from another. A hacker could open the javascript console and submit an API call that adds $1000000 to your account and takes $1 from another, were that the case. Instead the API call POSTs 2 accounts and an amount of money to move, and the back-end business logic checks this is all ok before moving the money or not. I mention this as the session state in the client needs to be designed such that it does not allow business logic to be subverted.

So in a banking application you would hold the clients ‘session’ state in the Elm Model, for things related to client operation but not core banking business logic; which page the user is on, the list of transactions they are currently viewing and so on. You would also have some auth tokens in your Elm Model - maybe the JWT token, a refresh token, a nonce to prevent replay attacks etc.

===

I should add, for your case where you might authenticate directly against PostgREST to obtain a JWT token, then pass it to API calls you make against that same PostgREST instance - putting the JWT token in a cookie will be “good enough”.

If it goes in a cookie, the browser takes care of that for you, and you don’t need to put it in the Elm Model. A succesfull login call might return a 204 (with no body) that sets up the JWT token as a cookie, for example.

2 Likes

Thank you for follow-up.

As i have no experience with elm, is it correct to conclude that:

  • the recommend way of handling a personalized (ie after login in) secure webapp, is to always add the jwt token in the api calls made by elm to the postgrest instance (which is probably handled by the Model in elm) And not to use cookies. (in the assumption of always using https)
  • using cookies is another style of thinking, for approaching this problem, and not needed in this philosophy unless it is necessary for a second browser tab without login in again
  • one should not think in terms of web sessions when working with elm as compared to other frameworks that operate in this way (using cookies)

Looking at:


i was wondering if i need such a server side spa framework, or just postgrest (+nginx) and elm is enough?

It depends what you want to do. Postgrest is just a database so fine if you just want to CRUD stuff. If you need more sophisticated back-end logic, you need to write an API to support that. I don’t really know what these back-end SPA frameworks are, but Elm does not need them. You can write the API in node, Elixir, .Net, Java, Rust, whatever…

If you’re willing to write all your server side logic in stored procedures, it’s certainly possible to use Postgrest as your server side framework. If you need to send emails or call external apis you’ll also need some additional server side code. See the external notification section of the documentation.
http://postgrest.org/en/v6.0/ecosystem.html#external-notification

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.