{"id":15566819,"url":"https://github.com/dajiaji/flask-paseto-extended","last_synced_at":"2025-04-23T23:47:40.384Z","repository":{"id":37252746,"uuid":"415156331","full_name":"dajiaji/flask-paseto-extended","owner":"dajiaji","description":"PASETO (Platform-Agnostic Security Token) for Flask applications.","archived":false,"fork":false,"pushed_at":"2025-04-09T18:05:29.000Z","size":1101,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-22T16:08:38.996Z","etag":null,"topics":["flask","flask-extension","jose","jwt","paseto","past","python","security","token"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dajiaji.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-08T23:57:44.000Z","updated_at":"2025-04-09T18:05:26.000Z","dependencies_parsed_at":"2023-10-15T01:51:20.942Z","dependency_job_id":"e3a3917b-8b47-41df-ac41-2eedbb8b52f3","html_url":"https://github.com/dajiaji/flask-paseto-extended","commit_stats":{"total_commits":239,"total_committers":4,"mean_commits":59.75,"dds":0.5815899581589958,"last_synced_commit":"0c718cc4e22d7cffd731e30b67241f27a93a96fd"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dajiaji%2Fflask-paseto-extended","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dajiaji%2Fflask-paseto-extended/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dajiaji%2Fflask-paseto-extended/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dajiaji%2Fflask-paseto-extended/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dajiaji","download_url":"https://codeload.github.com/dajiaji/flask-paseto-extended/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250535083,"owners_count":21446505,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","flask-extension","jose","jwt","paseto","past","python","security","token"],"created_at":"2024-10-02T17:07:09.599Z","updated_at":"2025-04-23T23:47:40.362Z","avatar_url":"https://github.com/dajiaji.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flask PASETO Extended\n\n![Flask PASETO Extended](https://github.com/dajiaji/flask-paseto-extended/wiki/images/flask_paseto_extended_header.png)\n\n[![PyPI version](https://badge.fury.io/py/flask-paseto-extended.svg)](https://badge.fury.io/py/flask-paseto-extended)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-paseto-extended)\n[![Documentation Status](https://readthedocs.org/projects/flask-paseto-extended/badge/?version=latest)](https://flask-paseto-extended.readthedocs.io/en/latest/?badge=latest)\n![Github CI](https://github.com/dajiaji/flask-paseto-extended/actions/workflows/ci.yml/badge.svg)\n[![codecov](https://codecov.io/gh/dajiaji/flask-paseto-extended/branch/main/graph/badge.svg?token=QN8GXEYEP3)](https://codecov.io/gh/dajiaji/flask-paseto-extended)\n\nFlask-PASETO-Extended provides following four classes to use [PASETO (Platform-Agnostic Security Tokens)](https://paseto.io/) for Flask applications:\n\n- **PasetoIssuer**\n  - This class can be used for issuing `public` (signed) PASETO. It is suitable for using PASETO as API tokens.\n- **PasetoVerifier**\n  - This class can be used for verifying `public` (signed) PASETO. It is suitable for using PASETO as API tokens.\n- **PasetoCookieSessionInterface**\n  - Flask (`Flask.sessions`) stores session information as a Cookie value. By using this class, you can serialize the session information as a `local` (encrypted and then MACed) PASETO.\n- **PasetoLoginManager**\n  - By using this class together with [Flask-Login](https://github.com/maxcountryman/flask-login), you can use a `local` PASETO for remember-me tokens which is also encoded into a Cookie value.\n\nFor encoding/decoding PASETO, we have adopted [PySETO](https://github.com/dajiaji/pyseto),\nwhich is a PASETO/PASERK implementation supporting all of PASETO versions (\n[v4](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version4.md),\n[v3](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version3.md),\n[v2](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version2.md) and\n[v1](https://github.com/paseto-standard/paseto-spec/blob/master/docs/01-Protocol-Versions/Version1.md)) and purposes (`local` and `public`).\n\n## Index\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n  - [PasetoIssuer/PasetoVerifier](#pasetoissuerverifier)\n  - [PasetoCookieSessionInterface](#pasetocookiesessioninterface)\n  - [PasetoLoginManager](#pasetologinmanager)\n- [API Reference](#api-reference)\n- [Tests](#tests)\n- [Contributing](#contributing)\n\n## Installation\n\nYou can install Flask-PASETO-Extended with pip:\n\n```sh\n$ pip install flask-paseto-extended\n```\n\n## Basic Usage\n\nFlask-PASETO-Extended provides three classes for each purpose.\n\n### PasetoIssuer/Verifier\n\n`PasetoIssuer` and `PasetoVerifier` can be used for issuing and verifying `public` (signed) PASETO tokens.\n\nBy using `PasetoIssuer`, you can easily implement the endpoint issuing PASETO tokens as follows:\n\n```py\nimport flask\n\nfrom flask_paseto_extended import PasetoIssuer\n\n# Mock user database.\nusers = {\"foo@bar.example\": {\"password\": \"mysecret\"}}\n\n\napp = flask.Flask(__name__)\n\napp.config[\"PASETO_ISS\"] = \"https://issuer.example\"\napp.config[\"PASETO_PRIVATE_KEYS\"] = [\n    {\n        \"version\": 4,\n        \"key\": \"-----BEGIN PRIVATE KEY-----\\nMC4CAQAwBQYDK2VwBCIEILTL+0PfTOIQcn2VPkpxMwf6Gbt9n4UEFDjZ4RuUKjd0\\n-----END PRIVATE KEY-----\",\n    },\n    # PASERK can also be used (RECOMMENDED).\n    # {\n    #     \"paserk\": \"k4.secret.tMv7Q99M4hByfZU-SnEzB_oZu32fhQQUONnhG5QqN3Qeudu7vAR8A_1wYE4AcfCYfhayi3VyJcEfAEFdDiCxog\",\n    # },\n]\nissuer = PasetoIssuer(app)\n\n\n@app.route(\"/login\", methods=[\"POST\"])\ndef login():\n    email = flask.request.form[\"email\"]\n    if flask.request.form[\"password\"] != users[email][\"password\"]:\n        return \"Bad login\"\n\n    token = issuer.issue(payload={\"user\": {\"email\": email}})\n    resp = flask.redirect(flask.url_for(\"protected_me\"))\n    resp.set_cookie(\n        \"paseto\", token, httponly=True\n    )  # Note: MUST add secure=True in production\n    return resp\n```\n\nOn the other hand, by using `PasetoVerifier`, you can easily implement the endpoint verifying PASETO tokens. You can enable PASETO token verification in your APIs by simply adding `@paseto_required` decorator to the API definitions. In the APIs, you can refer to the veified PASETO token with `current_paseto`.\n\n```py\nimport flask\nfrom flask import jsonify, make_response\n\nfrom flask_paseto_extended import PasetoVerifier, current_paseto, paseto_required\n\n# Mock user database.\nusers = {\"foo@bar.example\": {\"password\": \"mysecret\"}}\n\napp = flask.Flask(__name__)\n\n# Configurations for PasetoVerifier.\napp.config[\"PASETO_PUBLIC_KEYS\"] = [\n    {\n        \"iss\": \"https://issuer.exmaple\",\n        \"version\": 4,\n        \"key\": \"-----BEGIN PUBLIC KEY-----\\nMCowBQYDK2VwAyEAHrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI=\\n-----END PUBLIC KEY-----\",\n    },\n    # PASERK can also be used (RECOMMENDED).\n    # {\n    #     \"iss\": \"https://issuer.exmaple\",\n    #     \"paserk\": \"k4.public.Hrnbu7wEfAP9cGBOAHHwmH4Wsot1ciXBHwBBXQ4gsaI\",\n    # },\n]\nverifier = PasetoVerifier(app)\n\n\n@verifier.token_loader\ndef token_loader(req: flask.Request):\n    # You must implement a callback func to extract a PASETO token from each request.\n    return req.cookies.get(\"paseto\", None)\n\n\n@verifier.verification_error_handler\ndef verification_error_handler():\n    # You must also implement a callback func to handle token verification errors..\n    resp = make_response(\"Unauthorized\")\n    resp.delete_cookie(\"paseto\", httponly=True)\n    return resp\n\n\n@app.route(\"/protected/me\")\n@paseto_required()\ndef protected_me():\n    return jsonify(current_paseto.payload[\"user\"])\n```\n\nSee [examples/issuer_and_verifier.py](https://github.com/dajiaji/flask-paseto-extended/blob/main/examples/issuer_and_verifier.py) for a sample code that actually works.\n\n\n### PasetoCookieSessionInterface\n\nFlask (`Flask.sessions`) stores session information as a Cookie value. By using this class, you can serialize the session information as an encrypted (and then MACed) PASETO.\n\nThis class can be used as follows:\n\n```py\nimport flask\nfrom flask_paseto_extended import PasetoCookieSessionInterface\n\napp = flask.Flask(__name__)\napp.secret_key = \"super secret string\"\n\n# Use PASETO(\"v4\" by default) for cookie sessions.\napp.session_interface = PasetoCookieSessionInterface()\n```\n\nSee [examples/cookie_session.py](https://github.com/dajiaji/flask-paseto-extended/blob/main/examples/cookie_session.py) for a sample code that actually works.\n\n### PasetoLoginManager\n\nBy using this class together with [Flask-Login](https://github.com/maxcountryman/flask-login), you can use PASETO for remember-me tokens which is also encoded into a Cookie value.\n\nThis class can be used as follows:\n\n```py\nimport flask\nimport flask_login\n\n# Import PasetoLoginManager instead of flask_login.LoginManager.\nfrom flask_paseto_extended import PasetoLoginManager\n\napp = flask.Flask(__name__)\napp.secret_key = \"super secret string\"\n\nlogin_manager = PasetoLoginManager(app)\n```\n\nSee [examples/login_manager.py](https://github.com/dajiaji/flask-paseto-extended/blob/main/examples/login_manager.py) for a sample code that actually works.\n\n## API Reference\n\nSee [Documentation](https://flask-paseto-extended.readthedocs.io/en/stable/api.html).\n\n\n## Tests\n\nYou can run tests from the project root after cloning with:\n\n```sh\n$ tox\n```\n\n## Contributing\n\nWe welcome all kind of contributions, filing issues, suggesting new features or sending PRs.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdajiaji%2Fflask-paseto-extended","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdajiaji%2Fflask-paseto-extended","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdajiaji%2Fflask-paseto-extended/lists"}