{"id":48369718,"url":"https://github.com/mdfarhankc/fastapi-fullauth","last_synced_at":"2026-05-23T20:01:16.345Z","repository":{"id":349360049,"uuid":"1194441369","full_name":"mdfarhankc/fastapi-fullauth","owner":"mdfarhankc","description":"Production-grade, async-native authentication and authorization library for FastAPI.","archived":false,"fork":false,"pushed_at":"2026-05-19T11:33:35.000Z","size":1620,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T14:35:56.322Z","etag":null,"topics":["access-token","argon2","async","authentication","authorization","bcrypt","csrf","fastapi","fullauth","jwt","oauth","pydantic-v2","rbac","redis","refresh-token","security","sqlalchemy","sqlmodel","users"],"latest_commit_sha":null,"homepage":"https://mdfarhankc.github.io/fastapi-fullauth/","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/mdfarhankc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security/middleware.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-28T11:09:37.000Z","updated_at":"2026-05-19T11:33:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mdfarhankc/fastapi-fullauth","commit_stats":null,"previous_names":["mdfarhankc/fastapi-fullauth"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/mdfarhankc/fastapi-fullauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Ffastapi-fullauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Ffastapi-fullauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Ffastapi-fullauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Ffastapi-fullauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdfarhankc","download_url":"https://codeload.github.com/mdfarhankc/fastapi-fullauth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdfarhankc%2Ffastapi-fullauth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33410345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["access-token","argon2","async","authentication","authorization","bcrypt","csrf","fastapi","fullauth","jwt","oauth","pydantic-v2","rbac","redis","refresh-token","security","sqlalchemy","sqlmodel","users"],"created_at":"2026-04-05T16:01:44.513Z","updated_at":"2026-05-23T20:01:16.337Z","avatar_url":"https://github.com/mdfarhankc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.icons8.com/fluency/96/shield.png\" alt=\"FastAPI FullAuth\" width=\"96\" height=\"96\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eFastAPI FullAuth\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eProduction-grade, async-native authentication and authorization for FastAPI.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pypi.org/project/fastapi-fullauth/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/fastapi-fullauth?color=009688\u0026label=pypi\" alt=\"PyPI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://pypi.org/project/fastapi-fullauth/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/pyversions/fastapi-fullauth?color=009688\" alt=\"Python\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/mdfarhankc/fastapi-fullauth/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/mdfarhankc/fastapi-fullauth/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-009688\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://mdfarhankc.github.io/fastapi-fullauth\"\u003e\u003cimg src=\"https://img.shields.io/badge/docs-mdfarhankc.github.io-009688\" alt=\"Docs\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eDocumentation\u003c/strong\u003e: \u003ca href=\"https://mdfarhankc.github.io/fastapi-fullauth\"\u003ehttps://mdfarhankc.github.io/fastapi-fullauth\u003c/a\u003e\n  \u003cbr\u003e\n  \u003cstrong\u003eSource Code\u003c/strong\u003e: \u003ca href=\"https://github.com/mdfarhankc/fastapi-fullauth\"\u003ehttps://github.com/mdfarhankc/fastapi-fullauth\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nAdd a complete authentication and authorization system to your **FastAPI** project. FastAPI FullAuth is designed to be production-ready, async-native, and pluggable = handling JWT tokens, refresh rotation, password hashing, email verification, OAuth2 social login, and role-based access out of the box.\n\n## Features\n\n- **JWT access + refresh tokens** with configurable expiry\n- **Refresh token rotation** with reuse detection = revokes entire session family on replay\n- **Password hashing** via Argon2id (default) or bcrypt, with transparent rehashing\n- **Email verification** and **password reset** flows with event hooks\n- **Passkey (WebAuthn)** = passwordless login with fingerprint, Face ID, security keys\n- **OAuth2 social login** = Google and GitHub, with multi-redirect-URI support\n- **Role-based access control** = `CurrentUser`, `VerifiedUser`, `SuperUser`, `require_role()`\n- **Rate limiting** = per-route auth limits + global middleware (memory or Redis)\n- **CSRF protection** and **security headers** middleware, auto-wired\n- **Pluggable adapters** = SQLModel or SQLAlchemy\n- **Generic type parameters** = define your own schemas with full IDE support and type safety\n- **Composable routers** = include only the route groups you need\n- **Event hooks** = `after_register`, `after_login`, `send_verification_email`, etc.\n- **Custom JWT claims** = embed app-specific data in tokens\n- **Structured logging** = all auth events, security violations, and failures logged\n- **Redis support** = token blacklist and rate limiter backends\n- **Python 3.10 - 3.14** supported\n\n## Installation\n\n```bash\npip install fastapi-fullauth\n\n# with an ORM adapter\npip install fastapi-fullauth[sqlmodel]\npip install fastapi-fullauth[sqlalchemy]\n\n# with Redis for token blacklisting\npip install fastapi-fullauth[sqlmodel,redis]\n\n# with OAuth2 social login\npip install fastapi-fullauth[sqlmodel,oauth]\n\n# with passkey/WebAuthn\npip install fastapi-fullauth[sqlmodel,passkey]\n\n# everything\npip install fastapi-fullauth[all]\n```\n\n## Quick start\n\n```python\nfrom fastapi import FastAPI\nfrom sqlmodel import Field, Relationship\nfrom fastapi_fullauth import FullAuth, FullAuthConfig\nfrom fastapi_fullauth.adapters import SQLModelAdapter\nfrom fastapi_fullauth.models.sqlmodel import RefreshTokenMixin, UserMixin\n\n\nclass RefreshToken(RefreshTokenMixin, table=True):\n    pass\n\n\nclass User(UserMixin, table=True):\n    refresh_tokens: list[RefreshToken] = Relationship()\n\n\napp = FastAPI()\nfullauth = FullAuth(\n    adapter=SQLModelAdapter(\n        session_maker=session_maker,\n        user_model=User,\n        refresh_token_model=RefreshToken,\n    ),\n    config=FullAuthConfig(SECRET_KEY=\"your-secret-key\"),\n)\nfullauth.init_app(app)\n```\n\nThat's it = all auth routes are registered under `/api/v1/auth/` automatically.\n\nOmit `config` in dev and a random secret key is generated (tokens won't survive restarts).\n\n### Composable routers\n\nOpt in to a subset of routers:\n\n```python\nfullauth.init_app(app, include_routers=[\"auth\", \"profile\"])\n```\n\n`include_routers=None` (default) registers every available router. Or wire routers manually for full control:\n\n```python\napp = FastAPI()\nfullauth.bind(app)  # required for dependencies to work\n\napp.include_router(fullauth.auth_router, prefix=\"/api/v1/auth\")\napp.include_router(fullauth.profile_router, prefix=\"/api/v1/auth\")\n```\n\n| Router | Routes |\n|--------|--------|\n| `auth_router` | register, login, logout, refresh |\n| `profile_router` | me, verified-me, update profile, delete account, change password |\n| `verify_router` | email verification, password reset |\n| `admin_router` | assign/remove roles and permissions (superuser) |\n| `oauth_router` | OAuth provider routes (only if configured) |\n| `passkey_router` | Passkey register, authenticate, list, delete (only if enabled) |\n\n### Middleware\n\n`init_app()` does not wire any middleware automatically. Import what you want and add it yourself:\n\n```python\nfrom fastapi_fullauth.middleware import (\n    SecurityHeadersMiddleware,\n    CSRFMiddleware,\n    RateLimitMiddleware,\n)\n\napp.add_middleware(SecurityHeadersMiddleware)\napp.add_middleware(CSRFMiddleware, secret=fullauth.config.CSRF_SECRET or fullauth.config.SECRET_KEY)\napp.add_middleware(RateLimitMiddleware, max_requests=60, window_seconds=60)\n```\n\n## Routes\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `POST` | `/auth/register` | Create a new user |\n| `POST` | `/auth/login` | Authenticate, get tokens |\n| `POST` | `/auth/logout` | Blacklist token |\n| `POST` | `/auth/refresh` | Rotate token pair |\n| `GET` | `/auth/me` | Get current user |\n| `GET` | `/auth/me/verified` | Verified users only |\n| `PATCH` | `/auth/me` | Update profile |\n| `DELETE` | `/auth/me` | Delete account |\n| `POST` | `/auth/change-password` | Change password |\n| `POST` | `/auth/verify-email/request` | Request verification email |\n| `POST` | `/auth/verify-email/confirm` | Confirm email |\n| `POST` | `/auth/password-reset/request` | Request password reset |\n| `POST` | `/auth/password-reset/confirm` | Reset password |\n| `POST` | `/auth/admin/assign-role` | Assign role (superuser) |\n| `POST` | `/auth/admin/remove-role` | Remove role (superuser) |\n| `POST` | `/auth/admin/assign-permission` | Assign permission to role (superuser) |\n| `POST` | `/auth/admin/remove-permission` | Remove permission from role (superuser) |\n| `GET` | `/auth/admin/role-permissions/{role}` | List role's permissions (superuser) |\n\nWith OAuth enabled, additional routes are registered under `/auth/oauth/`. All routes are prefixed with `/api/v1` by default.\n\n## Custom user schemas\n\nCombine each mixin with `table=True` (or your `DeclarativeBase` for the SQLAlchemy adapter), then pass everything to the adapter:\n\n```python\nfrom sqlmodel import Field, Relationship\nfrom fastapi_fullauth import FullAuth, FullAuthConfig, UserSchema, CreateUserSchema\nfrom fastapi_fullauth.adapters import SQLModelAdapter\nfrom fastapi_fullauth.models.sqlmodel import (\n    RefreshTokenMixin, RoleMixin, UserMixin, UserRoleMixin,\n)\n\n\nclass RefreshToken(RefreshTokenMixin, table=True): pass\nclass Role(RoleMixin, table=True): pass\nclass UserRole(UserRoleMixin, table=True): pass\n\n\nclass User(UserMixin, table=True):\n    display_name: str = Field(default=\"\", max_length=100)\n    phone: str = Field(default=\"\", max_length=20)\n    roles: list[Role] = Relationship(link_model=UserRole)\n    refresh_tokens: list[RefreshToken] = Relationship()\n\n\nclass MyUserSchema(UserSchema):\n    display_name: str = \"\"\n    phone: str = \"\"\n\n\nclass MyCreateSchema(CreateUserSchema):\n    display_name: str = \"\"\n\n\nfullauth = FullAuth(\n    adapter=SQLModelAdapter(\n        session_maker,\n        user_model=User,\n        refresh_token_model=RefreshToken,\n        role_model=Role,\n        user_role_model=UserRole,\n        user_schema=MyUserSchema,\n        create_user_schema=MyCreateSchema,\n    ),\n    config=FullAuthConfig(SECRET_KEY=\"...\"),\n)\n```\n\nFull IDE autocompletion and type checking on custom fields. Use `get_current_user_dependency()` for typed dependencies:\n\n```python\nfrom typing import Annotated\nfrom fastapi import Depends\nfrom fastapi_fullauth.dependencies import get_current_user_dependency\n\nMyCurrentUser = Annotated[MyUserSchema, Depends(get_current_user_dependency(MyUserSchema))]\n\n@app.get(\"/profile\")\nasync def profile(user: MyCurrentUser):\n    return {\"name\": user.display_name}  # IDE knows this field exists\n```\n\n## Protected routes\n\n```python\nfrom fastapi import Depends\nfrom fastapi_fullauth.dependencies import CurrentUser, VerifiedUser, SuperUser, require_role\n\n@app.get(\"/profile\")\nasync def profile(user: CurrentUser):\n    return user\n\n@app.get(\"/dashboard\")\nasync def dashboard(user: VerifiedUser):\n    return {\"email\": user.email}\n\n@app.delete(\"/admin/users/{id}\")\nasync def delete_user(user: SuperUser):\n    ...\n\n@app.get(\"/editor\")\nasync def editor_panel(user=Depends(require_role(\"editor\"))):\n    ...\n```\n\n## OAuth2 social login\n\n```python\nfrom fastapi_fullauth import FullAuth, FullAuthConfig\nfrom fastapi_fullauth.oauth.google import GoogleOAuthProvider\nfrom fastapi_fullauth.oauth.github import GitHubOAuthProvider\n\nfullauth = FullAuth(\n    adapter=adapter,\n    config=FullAuthConfig(SECRET_KEY=\"...\"),\n    providers=[\n        GoogleOAuthProvider(\n            client_id=\"your-google-client-id\",\n            client_secret=\"your-google-secret\",\n            redirect_uris=[\n                \"http://localhost:3000/auth/callback\",\n                \"https://myapp.com/auth/callback\",\n            ],\n        ),\n        GitHubOAuthProvider(\n            client_id=\"your-github-client-id\",\n            client_secret=\"your-github-secret\",\n            redirect_uris=[\"http://localhost:3000/auth/callback\"],\n        ),\n    ],\n)\n```\n\nRequires `httpx`: `pip install fastapi-fullauth[oauth]`\n\n## Event hooks\n\n```python\nasync def welcome(user):\n    await send_email(user.email, \"Welcome!\")\n\nasync def send_verify(email, token):\n    await send_email(email, f\"Verify: https://myapp.com/verify?token={token}\")\n\nfullauth.hooks.on(\"after_register\", welcome)\nfullauth.hooks.on(\"send_verification_email\", send_verify)\n```\n\nEvents: `after_register`, `after_login`, `after_logout`, `after_password_change`, `after_password_reset`, `after_email_verify`, `send_verification_email`, `send_password_reset_email`, `after_oauth_login`\n\n## Configuration\n\nPass a `FullAuthConfig` object or set env vars with `FULLAUTH_` prefix.\n\n```python\nfullauth = FullAuth(\n    adapter=adapter,\n    config=FullAuthConfig(\n        SECRET_KEY=\"...\",\n        ACCESS_TOKEN_EXPIRE_MINUTES=60,\n        API_PREFIX=\"/api/v2\",\n        LOGIN_FIELD=\"username\",\n        PASSWORD_HASH_ALGORITHM=\"bcrypt\",\n        BLACKLIST_BACKEND=\"redis\",\n        REDIS_URL=\"redis://localhost:6379/0\",\n        AUTH_RATE_LIMIT_ENABLED=True,\n        TRUSTED_PROXY_HEADERS=[\"X-Forwarded-For\"],\n    ),\n)\n```\n\nSee [Configuration docs](https://mdfarhankc.github.io/fastapi-fullauth/configuration/) for all options.\n\n## AI-friendly docs\n\nUsing an AI coding assistant? Point it at our LLM-optimized docs:\n\n- **[llms.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms.txt)** = concise overview with links to all doc pages\n- **[llms-full.txt](https://mdfarhankc.github.io/fastapi-fullauth/llms-full.txt)** = full documentation in a single file\n\nWorks with Claude, Cursor, Copilot, and any tool that accepts a docs URL.\n\n## Development\n\n```bash\ngit clone https://github.com/mdfarhankc/fastapi-fullauth.git\ncd fastapi-fullauth\nuv sync --dev --extra sqlalchemy --extra sqlmodel\nuv run pytest tests/ -v\n\n# run examples\nuv run uvicorn examples.sqlmodel_app.main:app --reload\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdfarhankc%2Ffastapi-fullauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdfarhankc%2Ffastapi-fullauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdfarhankc%2Ffastapi-fullauth/lists"}