{ "info": { "author": "Drew Bednar", "author_email": "drew@androiddrew.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "# molten-jwt\n\n\n[![PyPI](https://img.shields.io/pypi/v/molten-jwt.svg)](https://pypi.python.org/project/molten-jwt/)\n[![PyPI](https://img.shields.io/pypi/pyversions/molten-jwt.svg)](https://pypi.python.org/project/molten-jwt/)\n[![Build Status](https://travis-ci.org/androiddrew/molten-jwt.svg?branch=master)](https://travis-ci.org/androiddrew/molten-jwt)\n[![codecov](https://codecov.io/gh/androiddrew/molten-jwt/branch/master/graph/badge.svg)](https://codecov.io/gh/androiddrew/molten-jwt)\n\nA JSON Web Token(JWT) library built on top of [Authlib](https://github.com/lepture/authlib) for use in the [Molten](https://github.com/Bogdanp/molten) web framework.\n\n## Usage\n\n### JWT\n\nThe `JWT` class provides the core methods to encode and decode JSON Web Tokens in your application or middleware. All tokens produced are signed with a key and algorithm according to the JSON Web Signature(JWS) specification. \n\n*__Note__: Signing a token does not mean that the token contents are encrypted. This signature is used to prevent tampering. Take care not to expose private information in unencrypted tokens. Also please always use transport level security (TLS)*\n\n```python\nfrom molten_jwt import JWT\n\njwt = JWT(key='asecretkeyforsigning', alg=\"HS256\")\n\ntoken = jwt.encode({'sub': 'superman'})\n\ndecoded = jwt.decode(token)\n```\n\n### JWT with dependency injection\n\nRegister the `JWTComponent` with your Molten application and provide a `JWT_SECRET_KEY` in the molten `Settings`. The `SettingsComponent` is utilized to provide the configuration for your `JWT` injectable instance. Now simply annotate your a handler param with the `JWT` type and use it to encode your JSON Web Token. \n\n```python\nfrom typing import Dict\nfrom molten import (\n App,\n Route,\n Settings,\n SettingsComponent,\n schema,\n field,\n HTTP_403,\n HTTP_500,\n)\nfrom molten.errors import HTTPError\n\nfrom molten_jwt import JWT, JWTComponent\n\nsettings = Settings({\"JWT_SECRET_KEY\": \"donotcommittoversioncontrol\"})\n\n\n@schema\nclass UserData:\n email: str\n password: str = field(request_only=True)\n\n\ndef db_login(data: UserData):\n # DB magic happens here. This is just to have a working example for copy pasta\n setattr(data, \"id\", 1)\n return data\n\n\ndef login(data: UserData, jwt: JWT) -> Dict:\n # Perform the authentication task with your data layer\n user = db_login(data)\n if not user:\n raise HTTPError(HTTP_403, \"Incorrect username or password\")\n\n payload = {\"sub\": user.id, \"name\": user.email, \"other_data\": \"12345\"}\n try:\n token = jwt.encode(payload)\n except Exception:\n raise HTTPError(HTTP_500, \"Internal error encountered\")\n\n return {\"token\": token}\n\n\ncomponents = [SettingsComponent(settings), JWTComponent()]\n\nroutes = [Route(\"/login\", login, method=\"POST\")]\n\napp = App(routes=routes, components=components)\n```\n\n### JWTIdentity\n\nA `JWTIdentity` component can be added to your application to provide a user representation from a decoded access token. By default this library assumes your access token is sent in the `Authorization` header of the request. Alternatively, you can provide a cookie name using `JWT_AUTH_COOKIE` within your settings, however current functionality does not support both methods. Add the `JWTIdentityComponent` to your app's component list then inject the `JWTIdentity` into your handler. In the event that the `Authorization` header / cookie is not found or if an error occurs in the decoding of the token the `JWTIdentityComponent` will return `None`.\n\n```python\n\n...\n\nfrom molten_jwt import JWT, JWTIdentity, JWTComponent, JWTIdentityComponent\n\n...\n\n\ndef protected_endpoint(jwt_user: JWTIdentity) -> Dict:\n if jwt_user is None:\n raise HTTPError(HTTP_403, \"Forbidden\")\n\n return {\"user_id\": jwt_user.id, \"name\": jwt_user.user_name, \"token\": jwt_user.token}\n\n\ncomponents = [SettingsComponent(settings), JWTComponent(), JWTIdentityComponent()]\n\nroutes = [\n Route(\"/login\", login, method=\"POST\"),\n Route(\"/safe\", protected_endpoint, method=\"GET\"),\n]\n\napp = App(routes=routes, components=components)\n\n\n```\n\n### JWTAuthMiddleware\n\nThe `JWTAuthMiddleware` can be added to your application to globally validate that a JSON Web Token was passed within the `Authorization` header or a named cookie of the request. This middleware depends on the availability of a `molten.Settings`component, a `molten_jwt.JWT` component, and a `molten_jwt.JWTIdentity` component.\n\nUse the `molten_jwt.decorators.allow_anonymous` decorator to allow for non-authenticated access to endpoints when using this middleware. Alternatively, the `JWT_AUTH_WHITELIST` setting can be used to provided a list of handler names that should skip authentication checks.\n\n\n```python\n\nfrom typing import Dict\nfrom molten import (\n App,\n Route,\n Settings,\n SettingsComponent,\n schema,\n field,\n HTTP_403,\n HTTP_500,\n ResponseRendererMiddleware,\n)\nfrom molten.errors import HTTPError\n\nfrom molten_jwt import JWT, JWTIdentity, JWTComponent, JWTIdentityComponent, JWTAuthMiddleware\nfrom molten_jwt.decorators import allow_anonymous\n\nsettings = Settings({\"JWT_SECRET\": \"donotcommittoversioncontrol\"})\n\n\n@schema\nclass UserData:\n email: str\n password: str = field(request_only=True)\n\n\ndef db_login(data: UserData):\n # DB magic happens here this is just to have a working example\n setattr(data, \"id\", 1)\n return data\n\n\n@allow_anonymous\ndef login(data: UserData, jwt: JWT) -> Dict:\n # Perform the authentication task with your data layer\n user = db_login(data)\n if not user:\n raise HTTPError(HTTP_403, \"Incorrect username or password\")\n\n payload = {\"sub\": user.id, \"name\": user.email, \"other_data\": \"12345\"}\n try:\n token = jwt.encode(payload)\n except Exception:\n raise HTTPError(HTTP_500, \"Interal error encountered\")\n\n return {\"token\": token}\n\n\ndef protected_endpoint(jwt_user: JWTIdentity) -> Dict:\n \"\"\"Will raise a 401 HTTP status if a JWT is not present or is invalid\"\"\"\n return {\"user_id\": jwt_user.id, \"name\": jwt_user.user_name, \"token\": jwt_user.token}\n\n\n@allow_anonymous\ndef anonymous_ok(jwt_user: JWTIdentity) -> Dict:\n if jwt_user is None:\n return {\n \"message\": \"JWT token not presented or is invalid. Accessing resource as anonymous.\"\n }\n return {\"user_id\": jwt_user.id, \"name\": jwt_user.user_name, \"token\": jwt_user.token}\n\n\ncomponents = [SettingsComponent(settings), JWTComponent(), JWTIdentityComponent()]\n\nmiddleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()]\n\nroutes = [\n Route(\"/login\", login, method=\"POST\"),\n Route(\"/safe\", protected_endpoint, method=\"GET\"),\n Route(\"/anyone\", anonymous_ok, method=\"GET\"),\n]\n\napp = App(routes=routes, components=components, middleware=middleware)\n\n```\n\n### Attribution\n\nMany thanks to [apistar-jwt](https://github.com/audiolion/apistar-jwt) for providing the inspiration and starting point for this package.\n\n\n# History\n\n### 0.2.1 Change / Fixed\n\n* Fixed README.md code examples\n* Pinned Authlib version due to API changes in Authlib 0.11\n\n### 0.2.0 Change / Added / Fixed\n\n* `JWTUser` is now known as `JWTIdentity`\n* `JWTIdentity` now has dynamic attribute access to its token claims via standard dot notation\n* Authentication code and components have been relocated to `molten_jwt.auth`\n* `JWT` is now a simple wrapper around `authlib.jwt` with no dependencies on the `molten.Settings`.\n* `JWTComponent` will return a single JWT instance configured from the settings passed in the `molten.Settings`\n* `JWTIdentityComponent` now has a setting to extract a JWTdentity from a json web token passed in a named cookie.\n* `JWTAuthMiddleware` now has new settings to control authentication checking, including a whitelist of handlers.\n\n### 0.1.1 Added / Fixed\n\n* Updated documentation before push to Pypi\n* Fixed bumpversion replacement string\n\n### 0.1.0 Change\n\nSwitched from using PyJWT to Authlib for JWT support\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/androiddrew/molten-jwt", "keywords": "molten-jwt molten_jwt molten jwt JWT", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "molten-jwt", "package_url": "https://pypi.org/project/molten-jwt/", "platform": "", "project_url": "https://pypi.org/project/molten-jwt/", "project_urls": { "Homepage": "https://github.com/androiddrew/molten-jwt" }, "release_url": "https://pypi.org/project/molten-jwt/0.2.1/", "requires_dist": [ "molten (>=0.7.1)", "Authlib (<0.11,>=0.10)", "pytest; extra == 'testing'", "pytest-cov; extra == 'testing'", "tox; extra == 'testing'" ], "requires_python": "", "summary": "A JSON Web Token library for the Molten web framework", "version": "0.2.1" }, "last_serial": 5477578, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "89ab089ede067d6327beb5ee6bca55b2", "sha256": "17350fe178f4604871083a2d6f9ee40bc75c1450b8ea628ef5094f80e54e5b7a" }, "downloads": -1, "filename": "molten_jwt-0.1.1-py36-none-any.whl", "has_sig": false, "md5_digest": "89ab089ede067d6327beb5ee6bca55b2", "packagetype": "bdist_wheel", "python_version": "py36", "requires_python": null, "size": 7335, "upload_time": "2018-10-21T14:48:42", "url": "https://files.pythonhosted.org/packages/1d/7a/0ccfe2265c6fedeab2460e6cc431220a351fcae5d690b2e5910d53908dfb/molten_jwt-0.1.1-py36-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5c89225f2bf6caf32da9258d365034f8", "sha256": "6551b83a22346c4c35a90c937c0b6d44821ead88bfff40d003c65807de1413e0" }, "downloads": -1, "filename": "molten_jwt-0.1.1.tar.gz", "has_sig": false, "md5_digest": "5c89225f2bf6caf32da9258d365034f8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8507, "upload_time": "2018-10-21T14:48:43", "url": "https://files.pythonhosted.org/packages/46/08/e1d64fced8eaac03422c478cb4a97d0e4c38830c9d042a8dd903bcc88c9c/molten_jwt-0.1.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "3d652f61dcf16735c7e97427384c0e92", "sha256": "7b418500200be72ea20d97ce0c86cce12e7b1658b3495ca792b87b54a9191c29" }, "downloads": -1, "filename": "molten_jwt-0.2.0-py36-none-any.whl", "has_sig": false, "md5_digest": "3d652f61dcf16735c7e97427384c0e92", "packagetype": "bdist_wheel", "python_version": "py36", "requires_python": null, "size": 9353, "upload_time": "2019-01-28T02:25:16", "url": "https://files.pythonhosted.org/packages/fa/82/c8dfece8ab7b3caf41c20acc4ae911cb37b9363984d13672000ca477632b/molten_jwt-0.2.0-py36-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f18117c88cc8e4594111b5a99d62558e", "sha256": "78137f9b06cb5cf77d4bc57316e786d31b5fcc30bc7aa86c6a32331ec3a8200b" }, "downloads": -1, "filename": "molten_jwt-0.2.0.tar.gz", "has_sig": false, "md5_digest": "f18117c88cc8e4594111b5a99d62558e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11002, "upload_time": "2019-01-28T02:25:18", "url": "https://files.pythonhosted.org/packages/16/09/6b353438085e350a3eafea3d25a25eb453362adefba0638acc29364fb433/molten_jwt-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "5c5018d3e88927a3722eee9b02b7efcf", "sha256": "7e0ee7007bc9f15885337cc41a27e2e0a7996827e009690cf8e91121b90b6afc" }, "downloads": -1, "filename": "molten_jwt-0.2.1-py36-none-any.whl", "has_sig": false, "md5_digest": "5c5018d3e88927a3722eee9b02b7efcf", "packagetype": "bdist_wheel", "python_version": "py36", "requires_python": null, "size": 9413, "upload_time": "2019-07-02T17:17:18", "url": "https://files.pythonhosted.org/packages/19/1e/dfbb70b224d66a624a272a7511355200bd45501a7e0399c50e7ac104d09f/molten_jwt-0.2.1-py36-none-any.whl" }, { "comment_text": "", "digests": { "md5": "112abfe56217dc5751a472762eecc46b", "sha256": "b71031359fdff095db508ae8ae946c37fba9de02563733f8b45af8a52708bfc9" }, "downloads": -1, "filename": "molten_jwt-0.2.1.tar.gz", "has_sig": false, "md5_digest": "112abfe56217dc5751a472762eecc46b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11040, "upload_time": "2019-07-02T17:17:19", "url": "https://files.pythonhosted.org/packages/06/e0/00880b37f82f940fdc21c97f8bcefd605c3ab16bbf4d039925d23ef5bc54/molten_jwt-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5c5018d3e88927a3722eee9b02b7efcf", "sha256": "7e0ee7007bc9f15885337cc41a27e2e0a7996827e009690cf8e91121b90b6afc" }, "downloads": -1, "filename": "molten_jwt-0.2.1-py36-none-any.whl", "has_sig": false, "md5_digest": "5c5018d3e88927a3722eee9b02b7efcf", "packagetype": "bdist_wheel", "python_version": "py36", "requires_python": null, "size": 9413, "upload_time": "2019-07-02T17:17:18", "url": "https://files.pythonhosted.org/packages/19/1e/dfbb70b224d66a624a272a7511355200bd45501a7e0399c50e7ac104d09f/molten_jwt-0.2.1-py36-none-any.whl" }, { "comment_text": "", "digests": { "md5": "112abfe56217dc5751a472762eecc46b", "sha256": "b71031359fdff095db508ae8ae946c37fba9de02563733f8b45af8a52708bfc9" }, "downloads": -1, "filename": "molten_jwt-0.2.1.tar.gz", "has_sig": false, "md5_digest": "112abfe56217dc5751a472762eecc46b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11040, "upload_time": "2019-07-02T17:17:19", "url": "https://files.pythonhosted.org/packages/06/e0/00880b37f82f940fdc21c97f8bcefd605c3ab16bbf4d039925d23ef5bc54/molten_jwt-0.2.1.tar.gz" } ] }