feedback on Supabase auth sample app for Pyramid

137 views
Skip to first unread message

Scott Lawton

unread,
Nov 27, 2023, 5:17:19 PM11/27/23
to pylons-discuss
I've used Pyramid for various small projects over the years. Thanks much to the devs and community for such a great framework.

For a future project, would like to support login via Google, Github, etc. Supabase (a Postgres-based platform) looks like a solid approach -- but I'm not sure the best way to integrate with Pyramid.

Here's our attempt via a simple example app: https://github.com/MakeDeeply/pyramid_supabase_auth_dev ... MIT License so open to all.

Would be great to get some feedback from the Pyramid community. (Also from Supabase folks; I reached out to them elsewhere.)

Cheers,

Scott
X/Twitter: @MakeDeeply

tonthon

unread,
Nov 28, 2023, 4:47:54 AM11/28/23
to pylons-...@googlegroups.com
I haven't red all the code, but is there a reason you store the access/refresh tokens in a cookie instead of inside the session ?

--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/d0cdd7e7-93cf-436c-8a36-894f48c7b8c2n%40googlegroups.com.


Scott Lawton

unread,
Nov 28, 2023, 6:40:51 AM11/28/23
to pylons-discuss
Thanks for taking a look. Good question. When we first wrote the code, the Supabase Python API didn't have a redirect param so a bit of JavaScript was required to parse info out of #local_params -- so maybe we only used cookies to 'share' that info back to the server. But with their current API, maybe there's no longer any benefit. I'll check with one of the contractors who worked on it.

There's also this bit from Supabase for their Flask version (which didn't exist as an example when we started): "Here we're getting the code query parameter from the request object, if this is available we then exchange the code for a session so that the user will be signed in. Under the hood the supabase python library will handle storing this session (JWT) into a cookie and sign the user in."

I've mostly treated Pyramid sessions & JWT & cookies as black boxes without having to fully understand the tradeoffs ... which is why I'm looking for community feedback!  :-)

Scott

Scott Lawton

unread,
Nov 28, 2023, 2:12:33 PM11/28/23
to pylons-discuss
Some followup:
- https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/sessions.html has a big section in red: 'By default the SignedCookieSessionFactory() implementation contains the following security concerns:

... which seems to argue against session, but maybe doesn't apply to access/refresh tokens? And/or maybe setting the cookie like we do isn't any better?

We also tried to follow https://docs.pylonsproject.org/projects/pyramid/en/latest/whatsnew-2.0.html#upgrading-auth-20 ... but not sure we did so correctly. That's what we're looking for feedback!

Scott

Jonathan Vanasco

unread,
Nov 29, 2023, 6:02:35 PM11/29/23
to pylons-discuss
First off, the refresh/access tokens are sensitive credentials that must be protected from exposure to third parties.

I would personally consider this implementation as a low security risk when it comes to the two tokens, as they'd be left as plaintext in the browser's settings/profile whether the connection was on http or HTTPS.

This would be completely insecure and a high security risk if the connection/server was http, as the data would be transferred in plaintext and is fully susceptible to MITM attacks or network packet sniffing.

To be clear, IMHO: storing this stuff in a cookie is not an issue.  Storing this stuff in an **unencrypted** cookie without TLS is an issue.

For this type of data, at a minimum, calls to request.response.set_cookie should contain `httponly=True` and `secure=True`; the app should also be under https only. If I understand how your system uses these credentials correctly, `samesite=strict` should also be added.

There are two concepts when it comes to Cookie Data.  
* signing
* encryption

Signing the cookie just creates a digest of the payload with a site secret.  It is used to prove the data originated from the site.  

Encrypting the cookie makes it unreadable without the key.

Pyramid's sessions, by default, are the following: (https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/sessions.html)
* unencrypted, but signed/authenticated
* fully contained in the cookie (Client-Side Sessions)

IMHO, putting this data in a standard Pyramid client-side session wouldn't fix the security concerns either - even though the information is signed, which authenticates it originated from your app, it could be extracted from the user's browser and would be susceptible to mitm attacks if the connection were not https.  There are also the concerns with the cookie not being locked down with the kwargs mentioned above.

If I were to be stashing this information, I would consider the following two options:

1- Store in an Encrypted cookie.  I am not sure if there are any open source projects on PyPi that automate this within Pyramid, but there are many that will handle the generic encryption/decryption.  Alternatively, you can use middleware to encrypt/decrypt the cookie data.
2- Store in a Server-Side session.  There are many projects in the pyramid ecosystem for this.  If this method is used, you need to ensure the cookies used for authentication/authorization/login-status are either encrypted or are HTTPS only.  If they are not, you should require re-authentication for the user to access this information.


Scott Lawton

unread,
Nov 30, 2023, 7:14:35 AM11/30/23
to pylons-discuss
Thanks so much!

> For this type of data, at a minimum, calls to request.response.set_cookie should contain `httponly=True` and `secure=True`; the app should also be under https only. If I understand how your system uses these credentials correctly, `samesite=strict` should also be added.

Makes sense. (Yes, we deploy sites behind https.)


> Store in a Server-Side session.  There are many projects in the pyramid ecosystem for this.

Any suggestions for 1-3 simple examples? Ideally with only Python dependencies -- I'd rather not add Redis, MongoDB etc. since we already have Supabase.

Scott

tonthon

unread,
Nov 30, 2023, 8:13:25 AM11/30/23
to pylons-...@googlegroups.com
pyramid_beaker is as far I know only python based (stores sessions on disk)


We use extensively for years now without any trouble.
--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.

Mike Orr

unread,
Nov 30, 2023, 11:31:46 AM11/30/23
to pylons-...@googlegroups.com
A second for 'pyramid_beaker'. It doesn't get much attention nowadays
but Beaker still works and is getting updates. It has backends to
store sessions in files, Redis, SQLAlchemy, cookie-only, and others. I
have two production applications on it. One because one developer's
workstation doesn't have Redis, so she uses file-based sessions. The
other because it's both a traditional website and is also bundled into
Windows/Mac desktop applications (using Electron with an embedded
browser) so Redis isn't available there. I think the desktop mode uses
memory-based sessions because it's a single thread talking to it.

One thing to keep in mind, Beaker doesn't clean up abandoned session
files so they accumulate until manually purged.
'pyramid_session_redis' and 'pyramid_redis_sessions' have an option to
use Redis's auto-expire feature to automatically delete sessions that
haven't been updated for a while.
> To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/006d2a5a-4b6e-4284-affe-5a0530087ea9%40gmail.com.



--
Mike Orr <slugg...@gmail.com>

tonthon

unread,
Nov 30, 2023, 11:40:34 AM11/30/23
to pylons-...@googlegroups.com
The following line can be added to a crontask to clean up old sessions :

find /<path_to>/beaker/sessions/ -type f -mtime +3 -print -exec rm {} \; > /dev/null 2>&1

Scott Lawton

unread,
Nov 30, 2023, 1:04:12 PM11/30/23
to pylons-discuss
Thanks for the link and the 'second' that it's still a practical solution; I was a bit hesitant given that it's 10 years old: 0.8 (2013-06-28).

Looks like there are enough docs available for us to proceed. Still, if anyone knows of a sample app that includes that + oauth, would be great to see. (I learn more from examples than from docs.)

Scott

Jonathan Vanasco

unread,
Nov 30, 2023, 2:37:14 PM11/30/23
to pylons-discuss
> Any suggestions for 1-3 simple examples? Ideally with only Python dependencies -- I'd rather not add Redis, MongoDB etc. since we already have Supabase.

Aside from beaker, no.  I maintain `pyramid_session_redis` and - as long as you disable redis administration - it is relatively insignificant on a server that has available memory.  Unless you have very high traffic and require more memory, running Redis with a 100MB limit is pretty insignificant.  

If you do use pyramid_beaker, i strongly suggest having it save to a dedicated disk partition so that it does not overrun your server, which can lead to downtime.

While there are memory backed options, there are two drawbacks for this:
* sessions do not persist across server or application restarts
* you can run into complications with forking servers

> Looks like there are enough docs available for us to proceed. Still, if anyone knows of a sample app that includes that + oauth, would be great to see. (I learn more from examples than from docs.)

I also main pyramid_oauthlib_lowlevel


The test suites have fully functional pyramid applications for oauth 1 and oauth 2 flows, each of which mimic how a consumer server and provider server will work with one another.




Delta Regeer

unread,
Nov 30, 2023, 2:48:03 PM11/30/23
to pylons-...@googlegroups.com
Use https://docs.pylonsproject.org/projects/pyramid-nacl-session/en/latest/usage.html

It encrypts the session the is stored in the cookie with NACL. No longer is the content if the cookie something that an attacker can read/do anything with.


--
You received this message because you are subscribed to the Google Groups "pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discus...@googlegroups.com.

Jonathan Vanasco

unread,
Nov 30, 2023, 5:26:55 PM11/30/23
to pylons-discuss
Wow. This looks great. I wish I knew about it sooner.

Digging into the code, there was a PR to split things out and support JSON serialization – however there are no unit tests covering this or docs for it.  @Delta do you know of any public examples of this usage?  If so I'd be happy to play around with it and generate a PR for unit tests.

I often manually generate and read encrypted cookies, which can be a chore.  This would be incredibly useful to me in a few projects.

Delta Regeer

unread,
Dec 1, 2023, 2:43:20 PM12/1/23
to pylons-...@googlegroups.com
Nope. I know it was created for a client of Agendaless, and I know it exists. I have not used it because I don’t store secret data in cookies, so using the signed factory one is easier and didn’t require additional crypto libraries to be added to my stack.

Jonathan Vanasco

unread,
Dec 4, 2023, 1:24:18 PM12/4/23
to pylons-discuss
Fair enough!  I wrote `pyramid_session_multi` to let me map multiple ISession Session libraries onto a request.  On our largest project, we run a secondary server side session and mix of encrypted cookies to handle some "secret" data.  This library would let me drop one of the server side sessions and replace the encrypted cookie with something more automated.  I am so excited and thankful you shared it!
Reply all
Reply to author
Forward
0 new messages