JWT auth for HawkAPI — access + refresh tokens, password hashing, DI guards
Project description
hawkapi-auth
JWT auth for HawkAPI. Access + refresh tokens, argon2id password hashing, DI guards, scope-based access control.
Install
pip install hawkapi-auth
Quickstart
from hawkapi import Depends, HawkAPI, HTTPException
from hawkapi_auth import (
JWTConfig,
hash_password,
init_auth,
random_secret,
requires_user,
verify_password,
)
app = HawkAPI()
init_auth(app, config=JWTConfig(secret=random_secret()))
@app.post("/register")
async def register(email: str, password: str):
await db.create_user(email=email, password_hash=hash_password(password))
return {"ok": True}
@app.post("/login")
async def login(email: str, password: str):
user = await db.find_user(email)
if not user or not verify_password(password, user.password_hash):
raise HTTPException(401, detail="Invalid credentials")
issuer = app.state.auth
return {
"access_token": issuer.issue_access(user.id),
"refresh_token": issuer.issue_refresh(user.id),
}
@app.get("/me")
async def me(user_id: str = Depends(requires_user)):
return await db.fetch_user(user_id)
Token issue / verify
issuer = app.state.auth # TokenIssuer
access = issuer.issue_access("user-1", role="admin", scope="read write")
refresh = issuer.issue_refresh("user-1")
claims = issuer.verify_access(access) # raises TokenError on bad token
claims = issuer.verify_refresh(refresh) # ditto, plus checks the token type
issue_access / issue_refresh accept arbitrary keyword claims (role, scope, anything JSON-serialisable).
JWTConfig
JWTConfig(
secret="…", # HMAC secret for HS256/384/512
algorithm="HS256",
access_ttl_seconds=15 * 60,
refresh_ttl_seconds=30 * 24 * 60 * 60,
issuer="my-service", # optional iss claim
audience="my-api", # optional aud claim
private_key="", # RS*/ES* — PEM
public_key="",
)
Use random_secret() to mint one. Store it outside of git.
DI guards
from hawkapi_auth import requires_user, requires_claims, requires_scopes
@app.get("/me")
async def me(user_id: str = Depends(requires_user)):
...
@app.get("/dump")
async def dump(claims: dict = Depends(requires_claims)):
...
@app.get("/admin", dependencies=[Depends(requires_scopes("admin"))])
async def admin():
...
requires_scopes(*scopes) expects either a space-separated scope claim or a list under scope / scopes. Missing scopes → 403.
Refresh + revocation
from hawkapi_auth import RevocationList
rev = RevocationList()
init_auth(app, config=JWTConfig(secret=...), revocation=rev)
@app.post("/refresh")
async def refresh(refresh_token: str):
issuer = app.state.auth
claims = issuer.verify_refresh(refresh_token)
return {"access_token": issuer.issue_access(claims["sub"])}
@app.post("/logout")
async def logout(refresh_token: str):
app.state.auth.revoke_refresh(refresh_token)
return {"ok": True}
RevocationList is in-memory only. For multi-process deployments, swap in a Redis-backed implementation (planned in v0.2.0).
Password hashing
from hawkapi_auth import hash_password, verify_password, needs_rehash
h = hash_password("hunter2") # argon2id
ok = verify_password("hunter2", h) # constant-time, returns bool
if needs_rehash(h):
h = hash_password("hunter2") # re-hash after a successful login
verify_password never raises — safe to use directly in handler bodies.
What's not included (v0.2.0 roadmap)
- Social OAuth providers (Google / GitHub / Discord / Microsoft).
- Email-based password reset + verification flows.
- Pre-built user model and storage.
- Redis-backed
RevocationList.
Development
git clone https://github.com/ashimov/hawkapi-auth.git
cd hawkapi-auth
uv sync --extra dev
uv run pytest -q
uv run ruff check . && uv run ruff format --check .
uv run pyright src/
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hawkapi_auth-0.2.0.tar.gz.
File metadata
- Download URL: hawkapi_auth-0.2.0.tar.gz
- Upload date:
- Size: 29.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d286082645f9b043dc1e3116a851aa7f08ab15907c683a9ebdf37a0c701af392
|
|
| MD5 |
2dcf4357d0d937546e13004fff2f2e4e
|
|
| BLAKE2b-256 |
4c5d9370b43c13e64db75c495d2f09422538c6bfa33e43f8f60ecb2b3d73d36c
|
Provenance
The following attestation bundles were made for hawkapi_auth-0.2.0.tar.gz:
Publisher:
release.yml on ashimov/hawkapi-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hawkapi_auth-0.2.0.tar.gz -
Subject digest:
d286082645f9b043dc1e3116a851aa7f08ab15907c683a9ebdf37a0c701af392 - Sigstore transparency entry: 1553516708
- Sigstore integration time:
-
Permalink:
ashimov/hawkapi-auth@c4aebd0fc27755798049885a23b7ab090484b221 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ashimov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c4aebd0fc27755798049885a23b7ab090484b221 -
Trigger Event:
release
-
Statement type:
File details
Details for the file hawkapi_auth-0.2.0-py3-none-any.whl.
File metadata
- Download URL: hawkapi_auth-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1fe78e4e3a1cf404c5b680415fa7f27b82170a1d179b4f1829e75ad7367af9b0
|
|
| MD5 |
4fd7d6fbaf92bb6f154527ec5d954033
|
|
| BLAKE2b-256 |
3409d7fe968696574c639f0669f7315cee054f66789db6bf942c9436bef3adfc
|
Provenance
The following attestation bundles were made for hawkapi_auth-0.2.0-py3-none-any.whl:
Publisher:
release.yml on ashimov/hawkapi-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hawkapi_auth-0.2.0-py3-none-any.whl -
Subject digest:
1fe78e4e3a1cf404c5b680415fa7f27b82170a1d179b4f1829e75ad7367af9b0 - Sigstore transparency entry: 1553516726
- Sigstore integration time:
-
Permalink:
ashimov/hawkapi-auth@c4aebd0fc27755798049885a23b7ab090484b221 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/ashimov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c4aebd0fc27755798049885a23b7ab090484b221 -
Trigger Event:
release
-
Statement type: