Professional OneID integration package for FastAPI applications
Project description
fastapi-oneid
fastapi-oneid is a reusable FastAPI package for integrating with Uzbekistan OneID SSO using the official OneID OAuth2 flow. The package handles authorization URL generation, state protection, token exchange, user-info lookup, and optional logout, while your application remains responsible for local user mapping and JWT or session issuance.
Installation
pip install fastapi-oneid
For local development:
pip install -e .[dev]
Environment Settings
The package reads configuration from environment variables.
| Variable | Required | Description |
|---|---|---|
ONE_ID_SSO_URL |
Yes | OneID authorization and token endpoint, usually https://sso.egov.uz/sso/oauth/Authorization.do |
ONE_ID_CLIENT_ID |
Yes | OneID client identifier |
ONE_ID_CLIENT_SECRET |
Yes | OneID client secret |
ONE_ID_SCOPE |
Yes | OneID scope provided by the operator |
ONE_ID_ALLOWED_REDIRECT_URIS |
Yes | JSON array or comma-separated list of allowed redirect URIs |
ONE_ID_DEFAULT_REDIRECT_URI |
Yes | Default redirect URI, must be included in the allow-list |
ONE_ID_TIMEOUT |
No | Upstream request timeout in seconds. Default: 5.0 |
ONE_ID_DEBUG |
No | If true, raw OneID payloads may be returned when no handler is configured. Default: false |
Example .env:
ONE_ID_SSO_URL=https://sso.egov.uz/sso/oauth/Authorization.do
ONE_ID_CLIENT_ID=myportal
ONE_ID_CLIENT_SECRET=super-secret
ONE_ID_SCOPE=myportal
ONE_ID_ALLOWED_REDIRECT_URIS=["https://backend.example.com/one-id/access","https://frontend.example.com/auth/oneid/callback"]
ONE_ID_DEFAULT_REDIRECT_URI=https://backend.example.com/one-id/access
ONE_ID_TIMEOUT=5.0
ONE_ID_DEBUG=false
Official OneID Grant Values
The package uses the OneID values required by the official technological guide:
- Authorization request:
response_type=one_code - Token exchange:
grant_type=one_authorization_code - User info request:
grant_type=one_access_token_identify - Logout request:
grant_type=one_log_out
Redirect URI Whitelist
OneID redirect URIs are not accepted freely from the client. Every requested redirect URI must:
- be present in
ONE_ID_ALLOWED_REDIRECT_URIS - be an absolute HTTP(S) URL
- not use
localhost,127.0.0.1,::1, or other loopback hosts
The package also binds each generated OAuth state to the selected redirect URI. During callback and token exchange, the same redirect URI must be used again or the request is rejected.
Quick Start
from fastapi import FastAPI, Request
from fastapi_oneid import OneIDAuthPayload, create_api_router, create_web_router
app = FastAPI(title="My OneID Integration")
async def auth_handler(payload: OneIDAuthPayload, request: Request) -> dict:
# 1. Find or create your local user
# 2. Issue your own JWT or session
# 3. Return the response expected by your frontend
return {
"token": "project-jwt",
"user": {
"pin": payload.user.pin,
"full_name": payload.user.full_name,
},
}
app.include_router(create_web_router(handler=auth_handler))
app.include_router(create_api_router(handler=auth_handler))
Web Flow Example
Default web endpoints:
GET /one-id/loginGET /one-id/access
Flow:
- User opens
/one-id/login - Package validates the redirect URI and generates a single-use
state - User is redirected to OneID
- OneID redirects back to
/one-id/access?code=...&state=... - Package verifies
state, exchangescodeforaccess_token, fetches user info, and passes the result to your handler
Example login URL:
GET /one-id/login
Optional alternative redirect URI from the whitelist:
GET /one-id/login?redirect_uri=https://frontend.example.com/auth/oneid/callback
API Flow Example
Default API endpoints:
GET /api/one-id/urlPOST /api/one-id/url(compatibility alias)GET /api/one-id/accessPOST /api/one-id/tokenPOST /api/one-id/logout
Flow:
- Frontend requests
/api/one-id/url - Backend returns a OneID authorization URL with a generated
state - Frontend redirects the user to OneID
- OneID redirects to the registered callback URI with
codeandstate - Frontend sends
codeandstateto/api/one-id/token - Package verifies the stored
state, resolves the OneID user, and calls your handler
Requesting the authorization URL:
curl "https://backend.example.com/api/one-id/url?redirect_uri=https://frontend.example.com/auth/oneid/callback"
Exchanging the callback code:
curl -X POST "https://backend.example.com/api/one-id/token" \
-H "Content-Type: application/json" \
-d '{
"code": "oneid-returned-code",
"state": "oneid-returned-state",
"redirect_uri": "https://frontend.example.com/auth/oneid/callback"
}'
The optional redirect_uri on /api/one-id/token is validated against the state-bound redirect URI. If it does not match, the request is rejected.
Handler Example
Your handler receives a typed OneIDAuthPayload and the FastAPI Request.
from fastapi import Request
from fastapi_oneid import OneIDAuthPayload
async def auth_handler(payload: OneIDAuthPayload, request: Request) -> dict:
user = payload.user
return {
"token": "project-jwt",
"profile": {
"pin": user.pin,
"full_name": user.full_name,
"is_validated": user.valid,
},
}
The package does not create users, issue JWTs, or manage sessions automatically.
Logout Example
Low-level client usage:
from fastapi_oneid import OneIDClient, OneIDSettings
client = OneIDClient(settings=OneIDSettings())
logout_response = await client.logout("access-token")
Router usage:
curl -X POST "https://backend.example.com/api/one-id/logout" \
-H "Content-Type: application/json" \
-d '{"access_token": "oneid-access-token"}'
Production Security Notes
stateis generated per login request and verified during callback and token exchange.- Raw token payloads are not returned by default. They are only exposed when
ONE_ID_DEBUG=trueand no handler is configured. client_secretandaccess_tokenshould never be logged by your application.- Package-level timeout defaults to 5 seconds to match the official operational guideline.
- Configure application-level rate limiting or gateway protection in production.
- The OneID guide recommends not exceeding
300 requests per minute. - Use HTTPS public domains for registered redirect URIs. Do not rely on
localhost.
Testing
Run the unit tests:
python -m pytest -v
The tests mock OneID responses and cover the official grant types, redirect URI whitelist validation, state verification, typed user parsing, logout, and safe default handler behavior.
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 fastapi_oneid-0.2.0.tar.gz.
File metadata
- Download URL: fastapi_oneid-0.2.0.tar.gz
- Upload date:
- Size: 13.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fe8b296dcba667a9a1272ebf2d271ffd6798ba7ce09202680606f1edbb6667d
|
|
| MD5 |
431ba5f81c6a436f128d263ade1179c4
|
|
| BLAKE2b-256 |
3ad93e3c5bbfe351afc89c4c3253c8000dcc95ef01d61612a86baaad83c1147c
|
Provenance
The following attestation bundles were made for fastapi_oneid-0.2.0.tar.gz:
Publisher:
workflow.yml on lochinbekdev/fastapi-oneid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_oneid-0.2.0.tar.gz -
Subject digest:
3fe8b296dcba667a9a1272ebf2d271ffd6798ba7ce09202680606f1edbb6667d - Sigstore transparency entry: 1396667464
- Sigstore integration time:
-
Permalink:
lochinbekdev/fastapi-oneid@324ca576d9db8a5b9332f8424318bc4c2adeb00b -
Branch / Tag:
refs/heads/master - Owner: https://github.com/lochinbekdev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@324ca576d9db8a5b9332f8424318bc4c2adeb00b -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file fastapi_oneid-0.2.0-py3-none-any.whl.
File metadata
- Download URL: fastapi_oneid-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.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 |
e8aba8e94d3bd6fdf3bd1cfb0bd44c6868778a998e8c7d8c84cbf00a26ddf629
|
|
| MD5 |
946b5d3ad790c03a73ee49682bf76e62
|
|
| BLAKE2b-256 |
783c8fa8fa30f49c631dd352a0e9576a189ce10d848f2f757d65f2e768bff24d
|
Provenance
The following attestation bundles were made for fastapi_oneid-0.2.0-py3-none-any.whl:
Publisher:
workflow.yml on lochinbekdev/fastapi-oneid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fastapi_oneid-0.2.0-py3-none-any.whl -
Subject digest:
e8aba8e94d3bd6fdf3bd1cfb0bd44c6868778a998e8c7d8c84cbf00a26ddf629 - Sigstore transparency entry: 1396667469
- Sigstore integration time:
-
Permalink:
lochinbekdev/fastapi-oneid@324ca576d9db8a5b9332f8424318bc4c2adeb00b -
Branch / Tag:
refs/heads/master - Owner: https://github.com/lochinbekdev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@324ca576d9db8a5b9332f8424318bc4c2adeb00b -
Trigger Event:
workflow_dispatch
-
Statement type: