If you've ever had to integrate an OAuth 2.0-protected third-party API into multiple projects, you know the drill: handle the authorization flow, store the tokens, track their expiration, build automatic refresh logic... and start over on every new project.
Asstgr is a self-hosted API gateway (Django + DRF) that centralizes all of this. The idea: you register a third-party API once in Asstgr, describe its endpoints, and then call it through a unified REST interface — Asstgr takes care of authentication, quota, and logging on your behalf.
In this article, we'll focus on one specific use case: how to connect an OAuth 2.0-protected API to Asstgr, and call it without ever handling a token by hand.
The concept
Your app ──► Asstgr (/api/v1/...execute/) ──► OAuth2-protected third-party API
│
├─ Auth (API Key or OAuth2)
├─ Quota
├─ Logs
└─ Response formatting
Your application only needs to know one thing: your Asstgr API key (sk-...). Asstgr internally handles all exchanges with the third-party API's OAuth server (fetching, caching, and refreshing tokens).
Supported flows
Asstgr supports the three most common OAuth 2.0 grants, with automatic token refresh:
client_credentials — for server-to-server integrations (the most common case)
authorization_code — for APIs requiring explicit user authorization
password — for legacy ROPC-based APIs
Step 1 — Register the API
We start like with any other API in Asstgr:
http
POST /api/v1/apis/
{
"name": "My Protected API",
"url": "https://api.example.com/v1",
"auth_required": true,
"quota_cost": 2
}
Step 2 — Configure OAuth 2.0
This is where it gets interesting. We attach an OAuth configuration to the API through the dedicated endpoint:
http
POST /api/v1/apis/{api_id}/oauth/
{
"grant_type": "client_credentials",
"token_url": "https://api.example.com/oauth/token",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"scope": "read write"
}
The client_secret is stored encrypted server-side (client_secret_encrypted in the database). Once this configuration is saved, Asstgr knows how to obtain a token for this API.
Checking token status
You can check at any time whether a valid token is currently cached:
http
GET /api/v1/apis/{api_id}/oauth/token/
Forcing a refresh
If needed (debugging, secret rotation on the provider's side, etc.), you can manually force a token refresh:
http
POST /api/v1/apis/{api_id}/oauth/token/
Under normal circumstances this isn't necessary: Asstgr's internal service (OAuthService) checks token expiration (token_expires_at) before every call and refreshes it automatically if needed, completely transparently.
Step 3 — Describe the endpoint and its parameters
Just like with a regular API, we add the endpoint and its parameters:
http
POST /api/v1/apis/{api_id}/endpoints/
{
"path": "/protected-resource",
"description": "OAuth2-protected resource"
}
http
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/parameters/
{
"name": "resource_id",
"param_type": "query",
"data_type": "STRING",
"required": true
}
http
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/methods/
{ "method": "GET" }
Step 4 — Execute the call
And here's the main payoff: from your application, a single call, using your Asstgr key — no OAuth token to manage:
http
POST /api/v1/apis/{api_id}/endpoints/{endpoint_id}/execute/
Authorization: Api-Key sk-xxxxxxxxxxxxxxxxxxxxxxxx
{
"method": "GET",
"params": { "resource_id": "42" },
"display_format": "standard"
}
Asstgr will, in order:
Verify your API key and remaining quota
Fetch (or refresh) the OAuth2 token associated with that third-party API
Build the actual HTTP request with that token in the Authorization header
Call the third-party API
Log the call (APILog: user, endpoint, method, status, response size)
Format and return the response
json
{
"status_code": 200,
"result": "...",
"quota": {
"used": 4,
"remaining": 96,
"limit": 100,
"usage_pct": 4.0
}
}
Why centralize this instead of handling OAuth in every service?
A single place to store secrets — your client_id / client_secret don't end up scattered across ten different microservices' codebases
Automatic, shared refresh — the token is cached and refreshed once, even if multiple services call the same API
Unified quota and logging — you know exactly who's calling what, and how much it costs in credits
Transparent provider changes — if the third-party API changes its token URL or scopes, there's only one place to update
Going further
Everything else (API keys, quotas, rate limiting, response formats) follows the same simple pattern: register declaratively once, then call it through /execute/.
The project is open source (Django 5.x + DRF, PostgreSQL):
👉 github.com/asstgr/asstgropensource
If you find the project useful, a ⭐ goes a long way, and you can follow updates on @asstgrio.
Top comments (0)