{ "info": { "author": "thor wolpert, with help from others", "author_email": "thor@wolpert.ca", "bugtrack_url": null, "classifiers": [], "description": "Licensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nDescription: # Flask JWT OIDC\n \n ### Simple OIDC JWT extension to protect APIs\n This is a fairly simple extension that should require minimal setup for OIDC standard services.\n \n Currently it's testing against Keycloak, but will be adding in example configs and testing for:\n - Keycloak\n - dex\n - Google\n - Amazon IAM\n - Auth0\n \n \n ### Alternatives\n There are some great alternatives that are not so opinionated and provide more support for general JWTs\n Check out: [**Flask-JWT-Simple**](https://github.com/vimalloc/flask-jwt-simple) \n \n ### Example(s)\n There is one example under\n `example/flask_app`\n It uses pytest and sets up a dummy JWT to be used in the tests.\n ### Configuration\n Create a .env file, or OS configmap, shell exports, etc.\n ```bash\n #.env\n export JWT_OIDC_WELL_KNOWN_CONFIG=\"https://KEYCLOAK-SERVICE/auth/realms/REALM-NAME/.well-known/openid-configuration\"\n export JWT_OIDC_AUDIENCE=\"keycloak-client\"\n export JWT_OIDC_CLIENT_SECRET=\"keycloak-client-secret\"\n ```\n \n Create a config file, that reads in the environment variables:\n ```python\n # config.py\n \n from os import environ as env\n from dotenv import load_dotenv, find_dotenv\n \n \n ENV_FILE = find_dotenv()\n if ENV_FILE:\n load_dotenv(ENV_FILE)\n \n class Config(object):\n \n JWT_OIDC_WELL_KNOWN_CONFIG = env.get('JWT_OIDC_WELL_KNOWN_CONFIG')\n JWT_OIDC_AUDIENCE = env.get('JWT_OIDC_AUDIENCE')\n JWT_OIDC_CLIENT_SECRET = env.get('JWT_OIDC_CLIENT_SECRET')\n ```\n \n Create a flask script that to use the JWT services\n \n Note: that roles can be checked as either *decorators* managing access to the function, or as a *function* call that returns True/False for finer grained access control in the body of the function.\n ```python\n # app.py\n \n from flask import Flask, jsonify\n from flask_cors import cross_origin\n from config import Config\n from flask_jwt_oidc import AuthError, JwtManager\n \n \n app = Flask(__name__)\n \n app.config.from_object(Config)\n \n def get_roles(dict):\n return dict['realm_access']['roles']\n app.config['JWT_ROLE_CALLBACK'] = get_roles\n \n jwt = JwtManager(app)\n \n @app.route(\"/api/secure\")\n @cross_origin(headers=[\"Content-Type\", \"Authorization\"])\n @cross_origin(headers=[\"Access-Control-Allow-Origin\", \"*\"]) # IRL you'd scope this to set domains\n @jwt.requires_auth\n def secure():\n \"\"\"A Bearer JWT is required to get a response from this endpoint\n \"\"\"\n return jsonify(message=\"The is a secured endpoint. You provided a valid Bearer JWT to access it.\")\n \n \n @app.route(\"/api/secured-and-roles\")\n @cross_origin(headers=[\"Content-Type\", \"Authorization\"])\n @cross_origin(headers=[\"Access-Control-Allow-Origin\", \"*\"]) # IRL you'd scope this to a real domain\n @jwt.requires_auth\n def secure_with_roles():\n \"\"\"valid access token and assigned roles are required\n \"\"\"\n if jwt.validate_roles(\"names_editor\"):\n return jsonify(message=\"This is a secured endpoint, where roles were examined in the body of the procedure! \"\n \"You provided a valid JWT token\")\n \n raise AuthError({\n \"code\": \"Unauthorized\",\n \"description\": \"You don't have access to this resource\"\n }, 403)\n \n \n @app.route(\"/api/secured-decorated-roles\")\n @cross_origin(headers=[\"Content-Type\", \"Authorization\"])\n @cross_origin(headers=[\"Access-Control-Allow-Origin\", \"*\"]) # IRL you'd scope this to a real domain\n @jwt.requires_roles(\"names_editor\")\n def secure_deco_roles():\n \"\"\"valid access token and assigned roles are required\n \"\"\"\n return jsonify(message=\"This is a secured endpoint. \"\n \"The roles were checked before entering the body of the procedure! \"\n \"You provided a valid JWT token\")\n \n \n if __name__ == \"__main__\":\n app.run()\n \n ```\n ## Thanks\n The following folks have provided help, feedback, PRs, etc:\n - Jamie Lennox\n - James Hollinger\n \n ## TODO\n - add tests\n - add more examples\n - add tests for the OIDC service providers listed above\n \nKeywords: flask extension development\nPlatform: any\nClassifier: Development Status :: 0.1.3 - Beta\nClassifier: Environment :: Web API\nClassifier: Intended Audience :: Developers\nClassifier: License :: OSI Approved :: Apache 2.0 License\nClassifier: Operating System :: MacOS :: MacOS X\nClassifier: Operating System :: Microsoft :: Windows\nClassifier: Operating System :: POSIX\nClassifier: Programming Language :: Python\nClassifier: Topic :: Communications :: Email\nClassifier: Topic :: Software Development :: GitHub Issue Tracking\nClassifier: Topic :: Software Development :: Libraries :: Python Modules\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/thorwolpert/flask-jwt-oidc", "keywords": "", "license": "Copyright 2018 Thor Wolpert", "maintainer": "", "maintainer_email": "", "name": "flask-jwt-oidc", "package_url": "https://pypi.org/project/flask-jwt-oidc/", "platform": "", "project_url": "https://pypi.org/project/flask-jwt-oidc/", "project_urls": { "Homepage": "https://github.com/thorwolpert/flask-jwt-oidc" }, "release_url": "https://pypi.org/project/flask-jwt-oidc/0.1.5/", "requires_dist": [ "flask", "python-jose", "six" ], "requires_python": "", "summary": "Flask JWT OIDC", "version": "0.1.5" }, "last_serial": 4751776, "releases": { "0.1.1.dev0": [ { "comment_text": "", "digests": { "md5": "4e2e96e310e172188c24d4c19917d04d", "sha256": "d6ad1660d98e0f6348316ee6addcfa3b8f48ac3a6d0c0b1d4cd2e598efa30dce" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.1.dev0-py3-none-any.whl", "has_sig": false, "md5_digest": "4e2e96e310e172188c24d4c19917d04d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7583, "upload_time": "2018-07-25T21:43:44", "url": "https://files.pythonhosted.org/packages/7b/ea/7aaeca1313f30b083eb61eacce89e4a940c6c3c7e2626ed10ee33d8919b9/flask_jwt_oidc-0.1.1.dev0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4f0d467df057166a14a64d80c5c351ba", "sha256": "27996a4af15282248dd46e5370c34e04926aed12e56f81b698553d5e69428b60" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.1.dev0.tar.gz", "has_sig": false, "md5_digest": "4f0d467df057166a14a64d80c5c351ba", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6933, "upload_time": "2018-07-25T21:43:45", "url": "https://files.pythonhosted.org/packages/ce/e8/77a39f14c4fb9714dccff2be6fc551ce3f7598fcb2eacdc59ae948c602c7/flask_jwt_oidc-0.1.1.dev0.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "c074431ace1413850e369cc46a2ef132", "sha256": "89237bcfad59bff094b57fe9bfa4ec235eb337b3f6cd2ca45ed186d278331dc4" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "c074431ace1413850e369cc46a2ef132", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7533, "upload_time": "2018-08-13T05:53:43", "url": "https://files.pythonhosted.org/packages/ec/a4/ffdb9f4c17de1c0c6a3a0cba35400294bbebf454c64fba4fd348a58c31ef/flask_jwt_oidc-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "8e6f9c87783663307a98a2515c5ea4a9", "sha256": "e51e75010dd9022f698595be289d4c7a5a473992b18ba85fe3f8835b79750fbd" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.2.tar.gz", "has_sig": false, "md5_digest": "8e6f9c87783663307a98a2515c5ea4a9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6924, "upload_time": "2018-08-13T05:53:45", "url": "https://files.pythonhosted.org/packages/53/7e/d808c2cf190265dbf9e239da8e1afc1281cec4ac56a4c210a68777cbf687/flask_jwt_oidc-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "ed7946f168c8bab8bdc139c28f5571bf", "sha256": "be07304ea3b65afe28247e8f9f2bdd1510a45d11e708786dfae6b4e06c9ad0e1" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.3-py3.6.egg", "has_sig": false, "md5_digest": "ed7946f168c8bab8bdc139c28f5571bf", "packagetype": "bdist_egg", "python_version": "3.6", "requires_python": null, "size": 13326, "upload_time": "2019-01-17T07:40:27", "url": "https://files.pythonhosted.org/packages/f9/1d/084045267124a1d9698bb99ff401328142f5fedbeeb15ed638230e5460b7/flask_jwt_oidc-0.1.3-py3.6.egg" }, { "comment_text": "", "digests": { "md5": "2fe2f34b6f2db075440e41aa22eec07c", "sha256": "92a0c8d2340a05151479a34c797e7afbd14873e1f2f27479560d7b5d03aa9468" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "2fe2f34b6f2db075440e41aa22eec07c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11525, "upload_time": "2019-01-17T07:40:25", "url": "https://files.pythonhosted.org/packages/eb/1f/4754e82fd303fcf3f4379ca3730a2c5f598bd2b7520623ecc50ddd039416/flask_jwt_oidc-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "501894be6b3f2700a31cb42fd2c84f90", "sha256": "ea54b5185c2e7e3f17e846a0e23183ab4b446839fd1c6ae7f2f959e8fd54bddd" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.3.tar.gz", "has_sig": false, "md5_digest": "501894be6b3f2700a31cb42fd2c84f90", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9498, "upload_time": "2019-01-17T07:40:28", "url": "https://files.pythonhosted.org/packages/ed/c7/9ce6447ebc74df2508040fd08cffaca2b5bab0d604c04280055ce64f396f/flask_jwt_oidc-0.1.3.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "5ecc8fbe0f27763f33e1187aa9bae74e", "sha256": "955dd944138c4573792b8d4fe376b518c6096b86a84cce78a3878706cb948470" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "5ecc8fbe0f27763f33e1187aa9bae74e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11780, "upload_time": "2019-01-28T20:29:45", "url": "https://files.pythonhosted.org/packages/61/5c/aafa1b2e599a1076b028f585543e5b3b0694c93bebe0db14d98b264b67f1/flask_jwt_oidc-0.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d541be4cc82b33265a744d557925bbee", "sha256": "e647dd0648720530c61106aa9a699dd76435b87d5f5a9ba302d7c0032aba5c72" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.5.tar.gz", "has_sig": false, "md5_digest": "d541be4cc82b33265a744d557925bbee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9720, "upload_time": "2019-01-28T20:29:46", "url": "https://files.pythonhosted.org/packages/bd/8d/81dfcb5a58941637ef02ab97689c79692e1ff124d2fcc827d401a613636e/flask_jwt_oidc-0.1.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5ecc8fbe0f27763f33e1187aa9bae74e", "sha256": "955dd944138c4573792b8d4fe376b518c6096b86a84cce78a3878706cb948470" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.5-py3-none-any.whl", "has_sig": false, "md5_digest": "5ecc8fbe0f27763f33e1187aa9bae74e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 11780, "upload_time": "2019-01-28T20:29:45", "url": "https://files.pythonhosted.org/packages/61/5c/aafa1b2e599a1076b028f585543e5b3b0694c93bebe0db14d98b264b67f1/flask_jwt_oidc-0.1.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d541be4cc82b33265a744d557925bbee", "sha256": "e647dd0648720530c61106aa9a699dd76435b87d5f5a9ba302d7c0032aba5c72" }, "downloads": -1, "filename": "flask_jwt_oidc-0.1.5.tar.gz", "has_sig": false, "md5_digest": "d541be4cc82b33265a744d557925bbee", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9720, "upload_time": "2019-01-28T20:29:46", "url": "https://files.pythonhosted.org/packages/bd/8d/81dfcb5a58941637ef02ab97689c79692e1ff124d2fcc827d401a613636e/flask_jwt_oidc-0.1.5.tar.gz" } ] }