Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to set ds_actor cookie such that it expires #829

Closed
simonw opened this issue Jun 10, 2020 · 6 comments
Closed

Ability to set ds_actor cookie such that it expires #829

simonw opened this issue Jun 10, 2020 · 6 comments

Comments

@simonw
Copy link
Owner

simonw commented Jun 10, 2020

I need this for datasette-auth-github: simonw/datasette-auth-github#62 (comment)

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

itsdangerous has this ability but you specify the max-age when you call unsign: https://itsdangerous.palletsprojects.com/en/1.1.x/timed/

s.unsign(string, max_age=5)
Traceback (most recent call last):
  ...
itsdangerous.exc.SignatureExpired: Signature age 15 > 5 seconds

I currently only decode the ds_actor cookie in one place:

@hookimpl
def actor_from_request(datasette, request):
if "ds_actor" not in request.cookies:
return None
try:
return datasette.unsign(request.cookies["ds_actor"], "actor")
except BadSignature:
return None

If plugins want to be able to set their own policies on how long the ds_actor cookie should remain valid, how do I know to listen to them when decoding the cookie here?

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

Some options:

  • Redesign the ds_actor cookie to be {"expires_at": 1591811250, "actor": ...} - check if it has expired in that default actor_from_request hook
  • Let plugins set an additional cookie of some sort
  • Expect plugins that care about this to set a cookie with a different name and implement their own actor_from_request against that

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

I'm going with expires_at - except to keep the cookies shorter the key will be called e and the actor will go in a, like this:

{
    "e": "1UuHoo",
    "a": {"id": "root"}
}

That e value is a base64 encoded expiry integer timestamp (again for a shorter cookie) - using https://pypi.org/project/python-baseconv/

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

And the e key can be nullor missing for "never expires".

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

Even shorter: encode an integer that is the difference between that expiry timestamp and a more recent epoch - June 1st 2020 will do.

>>> import datetime, calendar
>>> calendar.timegm(datetime.date(2020, 6, 1).timetuple())
1590969600
>>> import baseconv
>>> baseconv.base62.encode(int(time.time() - 1590969600))
'3XST'

@simonw
Copy link
Owner Author

simonw commented Jun 10, 2020

I didn't bother with the alternative epoch - it only shaves off two or three bytes from the cookie.

Documentation for the new ds_actor cookie shape is here: https://datasette.readthedocs.io/en/latest/authentication.html#the-ds-actor-cookie

simonw added a commit that referenced this issue Jun 12, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant