{"id":8116,"library":"django-sesame","title":"Django Sesame","description":"Django Sesame provides frictionless authentication for your Django project using \"Magic Links\". It generates URLs with embedded authentication tokens, allowing users to log in or access specific content without passwords or traditional sessions. The library supports various token-based authentication use cases and is actively maintained, with current version 3.2.3 compatible with recent Django and Python versions.","status":"active","version":"3.2.3","language":"en","source_language":"en","source_url":"https://github.com/aaugustin/django-sesame","tags":["django","authentication","magic-links","passwordless","token-based"],"install":[{"cmd":"pip install django-sesame","lang":"bash","label":"Basic Installation"},{"cmd":"pip install django-sesame[ua]","lang":"bash","label":"With User-Agent Parsing (for Safari)"}],"dependencies":[{"reason":"Core framework requirement, integrates with django.contrib.auth.","package":"Django"},{"reason":"Optional: Mitigates Safari's 'Protection Against First Party Bounce Trackers' by detecting the browser.","package":"ua-parser","optional":true}],"imports":[{"note":"Used to generate a URL query string containing an authentication token for a given user.","symbol":"get_query_string","correct":"from sesame.utils import get_query_string"},{"note":"Used in custom view logic to authenticate a user based on a token found in the request.","symbol":"get_user","correct":"from sesame.utils import get_user"},{"note":"A class-based view that handles token validation and user login, similar to Django's built-in LoginView.","symbol":"LoginView","correct":"from sesame.views import LoginView"},{"note":"The authentication backend to be added to Django's AUTHENTICATION_BACKENDS setting.","symbol":"ModelBackend","correct":"from sesame.backends import ModelBackend"},{"note":"A view decorator to authenticate a user for a specific view using a token.","symbol":"authenticate (decorator)","correct":"from sesame.decorators import authenticate"},{"note":"The `url_auth_token` argument was deprecated and removed in favor of `sesame` in version 2.0.","wrong":"user = authenticate(url_auth_token=token_value)","symbol":"authenticate (function)","correct":"from django.contrib.auth import authenticate\nuser = authenticate(request, sesame=token_value)"}],"quickstart":{"code":"import os\nfrom django.contrib.auth import get_user_model\nfrom django.urls import path\nfrom sesame.views import LoginView\nfrom sesame.utils import get_query_string\n\n# --- Django settings.py (example additions) ---\n# AUTHENTICATION_BACKENDS = [\n#     'django.contrib.auth.backends.ModelBackend',\n#     'sesame.backends.ModelBackend',\n# ]\n# # Optional: Configure token lifetime (e.g., 10 minutes for login by email)\n# import datetime\n# SESAME_MAX_AGE = datetime.timedelta(minutes=10)\n\n# --- Your app's urls.py (example) ---\nurlpatterns = [\n    path(\"sesame/login/\", LoginView.as_view(), name=\"sesame-login\"),\n]\n\n# --- Example usage in a view or script ---\nUser = get_user_model()\n\n# Create or get a user (e.g., for 'jane.doe@example.com')\ntry:\n    user = User.objects.get(email=\"jane.doe@example.com\")\nexcept User.DoesNotExist:\n    user = User.objects.create_user(\"jane.doe\", \"jane.doe@example.com\", \"password123\")\n    user.set_unusable_password() # If only using magic links, make password unusable\n    user.save()\n\n# Assuming a base URL like 'http://127.0.0.1:8000'\nbase_url = os.environ.get('DJANGO_BASE_URL', 'http://127.0.0.1:8000')\nlogin_path = '/sesame/login/'\n\n# Generate a magic link\nmagic_link = base_url + login_path + get_query_string(user)\n\nprint(f\"Magic link for {user.email}: {magic_link}\")\n\n# To test, manually visit this link in a browser while logged out.","lang":"python","description":"To quickly integrate `django-sesame`, first configure your Django `settings.py` by adding `sesame.backends.ModelBackend` to `AUTHENTICATION_BACKENDS`. Then, define a URL route for `sesame.views.LoginView` in your `urls.py`. You can then generate magic links using `sesame.utils.get_query_string(user)` and send them to users. Visiting this link will log the user in. You can also configure `SESAME_MAX_AGE` for token lifetime and mark user passwords as unusable if they'll only use magic links."},"warnings":[{"fix":"Configure all Django Sesame settings carefully before generating tokens in a production environment. If settings must change, regenerate and redistribute new tokens.","message":"Changing most Django Sesame settings (e.g., `SECRET_KEY`, `SESAME_TOKEN_NAME`, `SESAME_TOKENS`) will invalidate all previously generated authentication tokens.","severity":"breaking","affected_versions":"All versions"},{"fix":"After a Django upgrade, regenerate and redistribute new tokens. Alternatively, for long-lived tokens, consider setting `SESAME_INVALIDATE_ON_PASSWORD_CHANGE = False` in `settings.py`, but be aware of the security implications.","message":"Upgrading Django versions can invalidate existing magic links/tokens, particularly long-lived ones. This is because Django's password hashers increase their work factor with new releases, making a password hash upgrade indistinguishable from a password change to `django-sesame`.","severity":"breaking","affected_versions":"All versions, especially when upgrading Django (e.g., 4.x to 5.x, 5.x to 6.x)"},{"fix":"Instead of `SESAME_ONE_TIME`, consider using a short `SESAME_MAX_AGE` (e.g., 5-10 minutes) for login-by-email scenarios to balance security and usability.","message":"One-time tokens (`SESAME_ONE_TIME = True`) can fail if sent via email, as email providers often fetch links for previews or security scans, consuming the token before the actual user clicks it.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Install the `ua-parser` package (`pip install ua-parser`). `django-sesame` will then use it to detect Safari and avoid the problematic redirect.","message":"Safari's 'Protection Against First Party Bounce Trackers' can cause issues (clearing cookies, logging out users) when `django-sesame` redirects after successful authentication.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If this is a concern, consider customizing primary keys or carefully review the use case for magic links.","message":"The primary keys of users are stored in clear text within tokens. While this is not inherently a security flaw if the token is secure, it's a privacy consideration.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Update your code to use the `sesame` keyword argument: `user = authenticate(request, sesame=token_value)`.","cause":"Using the deprecated `url_auth_token` argument with `authenticate()` after upgrading to `django-sesame` v2.0 or later.","error":"django.contrib.auth.backends.ModelBackend.authenticate() received an unexpected keyword argument 'url_auth_token'"},{"fix":"Ensure `SESAME_ONE_TIME = False` explicitly in settings if tokens should be reusable. If you need reusable tokens and also update `last_login` through other means, consider setting `SESAME_INVALIDATE_ON_PASSWORD_CHANGE = False` (with security review) or regenerate tokens.","cause":"If `SESAME_ONE_TIME` is enabled (even implicitly if not explicitly `False`) and the user's `last_login` field is updated by another login mechanism or `authenticate(update_last_login=True)`, the token becomes invalid.","error":"Magic link works once, then fails subsequent attempts, even if 'SESAME_ONE_TIME' is False."}]}