Error writing variables to session

66 views
Skip to first unread message

Alfonso Serra

unread,
Aug 5, 2025, 1:19:50 PMAug 5
to py4web
I have several issues with the session object and auth.

First is that trying to save a session variable called 'user' crashes the controller
@action("index")
@action.uses("index.html", session, auth)
def index():
    session["user"] = 1
    return locals()

Traceback (most recent call last):
  File "C:\Users\Stark\Desktop\qadash\py4web\core.py", line 1059, in wrapper
    ret = func(*func_args, **func_kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Stark\Desktop\qadash\py4web\core.py", line 1044, in wrapper
    raise exception
  File "C:\Users\Stark\Desktop\qadash\py4web\core.py", line 1037, in wrapper
    call_f(fixture.on_success, context)
  File "C:\Users\Stark\Desktop\qadash\py4web\core.py", line 1002, in call_f
    return f(context)
           ^^^^^^^^^^
  File "C:\Users\Stark\Desktop\qadash\py4web\utils\auth.py", line 378, in on_success
    context["template_inject"]["user"] = self.get_user()
                                         ^^^^^^^^^^^^^^^
  File "C:\Users\Stark\Desktop\qadash\py4web\utils\auth.py", line 536, in get_user
    if not self.session.is_valid() or not self.user_id:
                                          ^^^^^^^^^^^^
  File "C:\Users\Stark\Desktop\qadash\py4web\utils\auth.py", line 565, in user_id
    return user.get("id", None)
           ^^^^^^^^
AttributeError: 'int' object has no attribute 'get'

But also if i try to log a user programatically when visiting index.html, this user is not added to the session so other urls are not aware that a user has been logged.

This fails for many reasons:
session['user'] = 1 throws the error above because we are using the key "user"

user, error = auth.login(email, password)
session['user"] = user Fails because Row is not JSON serializable.

So py4web does not add the user to the session when its logged in programatically but also throws an error when we manually try to add it to the session object.

How can i have a user session across different views? Shall i use a different key to manage user sessions? Thanks!

Massimo DiPierro

unread,
Aug 5, 2025, 1:55:48 PMAug 5
to Alfonso Serra, py4web
The problem is that session["user"] is reserved and used by auth. You can print it to see what is there but you should not write in it. It is possible this is not documented and need to be documented.

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/py4web/a8d0cfef-66ab-491e-9319-6a471c95cb28n%40googlegroups.com.
Message has been deleted
Message has been deleted

Alfonso Serra

unread,
Aug 7, 2025, 9:55:19 AMAug 7
to py4web
Hi Massimo.

Yes i suspected that much although the reason i tried to write the user into the session is because auth.login does not do it.

@action("index")
@action.uses("index.html", session, auth)
def index():
    user, error = auth.login(email, pwd)
    print(user) # Yes we get a user record but it will be logged only for this call
    print(session.get("user")) # None
    print(session.user) # None
    return locals()


Is there a way to programmatically log a user into a session? I want to do this to test authenticated content without having to manually fill a form.

To my knowledge this was web2py default behavior, if we wanted to implement a custom auth mechanic, for example not using auth default urls, but it wont manage the session we should be allowed to write to session.user. 

Thanks.
Best Regards.

Alfonso Serra

unread,
Aug 7, 2025, 9:55:27 AMAug 7
to py4web
Sorry cant post code or the comment gets deleted.

I figured that is the reason but if auth.login does not set the session.user how would i programmatically log a user into a session?

Im calling auth.login inside a controller but that does not get a user session. The reason to do this is to be able to test authenticated content.

Thanks
Best Regards.

Alfonso Serra

unread,
Aug 7, 2025, 9:55:35 AMAug 7
to py4web
Thanks Massimo, i suspected that much but the reason i tried to write the user into the session is because auth.login, when called inside a controller does not do it. 

How can we set a user session with auth.login, is it not possible? Is there another way?
@action("index")
@action.uses("index.html", session, auth)
def index():
    user, error = auth.login(email, pwd)
    print(user) # Yes we get a user
    print(session.get("user")) # None
    print(session.user) # None
    return locals()

I wanted to programmatically log a user into a session to test authenticated content without having to manually send a form. 

Thanks!.
Best Regards
On Tuesday, August 5, 2025 at 6:55:48 PM UTC+1 Massimo DiPierro wrote:
Message has been deleted

Christian Varas

unread,
Aug 7, 2025, 11:14:33 AMAug 7
to Alfonso Serra, py4web
Why don't you try authenticating programmatically instead of manipulating the session user object? Here's what I'd suggest:

- Use requests with session to save cookies
- Call the auth login endpoint to get a session cookie
- Grab the CSRF token from the response
- Send the POST with username and password to authenticate your cookie
- Then you can use it to access authenticated content

Way cleaner approach IMO.

Here's a quick Python example:

import requests
from bs4 import BeautifulSoup

session = requests.Session()


# Get login page and grab CSRF token
soup = BeautifulSoup(response.text, 'html.parser')
form_key = soup.find('input', {'name': '_formkey'})['value']

# Auth with credentials
auth_data = {
'email': 'te...@email.com',
'password': '12345',
'_formname': 'no_table',
'_formkey': form_key
}

#log in
session.post("http://127.0.0.1:8000/YOUR-APP/auth/login", data=auth_data)

# Now session has auth cookies, use it for protected stuff
#call a auth protected view
content = session.get("http://127.0.0.1:8000/YOUR-APP/admin")
print(content.text)




Pretty straightforward and much better than messing with session objects directly.

Greetings.

Massimo DiPierro

unread,
Aug 7, 2025, 11:33:20 AMAug 7
to Christian Varas, Alfonso Serra, py4web
I agree. Better use the rest API from outside or one of the following API from inside:




Christian Varas

unread,
Aug 8, 2025, 9:19:58 AMAug 8
to py4web
Hello,

Alfonso Serra

unread,
Aug 9, 2025, 11:14:08 AMAug 9
to py4web
The problem is that py4web is enforcing specific routes to log a user <app>/auth/login. Auth wont work otherwise when it should be agnostic. 
Because my app is a private dashboard i would like to log a user by posting to routes of my own. If i try that, auth.login does not create a user session.

I have found the undocumented function 
auth.store_user_in_session(user["id"])
 and the session only stores the user id, not the full record which makes no sense. The user record was fetched to log the user, why not save all the info so its available for every view? Right now you have to fetch this info every time.

Thanks to this function im able to continue with a few tweaks.

Thanks Christian and Massimo, for your comments and suggestions!

Massimo DiPierro

unread,
Aug 9, 2025, 11:26:46 AMAug 9
to Alfonso Serra, py4web
sessions by default are stored encrypted qnd signed in a cookie to avoid hitting the db at every request. This means the total session size should not exceed 4kb. That is why auth stores only the user id.

If you have auth.user_id you can call auth.current_user() to retrieve the full user info and get the most updated info reliably.






Reply all
Reply to author
Forward
0 new messages