{ "info": { "author": "aruseni", "author_email": "aruseni.magiku@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "What is django-qrauth?\n======================\n\ndjango-qrauth allows you to easily spice up your website with instant user authentication: once a user has signed in on their Mac or PC, they can pick up their smartphone (or tablet, iPod, etc: actually, anything that has Internet access, a camera and a QR code scanning application should work), scan a QR code (which appears on the display after the user clicks the corresponding link) and immediately sign in on their smartphone or other mobile device they use (so they don\u2019t have to enter the site address, their login/email and password).\n\n![A screenshot: scanning an authentication QR code on an Android phone](example.png \"Scanning an authentication QR code on an Android phone\")\n\nYou can see the detailed walkthrough in [this screencast](http://www.youtube.com/watch?v=6ob3oR_Frhk) (in Russian) and in [this blog post](http://habrahabr.ru/post/181093/) (also in Russian).\n\nVisit [Background Dating](http://backgrounddating.com/) to see this in action.\n\nInstallation\n============\n\nStep 1\n------\n\nInstall [Redis](http://redis.io/).\n\nStep 2\n------\n\nInstall django-qrauth:\n\n pip install django-qrauth\n\nStep 3\n------\n\nOpen your templates directory and add the following templates: qrauth/invalid_code.html and qrauth/page.html. For example:\n\n**qrauth/invalid_code.html**\n\n {% extends \"base.html\" %}\n\n {% block title %}Invalid QR code{% endblock %}\n\n {% block content %}\n
\n

Invalid QR code

\n

The QR code you are using for authentication is invalid. Please try to open the page with the QR code again and then rescan it.

\n
\n {% endblock %}\n\n**qrauth/page.html**\n\n {% extends \"base.html\" %}\n\n {% block title %}Authentication QR code{% endblock %}\n\n {% block content %}\n
\n

Authentication QR code

\n

Scan this QR code to instantly sign in to the website on your mobile device (a smartphone, a tablet, etc):

\n
\"QR\"
\n

Every generated QR code only works once and only for 5 minutes. If you need another QR code, just open this page again.

\n
\n {% endblock %}\n\nStep 4\n------\n\nOpen your root urlconf (the module is specified in the ROOT_URLCONF setting) and include the URLs used by the qrauth application:\n\n urlpatterns = patterns('',\n # \u2026\n url(r'^qr/', include('qrauth.urls')),\n # \u2026\n )\n\nConfiguration\n=============\n\nYou may also want to set a custom expiration time. Each QR code is valid for 300 seconds (5 minutes) by default. If you want to change this behavior, change the value of AUTH_QR_CODE_EXPIRATION_TIME setting. AUTH_QR_CODE_EXPIRATION_TIME is in seconds. For example:\n\n AUTH_QR_CODE_EXPIRATION_TIME = 600 # Ten minutes\n\nIf you want to specify the page where the user should be redirected after successfully signing in with a QR code, you have to set the URL using the AUTH_QR_CODE_REDIRECT_URL setting. For example:\n\n AUTH_QR_CODE_REDIRECT_URL = \"/welcome/\"\n\nThe user is redirected to \"/\" by default (which is usually the index page).\n\nIf you need to specify custom Redis connection settings, you can use the AUTH_QR_CODE_REDIS_KWARGS setting. It is a dictionary of keyword arguments that are passed to the redis.StrictRedis class when initializing Redis connections. For example:\n\n AUTH_QR_CODE_REDIS_KWARGS = {\n \"host\": \"localhost\",\n \"port\": 6379,\n \"db\": 0,\n }\n\nAlso, make sure that [LOGIN_URL](https://docs.djangoproject.com/en/dev/ref/settings/#login-url) has a correct value. Otherwise, users can be redirected to a page that does not exist (for example, if someone not authenticated tries to open the page with the QR code).\n\nHow to test\n===========\n\nIf you want to test this locally, make sure that your local web server is available from your mobile device. For example, if your computer and your mobile device are both connected to the same LAN, you should specify your LAN IP address (something like 192.168.0.5:8000 or 0.0.0.0:8000 if you want the web server to listen on all network interfaces) in order to make the web server listen on this address.\n\nIf you use [the \u201csites\u201d framework](https://docs.djangoproject.com/en/dev/ref/contrib/sites/) (django.contrib.sites), make sure you have correcly set the domain for the current site.\n\nFor example, if your LAN IP address is 192.168.0.5 and the development server is listening on port 8000, the domain should be 192.168.0.5:8000. You can set it in the admin interface (/admin/sites/site/).\n\nIf you don\u2019t have the \u201csites\u201d framework enabled, the current site domain will be dynamically determined based on the \u201cHost\u201d header (the get_host() method of the HttpRequest object is used in that case), so even if the development server is listening on both loopback interface and the LAN interface, you should open the website using the LAN IP address (otherwise your mobile device won\u2019t be able to browse to the authentication URL as a loopback interface\u2019s IP will be used in the link).\n\nNow it\u2019s time to try the QR code authentication. Make sure that you are logged in, browse to /qr/ (or use other path if you have specified something else in your root urlconf), pick up your mobile device and try to scan it.\n\nNote that some QR code readers try to prefetch the page\u2019s contents (e.g. to show you the page title), so the QR code will become invalid when you actually open the URL in your web browser. In that case, try to change the settings of your QR code scanning app.\n\nSecurity concerns\n=================\n\n1. If there are XSS vulnerabilities on the website, an attacker may be able to use iframes (at least if you haven\u2019t set the [X-Frame-Options](https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options) header to DENY) or XMLHttpRequest to retrieve an authentication QR code and use it to log into the user\u2019s account.\n\n2. Even without any XSS, it is possible for someone who has access to the user\u2019s session (for example, if the user is still logged in on the website, but is away from the computer) to scan the QR code and therefore to log into the user\u2019s account.\n\nPossible solutions include sending the QR code by email (actually, some users are always logged into their email accounts as well, so this might be meaningless except for the fact that the QR code will not be available from the attacker\u2019s JS) or prompting the user for their password before displaying the QR code (it is still much easier to type the password on a desktop/laptop computer\u2019s keyboard rather than to type the site address + login or email + password on a mobile device\u2019s virtual keyboard).\n\nOf course, even if you implement such protection, you should still carefully check your website for XSS (and other vulnerabilities, such as SQL injections, CSRF, etc), set the session ID cookies with the [HttpOnly](http://en.wikipedia.org/wiki/HTTP_cookie#HttpOnly_cookie) flag and so on. For instance, it would be even worse to accidentally let an attacker know the user\u2019s password (if the user is prompted for the password on a page with some attacker\u2019s JS) than just let them obtain a new session (which only means access to the account, without the password being exposed).\n\nThe general rule here is \u201cthink before you do\u201d. Features can be both handy and secure.\n\nA note on HTTP/HTTPS\n--------------------\n\nIf your web server is behind a reverse proxy (like nginx) and you use SSL for your website, please make sure that the upstream (the web server that you use to run your Django website) is being informed about that, so request.is_secure() will act correctly (so the authentication URLs will have correct scheme). You can do that by adding the [SECURE_PROXY_SSL_HEADER](https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header) setting and supplying the corresponding header from the reverse proxy (but don\u2019t forget to _always_ set or strip this header, in all the requests the reverse proxy sends to the upstream: otherwise, say, if your website is available via both HTTP and HTTPS, then a user opening the website via HTTP will be able to set this header at the client side, so request.is_secure() will return True, which is not good from the point of security).", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aruseni/django-qrauth", "keywords": null, "license": "BSD licence, see LICENCE.md", "maintainer": null, "maintainer_email": null, "name": "django-qrauth", "package_url": "https://pypi.org/project/django-qrauth/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-qrauth/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/aruseni/django-qrauth" }, "release_url": "https://pypi.org/project/django-qrauth/0.1.2/", "requires_dist": null, "requires_python": null, "summary": "Nice QR codes that allow the users to instantly sign in to the website on their mobile devices", "version": "0.1.2" }, "last_serial": 1038416, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "3303837502c414ef789b21ada77b61c7", "sha256": "5a5c3110376393c4a4d5b1661e21e04feb912d5b3a7a0ab5e6c8570722fe3067" }, "downloads": -1, "filename": "django-qrauth-0.1.tar.gz", "has_sig": false, "md5_digest": "3303837502c414ef789b21ada77b61c7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5793, "upload_time": "2013-06-01T11:20:56", "url": "https://files.pythonhosted.org/packages/16/8b/508835cfac193347e275f8f706c304fe8e8a47f7bf511a37d41bee124b62/django-qrauth-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "50d3499c467e6a10872fb6eed2e63b61", "sha256": "107765674dd9fb223d1dbba7f6e8946633d21fcab341d5c2853588b45a88c6e9" }, "downloads": -1, "filename": "django-qrauth-0.1.1.tar.gz", "has_sig": false, "md5_digest": "50d3499c467e6a10872fb6eed2e63b61", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6833, "upload_time": "2013-06-02T09:29:20", "url": "https://files.pythonhosted.org/packages/7d/7c/b22befbae98234cf6d938c0d503f8ad6def083c3a3e5e4c629150787e89d/django-qrauth-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "dfe679dbd646d6e6ec62ba069f8bdee9", "sha256": "ae39aa8fba826c9a56155fb66fac82398f25a19cee84d74e128abacac4d8a030" }, "downloads": -1, "filename": "django-qrauth-0.1.2.tar.gz", "has_sig": false, "md5_digest": "dfe679dbd646d6e6ec62ba069f8bdee9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6881, "upload_time": "2014-03-23T13:13:44", "url": "https://files.pythonhosted.org/packages/7a/c9/285bb4b228f3298d218c5187aa07c31b9136fc29e2585c53ab03d39543ef/django-qrauth-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "dfe679dbd646d6e6ec62ba069f8bdee9", "sha256": "ae39aa8fba826c9a56155fb66fac82398f25a19cee84d74e128abacac4d8a030" }, "downloads": -1, "filename": "django-qrauth-0.1.2.tar.gz", "has_sig": false, "md5_digest": "dfe679dbd646d6e6ec62ba069f8bdee9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6881, "upload_time": "2014-03-23T13:13:44", "url": "https://files.pythonhosted.org/packages/7a/c9/285bb4b228f3298d218c5187aa07c31b9136fc29e2585c53ab03d39543ef/django-qrauth-0.1.2.tar.gz" } ] }