{"id":13699149,"url":"https://github.com/authlib/example-oauth2-server","last_synced_at":"2025-05-04T07:31:46.350Z","repository":{"id":12002773,"uuid":"14581779","full_name":"authlib/example-oauth2-server","owner":"authlib","description":"Example for OAuth 2 Server for Authlib.","archived":false,"fork":false,"pushed_at":"2023-07-11T04:14:50.000Z","size":177,"stargazers_count":680,"open_issues_count":12,"forks_count":284,"subscribers_count":23,"default_branch":"master","last_synced_at":"2024-08-03T19:08:47.292Z","etag":null,"topics":["authlib","oauth2","oauth2-provider","oauth2-server"],"latest_commit_sha":null,"homepage":"https://authlib.org/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/authlib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-11-21T08:24:16.000Z","updated_at":"2024-07-31T04:27:45.000Z","dependencies_parsed_at":"2023-01-13T16:45:17.215Z","dependency_job_id":null,"html_url":"https://github.com/authlib/example-oauth2-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authlib%2Fexample-oauth2-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authlib%2Fexample-oauth2-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authlib%2Fexample-oauth2-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/authlib%2Fexample-oauth2-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/authlib","download_url":"https://codeload.github.com/authlib/example-oauth2-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224390583,"owners_count":17303579,"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":["authlib","oauth2","oauth2-provider","oauth2-server"],"created_at":"2024-08-02T19:01:04.818Z","updated_at":"2024-11-13T04:30:29.756Z","avatar_url":"https://github.com/authlib.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# How to create an OAuth 2.0 Provider\n\nThis is an example of OAuth 2.0 server in [Authlib](https://authlib.org/).\nIf you are looking for old Flask-OAuthlib implementation, check the\n`flask-oauthlib` branch.\n\n- Documentation: \u003chttps://docs.authlib.org/en/latest/flask/2/\u003e\n- Authlib Repo: \u003chttps://github.com/lepture/authlib\u003e\n\n## Sponsors\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg align=\"middle\" width=\"48\" src=\"https://user-images.githubusercontent.com/290496/39297078-89d00928-497d-11e8-8119-0c53afe14cd0.png\"\u003e\u003c/td\u003e\n    \u003ctd\u003eIf you want to quickly add secure token-based authentication to Python projects, feel free to check Auth0's Python SDK and free plan at \u003ca href=\"https://auth0.com/overview?utm_source=GHsponsor\u0026utm_medium=GHsponsor\u0026utm_campaign=example-oauth2-server\"\u003eauth0.com/overview\u003c/a\u003e.\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Take a quick look\n\nThis is a ready to run example, let's take a quick experience at first. To\nrun the example, we need to install all the dependencies:\n\n```bash\n$ pip install -r requirements.txt\n```\n\nSet Flask and Authlib environment variables:\n\n```bash\n# disable check https (DO NOT SET THIS IN PRODUCTION)\n$ export AUTHLIB_INSECURE_TRANSPORT=1\n```\n\nCreate Database and run the development server:\n\n```bash\n$ flask run\n```\n\nNow, you can open your browser with `http://127.0.0.1:5000/`, login with any\nname you want.\n\nBefore testing, we need to create a client:\n\n![create a client](https://user-images.githubusercontent.com/290496/38811988-081814d4-41c6-11e8-88e1-cb6c25a6f82e.png)\n\n### Password flow example\n\nGet your `client_id` and `client_secret` for testing. In this example, we\nhave enabled `password` grant types, let's try:\n\n```\n$ curl -u ${client_id}:${client_secret} -XPOST http://127.0.0.1:5000/oauth/token -F grant_type=password -F username=${username} -F password=valid -F scope=profile\n```\n\nBecause this is an example, every user's password is `valid`. Now you can access `/api/me`:\n\n```bash\n$ curl -H \"Authorization: Bearer ${access_token}\" http://127.0.0.1:5000/api/me\n```\n\n### Authorization code flow example\n\nTo test the authorization code flow, you can just open this URL in your browser.\n```bash\n$ open http://127.0.0.1:5000/oauth/authorize?response_type=code\u0026client_id=${client_id}\u0026scope=profile\n```\n\nAfter granting the authorization, you should be redirected to `${redirect_uri}/?code=${code}`\n\nThen your app can send the code to the authorization server to get an access token:\n\n```bash\n$ curl -u ${client_id}:${client_secret} -XPOST http://127.0.0.1:5000/oauth/token -F grant_type=authorization_code -F scope=profile -F code=${code}\n```\n\nNow you can access `/api/me`:\n\n```bash\n$ curl -H \"Authorization: Bearer ${access_token}\" http://127.0.0.1:5000/api/me\n```\n\nFor now, you can read the source in example or follow the long boring tutorial below.\n\n**IMPORTANT**: To test implicit grant, you need to `token_endpoint_auth_method` to `none`.\n\n## Preparation\n\nAssume this example doesn't exist at all. Let's write an OAuth 2.0 server\nfrom scratch step by step.\n\n### Create folder structure\n\nHere is our Flask website structure:\n\n```\napp.py         --- FLASK_APP\nwebsite/\n  app.py       --- Flask App Factory\n  __init__.py  --- module initialization (empty)\n  models.py    --- SQLAlchemy Models\n  oauth2.py    --- OAuth 2.0 Provider Configuration\n  routes.py    --- Routes views\n  templates/\n```\n\n### Installation\n\nCreate a virtualenv and install all the requirements. You can also put the\ndependencies into `requirements.txt`:\n\n```\nFlask\nFlask-SQLAlchemy\nAuthlib\n```\n\n### Hello World!\n\nCreate a home route view to say \"Hello World!\". It is used to test if things\nworking well.\n\n\n```python\n# website/routes.py\nfrom flask import Blueprint\nbp = Blueprint(__name__, 'home')\n\n@bp.route('/')\ndef home():\n    return 'Hello World!'\n```\n\n```python\n# website/app.py\nfrom flask import Flask\nfrom .routes import bp\n\ndef create_app(config=None):\n    app = Flask(__name__)\n    # load app sepcified configuration\n    if config is not None:\n        if isinstance(config, dict):\n            app.config.update(config)\n        elif config.endswith('.py'):\n            app.config.from_pyfile(config)\n    setup_app(app)\n    return app\n\ndef setup_app(app):\n    app.register_blueprint(bp, url_prefix='')\n```\n\n```python\n# app.py\nfrom website.app import create_app\n\napp = create_app({\n    'SECRET_KEY': 'secret',\n})\n```\n\nCreate an empty ```__init__.py``` file in the ```website``` folder.\n\nThe \"Hello World!\" example should run properly:\n\n    $ FLASK_APP=app.py flask run\n\n## Define Models\n\nWe will use SQLAlchemy and SQLite for our models. You can also use other\ndatabases and other ORM engines. Authlib has some built-in SQLAlchemy mixins\nwhich will make it easier for creating models.\n\nLet's create the models in `website/models.py`. We need four models, which are\n\n- User: you need a user to test and create your application\n- OAuth2Client: the oauth client model\n- OAuth2AuthorizationCode: for `grant_type=code` flow\n- OAuth2Token: save the `access_token` in this model.\n\nCheck how to define these models in `website/models.py`.\n\nOnce you've created your own `website/models.py` (or copied our version), you'll need to import the database object `db`. Add the line `from .models import db` just after `from flask import Flask` in your scratch-built version of `website/app.py`.\n\nTo initialize the database upon startup, if no tables exist, you'll add a few lines to the `setup_app()` function in `website/app.py` so that it now looks like:\n\n```python\ndef setup_app(app):\n    # Create tables if they do not exist already\n    @app.before_first_request\n    def create_tables():\n        db.create_all()\n\n    db.init_app(app)\n    app.register_blueprint(bp, url_prefix='')\n```\n\nYou can try running the app again as above to make sure it works.\n\n## Implement Grants\n\nThe source code is in `website/oauth2.py`. There are four standard grant types:\n\n- Authorization Code Grant\n- Implicit Grant\n- Client Credentials Grant\n- Resource Owner Password Credentials Grant\n\nAnd Refresh Token is implemented as a Grant in Authlib. You don't have to do\nanything on Implicit and Client Credentials grants, but there are missing\nmethods to be implemented in other grants. Check out the source code in\n`website/oauth2.py`.\n\nOnce you've created your own `website/oauth2.py`, import the oauth2 config object from the oauth2 module. Add the line `from .oauth2 import config_oauth` just after the import you added above in your scratch-built version of `website/app.py`.\n\nTo initialize the oauth object, add `config_oauth(app)` to the `setup_app()` function, just before the line that starts with `app.register_blueprint` so it looks like:\n\n```python\ndef setup_app(app):\n    # Create tables if they do not exist already\n    @app.before_first_request\n    def create_tables():\n        db.create_all()\n\n    db.init_app(app)\n    config_oauth(app)\n    app.register_blueprint(bp, url_prefix='')\n```\nYou can try running the app again as above to make sure it still works.\n\n## `@require_oauth`\n\nAuthlib has provided a `ResourceProtector` for you to create the decorator\n`@require_oauth`, which can be easily implemented:\n\n```py\nfrom authlib.flask.oauth2 import ResourceProtector\n\nrequire_oauth = ResourceProtector()\n```\n\nFor now, only Bearer Token is supported. Let's add bearer token validator to\nthis ResourceProtector:\n\n```py\nfrom authlib.flask.oauth2.sqla import create_bearer_token_validator\n\n# helper function: create_bearer_token_validator\nbearer_cls = create_bearer_token_validator(db.session, OAuth2Token)\nrequire_oauth.register_token_validator(bearer_cls())\n```\n\nCheck the full implementation in `website/oauth2.py`.\n\n\n## OAuth Routes\n\nFor OAuth server itself, we only need to implement routes for authentication,\nand issuing tokens. Since we have added token revocation feature, we need a\nroute for revoking too.\n\nCheckout these routes in `website/routes.py`. Their path begin with `/oauth/`.\n\n\n## Other Routes\n\nBut that is not enough. In this demo, you will need to have some web pages to\ncreate and manage your OAuth clients. Check that `/create_client` route.\n\nAnd we have an API route for testing. Check the code of `/api/me`.\n\n\n## Finish\n\nHere you go. You've got an OAuth 2.0 server.\n\nRead more information on \u003chttps://docs.authlib.org/\u003e.\n\n## License\n\nSame license with [Authlib](https://authlib.org/plans).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauthlib%2Fexample-oauth2-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fauthlib%2Fexample-oauth2-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fauthlib%2Fexample-oauth2-server/lists"}