{ "info": { "author": "Gnarly Chicken", "author_email": "gnarlychicken@gmx.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3 :: Only", "Topic :: Internet :: WWW/HTTP :: Session" ], "description": "aiohttp_auth\n============\n\nThis library provides authorization and authentication middleware plugins for\naiohttp servers.\n\nThese plugins are designed to be lightweight, simple, and extensible, allowing\nthe library to be reused regardless of the backend authentication mechanism.\nThis provides a familiar framework across projects.\n\nThere are two middleware plugins provided by the library. The auth_middleware\nplugin provides a simple system for authenticating a users credentials, and\nensuring that the user is who they say they are.\n\nThe acl_middleware plugin provides a simple access control list authorization\nmechanism, where users are provided access to different view handlers depending\non what groups the user is a member of.\n\n\nauth_middleware Usage\n---------------------\n\nThe auth_middleware plugin provides a simple abstraction for remembering and\nretrieving the authentication details for a user across http requests.\nTypically, an application would retrieve the login details for a user, and call\nthe remember function to store the details. These details can then be recalled\nin future requests. A simplistic example of users stored in a python dict would\nbe::\n\n from aiohttp_auth import auth\n from aiohttp import web\n\n # Simplistic name/password map\n db = {'user': 'password',\n 'super_user': 'super_password'}\n\n\n async def login_view(request):\n params = await request.post()\n user = params.get('username', None)\n if (user in db and\n params.get('password', None) == db[user]):\n\n # User is in our database, remember their login details\n await auth.remember(request, user)\n return web.Response(body='OK'.encode('utf-8'))\n\n raise web.HTTPForbidden()\n\nUser data can be verified in later requests by checking that their username is\nvalid explicity, or by using the auth_required decorator::\n\n async def check_explicitly_view(request):\n user = await get_auth(request)\n if user is None:\n # Show login page\n return web.Response(body='Not authenticated'.encode('utf-8'))\n\n return web.Response(body='OK'.encode('utf-8'))\n\n @auth.auth_required\n async def check_implicitly_view(request):\n # HTTPForbidden is raised by the decorator if user is not valid\n return web.Response(body='OK'.encode('utf-8'))\n\nTo end the session, the user data can be forgotten by using the forget\nfunction::\n\n @auth.auth_required\n async def logout_view(request):\n await auth.forget(request)\n return web.Response(body='OK'.encode('utf-8'))\n\nThe actual mechanisms for storing the authentication credentials are passed as\na policy to the session manager middleware. New policies can be implemented\nquite simply by overriding the AbstractAuthentication class. The aiohttp_auth\npackage currently provides two authentication policies, a cookie based policy\nbased loosely on mod_auth_tkt (Apache ticket module), and a second policy that\nuses the aiohttp_session class to store authentication tickets.\n\nThe cookie based policy (CookieTktAuthentication) is a simple mechanism for\nstoring the username of the authenticated user in a cookie, along with a hash\nvalue known only to the server. The cookie contains the maximum age allowed\nbefore the ticket expires, and can also use the IP address (v4 or v6) of the\nuser to link the cookie to that address. The cookies data is not encryptedd,\nbut only holds the username of the user and the cookies expiration time, along\nwith its security hash::\n\n def init(loop):\n # Create a auth ticket mechanism that expires after 1 minute (60\n # seconds), and has a randomly generated secret. Also includes the\n # optional inclusion of the users IP address in the hash\n policy = auth.CookieTktAuthentication(urandom(32), 60,\n include_ip=True))\n\n app = web.Application(loop=loop,\n middlewares=[auth.auth_middleware(policy)])\n app = web.Application()\n app.router.add_route('POST', '/login', login_view)\n app.router.add_route('GET', '/logout', logout_view)\n app.router.add_route('GET', '/test0', check_explicitly_view)\n app.router.add_route('GET', '/test1', check_implicitly_view)\n\n return app\n\nThe SessionTktAuthentication policy provides many of the same features, but\nstores the same ticket credentials in a aiohttp_session object, allowing\ndifferent storage mechanisms such as Redis storage, and\nEncryptedCookieStorage::\n\n from aiohttp_session import get_session, session_middleware\n from aiohttp_session.cookie_storage import EncryptedCookieStorage\n\n def init(loop):\n\n # Create a auth ticket mechanism that expires after 1 minute (60\n # seconds), and has a randomly generated secret. Also includes the\n # optional inclusion of the users IP address in the hash\n policy = auth.SessionTktAuthentication(urandom(32), 60,\n include_ip=True))\n\n middlewares = [session_middleware(EncryptedCookieStorage(urandom(32))),\n auth.auth_middleware(policy)]\n\n app = web.Application(loop=loop, middlewares=middlewares)\n\n ...\n\n\nacl_middleware Usage\n---------------------\n\nThe acl_middleware plugin (provided by the aiohttp_auth library), is layered\non top of the auth_middleware plugin, and provides a access control list (ACL)\nsystem similar to that used by the Pyramid WSGI module.\n\nEach user in the system is assigned a series of groups. Each group in the\nsystem can then be assigned permissions that they are allowed (or not allowed)\nto access. Groups and permissions are user defined, and need only be immutable\nobjects, so they can be strings, numbers, enumerations, or other immutable\nobjects.\n\nTo specify what groups a user is a member of, a function is passed to the\nacl_middleware factory which taks a user_id (as returned from the\nauth.get_auth function) as a parameter, and expects a sequence of permitted ACL\ngroups to be returned. This can be a empty tuple to represent no explicit\npermissions, or None to explicitly forbid this particular user_id. Note that\nthe user_id passed may be None if no authenticated user exists. Building apon\nour example, a function may be defined as::\n\n from aiohttp_auth import acl\n\n group_map = {'user': (,),\n 'super_user': ('edit_group',),}\n\n async def acl_group_callback(user_id):\n # The user_id could be None if the user is not authenticated, but in\n # our example, we allow unauthenticated users access to some things, so\n # we return an empty tuple.\n return group_map.get(user_id, tuple())\n\n def init(loop):\n ...\n\n middlewares = [session_middleware(EncryptedCookieStorage(urandom(32))),\n auth.auth_middleware(policy),\n acl.acl_middleware(acl_group_callback)]\n\n app = web.Application(loop=loop, middlewares=middlewares)\n ...\n\n\nNote that the ACL groups returned by the function will be modified by the\nacl_middleware to also include the Group.Everyone group (if the value returned\nis not None), and also the Group.AuthenticatedUser and user_id if the user_id\nis not None.\n\nWith the groups defined, a ACL context can be specified for looking up what\npermissions each group is allowed to access. A context is a sequence of ACL\ntuples which consist of a Allow/Deny action, a group, and a sequence of\npermissions for that ACL group. For example::\n\n from aiohttp_auth.permissions import Group, Permission\n\n context = [(Permission.Allow, Group.Everyone, ('view',)),\n (Permission.Allow, Group.AuthenticatedUser, ('view', 'view_extra')),\n (Permission.Allow, 'edit_group', ('view', 'view_extra', 'edit')),]\n\nViews can then be defined using the acl_required decorator, allowing only\nspecific users access to a particular view. The acl_required decorator\nspecifies a permission required to access the view, and a context to check\nagainst::\n\n @acl_required('view', context)\n async def view_view(request):\n return web.Response(body='OK'.encode('utf-8'))\n\n @acl_required('view_extra', context)\n async def view_extra_view(request):\n return web.Response(body='OK'.encode('utf-8'))\n\n @acl_required('edit', context)\n async def edit_view(request):\n return web.Response(body='OK'.encode('utf-8'))\n\nIn our example, non-logged in users will have access to the view_view, 'user'\nwill have access to both the view_view and view_extra_view, and 'super_user'\nwill have access to all three views. If no ACL group of the user matches the\nACL permission requested by the view, the decorator raises HTTPForbidden.\n\nACL tuple sequences are checked in order, with the first tuple that matches the\ngroup the user is a member of, AND includes the permission passed to the\nfunction, declared to be the matching ACL group. This means that if the ACL\ncontext was modified to::\n\n context = [(Permission.Allow, Group.Everyone, ('view',)),\n (Permission.Deny, 'super_user', ('view_extra')),\n (Permission.Allow, Group.AuthenticatedUser, ('view', 'view_extra')),\n (Permission.Allow, 'edit_group', ('view', 'view_extra', 'edit')),]\n\nIn this example the 'super_user' would be denied access to the view_extra_view\neven though they are an AuthenticatedUser and in the edit_group.\n\nLicense\n-------\n\nThe library is licensed under a MIT license.", "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/gnarlychicken/aiohttp_auth", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "aiohttp_auth", "package_url": "https://pypi.org/project/aiohttp_auth/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/aiohttp_auth/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/gnarlychicken/aiohttp_auth" }, "release_url": "https://pypi.org/project/aiohttp_auth/0.1.1/", "requires_dist": null, "requires_python": null, "summary": "Authorization and authentication middleware plugin for aiohttp.", "version": "0.1.1" }, "last_serial": 1975800, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "05b55e3b4cc9b944092bf6586cebe982", "sha256": "8fbe1fb0308afd70d5e3b36a3cc8ecd20c008dbbb1ee55e84872c8f928f5287f" }, "downloads": -1, "filename": "aiohttp_auth-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "05b55e3b4cc9b944092bf6586cebe982", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 16437, "upload_time": "2016-01-11T01:00:36", "url": "https://files.pythonhosted.org/packages/7b/34/04add2f8aaf0562f8e3408d28f0bc2f7f2d54ab1272a25da3a359654f4c8/aiohttp_auth-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5efc4a242ca8748b8e42c8ecdbec6dff", "sha256": "4c271cdf1c9a5272e03b51ff2d86a642607c4376d29dfb35dca9f4dba63a647c" }, "downloads": -1, "filename": "aiohttp_auth-0.1.0.tar.gz", "has_sig": false, "md5_digest": "5efc4a242ca8748b8e42c8ecdbec6dff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11702, "upload_time": "2016-01-11T01:00:27", "url": "https://files.pythonhosted.org/packages/b8/59/3cd79cc8362ee66768aae3ce6daa82831db1c55090e3dce24c90fb594c24/aiohttp_auth-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "fce75f81b4e48e026f8fe683a08dc625", "sha256": "0ad3dc5201f61f2188344c327b3535ec515e3e47925fef1e587fbdea9c480634" }, "downloads": -1, "filename": "aiohttp_auth-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "fce75f81b4e48e026f8fe683a08dc625", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 16901, "upload_time": "2016-02-25T09:21:48", "url": "https://files.pythonhosted.org/packages/ab/c1/00e84607b69aad9625d66b7fa6668509c527b7b6b7a6de2a1b413414bfb9/aiohttp_auth-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ba0348f635353e8bcc97136c341c6b17", "sha256": "6b2ed2ad6f44819ad9ec3b692dad0489f8f8c59860207d09c639315d06d2e32d" }, "downloads": -1, "filename": "aiohttp_auth-0.1.1.tar.gz", "has_sig": false, "md5_digest": "ba0348f635353e8bcc97136c341c6b17", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9611, "upload_time": "2016-02-25T09:21:39", "url": "https://files.pythonhosted.org/packages/74/1d/261bb7e86b660cb5bdb1f4c28393d8078c189eddc1c87cd16389dfca8500/aiohttp_auth-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "fce75f81b4e48e026f8fe683a08dc625", "sha256": "0ad3dc5201f61f2188344c327b3535ec515e3e47925fef1e587fbdea9c480634" }, "downloads": -1, "filename": "aiohttp_auth-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "fce75f81b4e48e026f8fe683a08dc625", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 16901, "upload_time": "2016-02-25T09:21:48", "url": "https://files.pythonhosted.org/packages/ab/c1/00e84607b69aad9625d66b7fa6668509c527b7b6b7a6de2a1b413414bfb9/aiohttp_auth-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ba0348f635353e8bcc97136c341c6b17", "sha256": "6b2ed2ad6f44819ad9ec3b692dad0489f8f8c59860207d09c639315d06d2e32d" }, "downloads": -1, "filename": "aiohttp_auth-0.1.1.tar.gz", "has_sig": false, "md5_digest": "ba0348f635353e8bcc97136c341c6b17", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9611, "upload_time": "2016-02-25T09:21:39", "url": "https://files.pythonhosted.org/packages/74/1d/261bb7e86b660cb5bdb1f4c28393d8078c189eddc1c87cd16389dfca8500/aiohttp_auth-0.1.1.tar.gz" } ] }