Asana Auth
AsanaAuthProvider exchanges OAuth tokens or personal access tokens for the Asana provider.
App Credentials
| Field | Default | Env keys | Notes |
|---|---|---|---|
authorization_url |
https://app.asana.com/-/oauth_authorize |
ASANA_AUTHORIZATION_URL, ASANA_AUTHORIZE_URL |
Override when using a self-hosted OAuth screen. |
token_url |
https://app.asana.com/-/oauth_token |
ASANA_TOKEN_URL, ASANA_ACCESS_TOKEN_URL |
Exchange endpoint for OAuth2. |
client_id |
None |
ASANA_CLIENT_ID |
OAuth client ID. |
client_secret |
None |
ASANA_CLIENT_SECRET |
OAuth client secret. |
redirect_uri |
None |
ASANA_REDIRECT_URI |
Optional redirect override. |
token |
None |
ASANA_ACCESS_TOKEN, ASANA_PERSONAL_ACCESS_TOKEN, ASANA_TOKEN |
Personal access token fallback when skipping OAuth. |
default_scope |
None |
— | Comma/space separated scopes or a sequence. |
workspace_gid |
None |
ASANA_WORKSPACE_GID, ASANA_WORKSPACE |
Default workspace to inject into settings. |
User Credentials
Tokens are stored as AsanaUserCredentials:
| Field | Type | Default |
|---|---|---|
access_token |
str |
— |
token_type |
str |
"Bearer" |
refresh_token |
str or None |
None |
scope |
tuple[str, ...] or None |
None |
expires_in |
int or None |
None |
expires_at |
float or None |
None |
id_token |
str or None |
None |
raw |
dict[str, Any] |
{} |
workspace_gid |
str or None |
None |
Persist them with AuthManager.store_credentials or pass them via with_credentials.
OAuth Flow
from integrations.auth import AuthManager
auth = AuthManager(asana={"client_id": "...", "client_secret": "..."})
flow = auth.asana.oauth2
# Step 1: send the user through Asana's consent screen
step = await flow.authorize(state="example-state")
# Step 2: exchange the code for a token
token = await flow.exchange(code="authorization-code", subject="user-123")
await auth.store_credentials("asana", "user-123", token)
# Step 3: build a session with hydrated Asana settings
async with auth.session(subject="user-123") as integrations:
await integrations.asana.get_user("me")
The binding prefers stored OAuth tokens but will fall back to the app-level personal access token when present.