{ "info": { "author": "Aymeric Augustin", "author_email": "aymeric.augustin@m4x.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.11", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": ".. image:: logo/horizontal.svg\n :width: 400px\n :alt: django-sesame\n\n`django-sesame`_ provides frictionless authentication with \"Magic Links\" for\nyour Django project.\n\n.. _django-sesame: https://github.com/aaugustin/django-sesame\n\nIt generates URLs containing an authentication token such as:\nhttps://example.com/?url_auth_token=AAAAARchl18CIQUlImmbV9q7PZk%3A89AEU34b0JLSrkT8Ty2RPISio5\n\nThen it authenticates users based on tokens found in URLs.\n\nUse cases\n=========\n\nKnown use cases for django-sesame include:\n\n1. Login by email, an increasingly attractive option on mobile where\n typing passwords is uncomfortable. This technique is prominently\n deployed by Slack.\n\n If you're doing this, you should define a small ``SESAME_MAX_AGE``, perhaps\n 10 minutes, and consider enabling ``SESAME_ONE_TIME``.\n\n2. Authenticated links, typically if you're generating an export or a report\n and emailing a link to access it. An authenticated link will work even if\n the user isn't logged in on the device where they're opening it.\n\n Likewise, you should configure an appropriate ``SESAME_MAX_AGE``, probably\n no more than a few days.\n\n3. Non-critical private websites, for example for a family or club site,\n where users don't expect to manage a personal account with a password.\n Authorized users can bookmark personalized authenticated URLs.\n\n Here you can rely on the default settings because that's the original use\n case for which django-sesame was built.\n\n(In)security\n============\n\n**Before using django-sesame in your project, please review the following\nadvice carefully.** (Also, please don't use security-sensitive libraries\npublished by strangers on the Internet without checking what they do.)\n\nThe major security weakness in django-sesame is a direct consequence of the\nfeature it implements: **whoever obtains an authentication token will be able\nto authenticate to your website.**\n\nURLs end up in countless insecure places: emails, referer headers, proxy logs,\nbrowser history, etc. You can't avoid that. At best you can mitigate it by\ncreating short-lived or single-use tokens, as described below.\n\nOtherwise, a reasonable attempt has been made to provide a secure solution.\ndjango-sesame uses Django's signing framework to create signed tokens. It\noffers configurable options for token expiration or invalidation.\n\nRequirements\n============\n\ndjango-sesame is tested with:\n\n- Django 1.11 (LTS), 2.1 and 2.2;\n- all supported Python versions.\n\nIt builds upon ``django.contrib.auth``.\n\nIt supports custom user models, provided:\n\n- They have an integer or UUID primary key \u2014 other types could be added\n if there's a use case;\n- They have ``password`` and ``last_login`` fields \u2014 most custom user models\n inherit them from ``AbstractBaseUser``.\n\ndjango-sesame is released under the BSD license, like Django itself.\n\nGetting started\n===============\n\n1. Install django-sesame and ua-parser::\n\n $ pip install django-sesame\n $ pip install ua-parser # optional, see \"Safari issues\" below\n\n2. Add ``sesame.backends.ModelBackend`` to ``AUTHENTICATION_BACKENDS``::\n\n AUTHENTICATION_BACKENDS += ['sesame.backends.ModelBackend']\n\n3. Add ``sesame.middleware.AuthenticationMiddleware`` to ``MIDDLEWARE``::\n\n MIDDLEWARE += ['sesame.middleware.AuthenticationMiddleware']\n\n The best position for ``sesame.middleware.AuthenticationMiddleware`` is\n just after ``django.contrib.auth.middleware.AuthenticationMiddleware``.\n\n4. Generate authentication tokens with ``sesame.utils.get_query_string(user)``.\n\nThat's all!\n\nGenerating URLs\n===============\n\ndjango-sesame provides two functions to generate authenticated URLs.\n\n1. ``sesame.utils.get_query_string(user)`` returns a complete query string\n that you can append to any URL to enable one-click login.\n\n2. ``sesame.utils.get_parameters(user)`` returns a dictionary of GET\n parameters to add to the query string, if you're already building one.\n\nShare resulting URLs with your users while ensuring adequate confidentiality.\n\nBy default, the URL parameter is called ``url_auth_token``. You can set the\n``SESAME_TOKEN_NAME`` setting to a shorter name that doesn't conflict with\nquery string parameters used by your application.\n\nTokens lifecycle\n================\n\nBy default, tokens don't expire but are tied to the password of the user.\nChanging the password invalidates the token. When the authentication backend\nuses salted passwords \u2014 that's been the default in Django for a long time \u2014\nthe token is invalidated even if the new password is identical to the old one.\n\nIf you want tokens to expire after a given amount of time, set the\n``SESAME_MAX_AGE`` setting to a duration in seconds. Then each token will\ncontain the time it was generated at and django-sesame will check if it's\nstill valid at each login attempt.\n\nIf you want tokens to be usable only once, set the ``SESAME_ONE_TIME`` setting\nto ``True``. In that case tokens are only valid if the last login date hasn't\nchanged since they were generated. Since logging in changes the last login\ndate, such tokens are usable at most once.\n\nIf you don't want tokens to be invalidated by password changes, set the\n``SESAME_INVALIDATE_ON_PASSWORD_CHANGE`` setting to ``False``. **This is\nstrongly discouraged because it becomes impossible to invalidate tokens**\nshort of changing the ``SECRET_KEY`` setting. If you're doing it anyway, you\nshould set ``SESAME_MAX_AGE`` to a short value to minimize risks. This option\nmay be useful for generating tokens during a signup process, when you don't\nknow if the token will be used before or after initializing the password.\n\nFinally, if the ``is_active`` attribute of a user is set to ``False``,\ndjango-sesame rejects authentication tokens for this user.\n\nPer-view authentication\n=======================\n\nThe configuration described in the \"Getting started\" section enables a\nmiddleware that looks for a token in every request and, if there is a valid\ntoken, logs the user in. It's as if they had submitted their username and\npassword in a login form.\n\nSometimes this behavior is too blunt. For example, you may want to build a\nMagic Link that gives access to a specific view but doesn't log the user in\npermanently.\n\nTo achieve this, you can remove ``sesame.middleware.AuthenticationMiddleware``\nfrom the ``MIDDLEWARE`` setting and authenticate the user with django-sesame\nin a view as follows::\n\n from django.core.exceptions import PermissionDenied\n from django.http import HttpResponse\n\n from sesame.utils import get_user\n\n def hello(request):\n user = get_user(request)\n if user is None:\n raise PermissionDenied\n return HttpResponse(\"Hello {}!\".format(user))\n\nWhen ``SESAME_ONE_TIME`` is enabled, ``get_user()`` updates the user's last\nlogin date in order to invalidate the token. When ``SESAME_ONE_TIME`` isn't\nenabled, it doesn't, because making a database write for every call to\n``get_user()`` could degrade performance. You can override this behavior with\nthe ``update_last_login`` keyword argument::\n\n get_user(request, update_last_login=True) # update last_login\n get_user(request, update_last_login=False) # don't update last_login\n\n``get_user()`` is a thin wrapper around the low-level ``authenticate()``\nfunction from ``django.contrib.auth``. If you use ``authenticate()`` to verify\nan authentication token, the ``sesame.backends.ModelBackend`` authentication\nbackend expects an ``url_auth_token`` argument::\n\n from django.contrib.auth import authenticate\n\n user = authenticate(url_auth_token=...)\n\nIf you rely on ``authenticate()``, you must update ``user.last_login`` to\nensure one-time tokens are invalidated. Indeed, in ``django.contrib.auth``,\n``authenticate()`` is a low-level function and the higher-level ``login()``\nfunction is responsible for updating ``user.last_login``.\n\nSafari issues\n=============\n\ndjango-sesame removes the token from the URL with a HTTP 302 Redirect after\nauthenticating a user successfully. Unfortunately, in some scenarios, this\ntriggers Safari's \"Protection Against First Party Bounce Trackers\". In that\ncase, Safari clears cookies and the user is logged out.\n\nTo avoid this problem, django-sesame doesn't perform the redirect when it\ndetects that the browser is Safari. This relies on the ua-parser package,\nwhich is an optional dependency. If it isn't installed, django-sesame always\nredirects.\n\nStateless authentication\n========================\n\nTechnically, django-sesame can provide stateless authenticated navigation\nwithout ``django.contrib.sessions``, provided all internal links include the\nauthentication token, but that increases the security issues explained above.\n\nIf ``django.contrib.sessions.middleware.SessionMiddleware`` and\n``django.contrib.auth.middleware.AuthenticationMiddleware`` aren't enabled,\n``sesame.middleware.AuthenticationMiddleware`` sets ``request.user`` to the\ncurrently logged-in user or ``AnonymousUser()``.\n\nChangelog\n=========\n\n1.7\n---\n\n* Fixed invalidation of one-time tokens in ``get_user()``.\n\n1.6\n---\n\n* Fixed detection of Safari on iOS.\n\n1.5\n---\n\n* Added support for single use tokens with the ``SESAME_ONE_TIME`` setting.\n* Added support for not invalidating tokens on password change with the\n ``SESAME_INVALIDATE_ON_PASSWORD_CHANGE`` setting.\n* Added compatibility with custom user models where the primary key is a UUID.\n* Added the ``get_user()`` function to obtain a user instance from a request.\n* Improved error message for pre-existing tokens when changing the\n ``SESAME_MAX_AGE`` setting.\n* Fixed authentication on Safari by disabling the redirect which triggers ITP.\n\n1.4\n---\n\n* Added a redirect to the same URL with the query string parameter removed.\n\n1.3\n---\n\n* Added compatibility with Django \u2265 2.0.\n\n1.2\n---\n\n* Added the ability to rename the query string parameter with the\n ``SESAME_TOKEN_NAME`` setting.\n* Added compatibility with Django \u2265 1.8.\n\n1.1\n---\n\n* Added support for expiring tokens with the ``SESAME_MAX_AGE`` setting.\n\n1.0\n---\n\n* Initial release.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aaugustin/django-sesame", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "django-sesame", "package_url": "https://pypi.org/project/django-sesame/", "platform": "", "project_url": "https://pypi.org/project/django-sesame/", "project_urls": { "Homepage": "https://github.com/aaugustin/django-sesame" }, "release_url": "https://pypi.org/project/django-sesame/1.7/", "requires_dist": null, "requires_python": "", "summary": "URL-based authentication, an application that provides one-click login via specially crafted URLs", "version": "1.7" }, "last_serial": 5375973, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "be452501c526e231c6bd6da161409f15", "sha256": "6391b1cc19613c2fd9a156c582cc2ab8d02ffa7abb182c392d502d873e215fc0" }, "downloads": -1, "filename": "django-sesame-0.1.tar.gz", "has_sig": false, "md5_digest": "be452501c526e231c6bd6da161409f15", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6055, "upload_time": "2012-05-03T22:05:48", "url": "https://files.pythonhosted.org/packages/20/ba/237e5b3f520c461a161aa6f409eae108234bdebb69f060a5a06d97dae709/django-sesame-0.1.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "7bc061bd757207226d4abb61b3746e9d", "sha256": "f34b6bae688764f1557418a1a00f8af29ec525dace4cb4102cca00b9536becaa" }, "downloads": -1, "filename": "django-sesame-1.0.tar.gz", "has_sig": false, "md5_digest": "7bc061bd757207226d4abb61b3746e9d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6365, "upload_time": "2014-07-03T21:41:21", "url": "https://files.pythonhosted.org/packages/ed/06/c81785f40ac64739cf1cfecd57c28d212cae677dbdf8be5c499c23e8843f/django-sesame-1.0.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "dfc6dc627f6d6b21114391ab9746ef4a", "sha256": "96a78edf48a0277f8bc2d33479f35b5ef9e8bbf29bb519fc11e9d4f530a1c954" }, "downloads": -1, "filename": "django-sesame-1.1.tar.gz", "has_sig": false, "md5_digest": "dfc6dc627f6d6b21114391ab9746ef4a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6831, "upload_time": "2014-09-17T20:10:56", "url": "https://files.pythonhosted.org/packages/0f/38/86155b24a4bbcdbd473b75e61751bb90f2614466160f401fbf624959169a/django-sesame-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "1735f83b8da2878ef47edfa5ef3ffeef", "sha256": "b16bdafcfa74e0f112204f22c99d3b51998a4f96ecdf0718f3fbf9038b7fffe6" }, "downloads": -1, "filename": "django_sesame-1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "1735f83b8da2878ef47edfa5ef3ffeef", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 9297, "upload_time": "2016-08-19T13:17:08", "url": "https://files.pythonhosted.org/packages/29/b3/b21aad09de12c8357746faca66f0fcbc40508a4b4d4a3eafc2aef3ed3949/django_sesame-1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0b1400e59ec666e1e5d4e18f41ad8c2c", "sha256": "a2ba805ae29dd5035708fd06d157c2e25bc5a211fecbb36158cd68e4dc9822ea" }, "downloads": -1, "filename": "django-sesame-1.2.tar.gz", "has_sig": false, "md5_digest": "0b1400e59ec666e1e5d4e18f41ad8c2c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7295, "upload_time": "2016-08-19T13:17:04", "url": "https://files.pythonhosted.org/packages/ef/17/54617b2ceeebcf2a8241fcd63e7a16e7d94265e02ed87ba06269b56507c3/django-sesame-1.2.tar.gz" } ], "1.3": [ { "comment_text": "", "digests": { "md5": "2449f0c95278f3d9c71e1b654b50931a", "sha256": "022079bc36edec3f3e427a5490a92261d2583d4b629220728c1de02f6cccd2d2" }, "downloads": -1, "filename": "django_sesame-1.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2449f0c95278f3d9c71e1b654b50931a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11497, "upload_time": "2017-12-02T20:20:37", "url": "https://files.pythonhosted.org/packages/66/47/62a370d26db571969d9ae83bbfa41e9232a58ec6644a811e94aecd8196c1/django_sesame-1.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "33a19b7823520ad6e332288aeb308678", "sha256": "10391e973627da3e45f6ea5ff073685efb11d30567aaf40c1daa8d1313ab842f" }, "downloads": -1, "filename": "django-sesame-1.3.tar.gz", "has_sig": false, "md5_digest": "33a19b7823520ad6e332288aeb308678", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7309, "upload_time": "2017-12-02T20:20:39", "url": "https://files.pythonhosted.org/packages/0e/a8/b1e580cc656be6a0288d7e82135f496c06f2fdce4f20041b525cd2ebb12a/django-sesame-1.3.tar.gz" } ], "1.4": [ { "comment_text": "", "digests": { "md5": "7bfd3729c6b980683eff364c5c0f24b5", "sha256": "7da5072e3f2298b94ec78c838d467d4585cbc6efec2248d326b6ae4fb2c32271" }, "downloads": -1, "filename": "django_sesame-1.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7bfd3729c6b980683eff364c5c0f24b5", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 10079, "upload_time": "2018-04-29T07:45:31", "url": "https://files.pythonhosted.org/packages/75/83/1dd29b174f0eedad987a24de30065b1ba49d2202c1f1631df99e81b1aab1/django_sesame-1.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "566529e8be85fac14ea5c0c7369bcaae", "sha256": "4a2d88417fe49c62c73e061cf03510697eba01a72ea57763942a2a9eda1e3820" }, "downloads": -1, "filename": "django-sesame-1.4.tar.gz", "has_sig": false, "md5_digest": "566529e8be85fac14ea5c0c7369bcaae", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9507, "upload_time": "2018-04-29T07:45:29", "url": "https://files.pythonhosted.org/packages/52/72/43003e3133a008ce6efd983c0cb6e12e42638ddc3172b49d679965cb32fc/django-sesame-1.4.tar.gz" } ], "1.5": [ { "comment_text": "", "digests": { "md5": "1a9983948be078881c1b4be37a4452c3", "sha256": "b5ff272729550bd8266fb028cf2f209af5d447a82a14fcecd8d39067809872db" }, "downloads": -1, "filename": "django_sesame-1.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1a9983948be078881c1b4be37a4452c3", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15297, "upload_time": "2019-05-01T07:14:49", "url": "https://files.pythonhosted.org/packages/24/54/556da68c3dc46d0c4413d44fc5850d68a867dca5dc1f126cb5a5e497d92d/django_sesame-1.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d3603fdd0e272f9729ee0a0a80a838c3", "sha256": "820d5b9bbefdac713dad5f68c1ff4e839498a6d9daab96ce2aa939935212e3fc" }, "downloads": -1, "filename": "django-sesame-1.5.tar.gz", "has_sig": false, "md5_digest": "d3603fdd0e272f9729ee0a0a80a838c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12021, "upload_time": "2019-05-01T07:14:51", "url": "https://files.pythonhosted.org/packages/be/1a/14881caed2f499e6c3815d3b0f50630c7d351c8d0a60d283c01f74f355ed/django-sesame-1.5.tar.gz" } ], "1.6": [ { "comment_text": "", "digests": { "md5": "d5cf61ee1bfec6e2bc276e3694c13eba", "sha256": "668f0f4206d9c8a2d7d13c1198551b6f907b0be8167032573f75c4cfea1cc769" }, "downloads": -1, "filename": "django_sesame-1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d5cf61ee1bfec6e2bc276e3694c13eba", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 15508, "upload_time": "2019-05-18T17:34:02", "url": "https://files.pythonhosted.org/packages/81/8d/db619bd0f00b69a83e2b334623836e432edac53dead3f22b2bf326147c8d/django_sesame-1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5c0b0b08f6c4276c6d1bfa79b82eea36", "sha256": "01f464b2526ad9438815173dc25aa19e5a07789a5109645333309ffbfa57c5a4" }, "downloads": -1, "filename": "django-sesame-1.6.tar.gz", "has_sig": false, "md5_digest": "5c0b0b08f6c4276c6d1bfa79b82eea36", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12337, "upload_time": "2019-05-18T17:34:05", "url": "https://files.pythonhosted.org/packages/f9/fd/6ccfcfaf9f7121798a5573122137b41a69b987c46ec4a7acb589c5adf24f/django-sesame-1.6.tar.gz" } ], "1.7": [ { "comment_text": "", "digests": { "md5": "e83520a8b0575ed69612aefa0307a190", "sha256": "8d2852f441217fd8a3de5fa8199dd16e4148229ecf25717f69564223e47097f8" }, "downloads": -1, "filename": "django_sesame-1.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e83520a8b0575ed69612aefa0307a190", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 17029, "upload_time": "2019-06-08T18:52:12", "url": "https://files.pythonhosted.org/packages/ab/b0/1a2345e5d697e77a45ca191e6643a8ff8a53c954e59baa5aa3500812b9bc/django_sesame-1.7-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0e8d3174c63a79aa818c3ea79788882e", "sha256": "e68bad4a6ef44322380f1f01d009f9d3cb55d1ffef0b669574b511db5ab0c6c0" }, "downloads": -1, "filename": "django-sesame-1.7.tar.gz", "has_sig": false, "md5_digest": "0e8d3174c63a79aa818c3ea79788882e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13861, "upload_time": "2019-06-08T18:52:14", "url": "https://files.pythonhosted.org/packages/43/c4/2d48e351983da54b4fff5e4a5f9cbeee8c86f4e13a1c825869ed7b972fbe/django-sesame-1.7.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e83520a8b0575ed69612aefa0307a190", "sha256": "8d2852f441217fd8a3de5fa8199dd16e4148229ecf25717f69564223e47097f8" }, "downloads": -1, "filename": "django_sesame-1.7-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e83520a8b0575ed69612aefa0307a190", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 17029, "upload_time": "2019-06-08T18:52:12", "url": "https://files.pythonhosted.org/packages/ab/b0/1a2345e5d697e77a45ca191e6643a8ff8a53c954e59baa5aa3500812b9bc/django_sesame-1.7-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0e8d3174c63a79aa818c3ea79788882e", "sha256": "e68bad4a6ef44322380f1f01d009f9d3cb55d1ffef0b669574b511db5ab0c6c0" }, "downloads": -1, "filename": "django-sesame-1.7.tar.gz", "has_sig": false, "md5_digest": "0e8d3174c63a79aa818c3ea79788882e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13861, "upload_time": "2019-06-08T18:52:14", "url": "https://files.pythonhosted.org/packages/43/c4/2d48e351983da54b4fff5e4a5f9cbeee8c86f4e13a1c825869ed7b972fbe/django-sesame-1.7.tar.gz" } ] }