# Muffin‑OAuth
**Muffin‑OAuth** adds OAuth 1 and 2 support to the Muffin\_ framework, enabling both client-side and server-side authentication flows.
[](https://github.com/klen/muffin-oauth/actions)
[](https://pypi.org/project/muffin-oauth/)
[](https://pypi.org/project/muffin-oauth/)
# Requirements
- Python >= 3.10
- Compatible with `asyncio`, `Trio`, and `Curio`
# Installation
Install via pip:
pip install muffin-oauth
# Usage
Here's a basic example using OAuth2:
```python
from muffin import Application
from muffin_oauth import OAuthPlugin
app = Application("auth-example")
oauth = OAuthPlugin()
oauth.setup(app, providers={
"github": {
"client_id": "...",
"client_secret": "...",
"authorize_url": "https://github.com/login/oauth/authorize",
"access_token_url": "https://github.com/login/oauth/access_token",
"api_base_url": "https://api.github.com"
}
})
@app.route("/")
async def login(request):
return await oauth.authorize_redirect(request, "github", redirect_uri="http://localhost:8000/callback")
@app.route("/callback")
async def callback(request):
token = await oauth.authorize_access_token(request, "github")
request.session["token"] = token
return "Logged in"
@app.route("/user")
async def user(request):
client = oauth.client("github", token=request.session.get("token"))
resp = await client.get("/user")
return resp.json()
```
Run the example app:
```bash
$ make example
http://localhost:5000
```
Client-side usage:
```python
client = oauth.client("github", access_token="...")
resp = await client.request("GET", "/user")
user_info = resp.json()
```
This supports both OAuth1 and OAuth2 flows, with automatic token handling and resource access via configured providers.
## Testing & Security
- Test coverage for major flows is provided in `tests.py`.
- Minimal dependencies and async-native design.
- Production-ready, MIT-licensed.
## Bug Tracker & Contributing
Found an issue or have an idea? Report it at:
https://github.com/klen/muffin-oauth/issues
Contributions welcome! Fork the repo and submit a PR.
## Contributors
- [klen](https://github.com/klen) (Kirill Klenov)
## License
Licensed under the [MIT license](http://opensource.org/licenses/MIT).
[Muffin]: https://github.com/klen/muffin
Raw data
{
"_id": null,
"home_page": "https://github.com/klen/muffin-oauth",
"name": "muffin-oauth",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "asgi, asyncio, authorization, muffin, oauth, trio",
"author": "Kirill Klenov",
"author_email": "horneds@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b1/f6/c7bd76dba88c8f978f8cededb42d9c328f4f9dbf977767398117baa10939/muffin_oauth-2.8.1.tar.gz",
"platform": null,
"description": "# Muffin\u2011OAuth\n\n**Muffin\u2011OAuth** adds OAuth 1 and 2 support to the Muffin\\_ framework, enabling both client-side and server-side authentication flows.\n\n[](https://github.com/klen/muffin-oauth/actions)\n[](https://pypi.org/project/muffin-oauth/)\n[](https://pypi.org/project/muffin-oauth/)\n\n# Requirements\n\n- Python >= 3.10\n- Compatible with `asyncio`, `Trio`, and `Curio`\n\n# Installation\n\nInstall via pip:\n\n pip install muffin-oauth\n\n# Usage\n\nHere's a basic example using OAuth2:\n\n```python\nfrom muffin import Application\nfrom muffin_oauth import OAuthPlugin\n\napp = Application(\"auth-example\")\noauth = OAuthPlugin()\noauth.setup(app, providers={\n \"github\": {\n \"client_id\": \"...\",\n \"client_secret\": \"...\",\n \"authorize_url\": \"https://github.com/login/oauth/authorize\",\n \"access_token_url\": \"https://github.com/login/oauth/access_token\",\n \"api_base_url\": \"https://api.github.com\"\n }\n})\n\n@app.route(\"/\")\nasync def login(request):\n return await oauth.authorize_redirect(request, \"github\", redirect_uri=\"http://localhost:8000/callback\")\n\n@app.route(\"/callback\")\nasync def callback(request):\n token = await oauth.authorize_access_token(request, \"github\")\n request.session[\"token\"] = token\n return \"Logged in\"\n\n@app.route(\"/user\")\nasync def user(request):\n client = oauth.client(\"github\", token=request.session.get(\"token\"))\n resp = await client.get(\"/user\")\n return resp.json()\n```\n\nRun the example app:\n\n```bash\n$ make example\nhttp://localhost:5000\n```\n\nClient-side usage:\n\n```python\nclient = oauth.client(\"github\", access_token=\"...\")\nresp = await client.request(\"GET\", \"/user\")\nuser_info = resp.json()\n```\n\nThis supports both OAuth1 and OAuth2 flows, with automatic token handling and resource access via configured providers.\n\n## Testing & Security\n\n- Test coverage for major flows is provided in `tests.py`.\n- Minimal dependencies and async-native design.\n- Production-ready, MIT-licensed.\n\n## Bug Tracker & Contributing\n\nFound an issue or have an idea? Report it at:\nhttps://github.com/klen/muffin-oauth/issues\n\nContributions welcome! Fork the repo and submit a PR.\n\n## Contributors\n\n- [klen](https://github.com/klen) (Kirill Klenov)\n\n## License\n\nLicensed under the [MIT license](http://opensource.org/licenses/MIT).\n\n[Muffin]: https://github.com/klen/muffin\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Support OAuth authentication for Muffin Framework.",
"version": "2.8.1",
"project_urls": {
"Homepage": "https://github.com/klen/muffin-oauth",
"Repository": "https://github.com/klen/muffin-oauth"
},
"split_keywords": [
"asgi",
" asyncio",
" authorization",
" muffin",
" oauth",
" trio"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "71e00d1213ca20b61a675f3dcf177ec396b1ad75a961a5f9862fb5065e8f8903",
"md5": "11d1188e57bf72cb40fe735d714833bb",
"sha256": "da6ecc7cc08641f69e40a9168f52db50959d9688913d77971b38d1a70d5f15a2"
},
"downloads": -1,
"filename": "muffin_oauth-2.8.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "11d1188e57bf72cb40fe735d714833bb",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 4839,
"upload_time": "2025-07-16T12:51:26",
"upload_time_iso_8601": "2025-07-16T12:51:26.000184Z",
"url": "https://files.pythonhosted.org/packages/71/e0/0d1213ca20b61a675f3dcf177ec396b1ad75a961a5f9862fb5065e8f8903/muffin_oauth-2.8.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b1f6c7bd76dba88c8f978f8cededb42d9c328f4f9dbf977767398117baa10939",
"md5": "a160e20b09a8e05a8eadd97293db7b52",
"sha256": "16fb4079541b754cb3f8f89a5ddd334993a616f74af7319e8f52c6409647a845"
},
"downloads": -1,
"filename": "muffin_oauth-2.8.1.tar.gz",
"has_sig": false,
"md5_digest": "a160e20b09a8e05a8eadd97293db7b52",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 4278,
"upload_time": "2025-07-16T12:51:26",
"upload_time_iso_8601": "2025-07-16T12:51:26.920237Z",
"url": "https://files.pythonhosted.org/packages/b1/f6/c7bd76dba88c8f978f8cededb42d9c328f4f9dbf977767398117baa10939/muffin_oauth-2.8.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-16 12:51:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "klen",
"github_project": "muffin-oauth",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "muffin-oauth"
}