Skip to content

Authentication

cyber-asana accepts either a personal access token or an OAuth grant obtained through auth login.

Resolved in this order — the first one found wins:

  1. --token <token> on the command
  2. ASANA_ACCESS_TOKEN environment variable
  3. ASANA_TOKEN environment variable
  4. The stored OAuth credential from cyber-asana auth login

A personal access token is the simplest start — create one at app.asana.com → My Apps:

Terminal window
export ASANA_ACCESS_TOKEN="<pat>"
export ASANA_WORKSPACE="<workspace-gid>" # optional, saves --workspace-gid everywhere
Terminal window
cyber-asana auth status

Reports whether you are authenticated, which source won, the masked token, the account it belongs to, expiry if any, and which other credentials were shadowed — all without calling the Asana API. When nothing is configured it prints the two ways to fix that.

It also reports the app registration auth login would authorize with, which resolves from a separate chain — so a token that works says nothing about whether the registration is the right one:

Status authenticated
Source ASANA_TOKEN
Token …bbbb
App …cdef (ASANA_API_CLIENT_ID)
App ignored ASANA_CLIENT_ID

App names the masked client id and the source it came from; App ignored lists the registrations that source shadowed. With --json (or --toon) the same appears as an app object, null when no registration resolves:

{
"app": {
"client_id_masked": "…cdef",
"source": "ASANA_API_CLIENT_ID",
"shadowed": ["ASANA_CLIENT_ID"]
}
}
Terminal window
cyber-asana auth login
cyber-asana auth login --no-store --raw
cyber-asana auth logout

login opens the browser, listens on a loopback callback, and stores the credential locally. It runs against your own Asana app, which must be registered as an API app — tokens from an MCP app work only with Asana’s hosted MCP server.

Terminal window
export ASANA_API_CLIENT_ID="<client-id>"
export ASANA_API_CLIENT_SECRET="<client-secret>"
Option Command Description
--client-id <id> status, login, token, logout OAuth client ID — overrides ASANA_API_CLIENT_ID, ASANA_CLIENT_ID, and settings.json
--client-secret <secret> status, login, token, logout OAuth client secret (visible in shell history — prefer the env var)
--no-store login Print the token instead of saving it
--include-refresh-token login Also print the long-lived refresh token (implies --no-store)
--raw login Print only the token, for shell substitution
--scope <list> login Comma-separated scopes to request
--manual login Paste the code from the browser instead of listening for a redirect
--redirect-uri <uri> login Redirect URL registered for the app (default: the loopback URL)
--port <port> login Callback port
--local logout Delete local credentials without revoking the grant

Use --manual when you are on a remote or headless machine where the browser cannot reach the loopback listener.

The client id and secret resolve independently, in this order:

  1. --client-id / --client-secret on the command
  2. ASANA_API_CLIENT_ID / ASANA_API_CLIENT_SECRET environment variables
  3. ASANA_CLIENT_ID / ASANA_CLIENT_SECRET environment variables
  4. client_id / client_secret in ~/.config/cyber-asana/settings.json

ASANA_API_CLIENT_ID and ASANA_API_CLIENT_SECRET are names cyber-asana defines — they are not official Asana variables. They exist because Asana’s docs use ASANA_CLIENT_ID / ASANA_CLIENT_SECRET for the hosted MCP server’s MCP app, whose credentials do not work here; the prefixed pair lets both registrations coexist. ASANA_CLIENT_ID / ASANA_CLIENT_SECRET still work as a fallback.

Run auth status to see which of these won and which were shadowed. If an MCP app’s id reaches the token endpoint anyway, Asana answers with invalid_client, and cyber-asana appends a hint naming this distinction to Asana’s own message.

Terminal window
cyber-asana auth token

Prints the stored access token, refreshing it first when it is close to expiring. Useful for handing a fresh token to another tool:

Terminal window
curl -H "Authorization: Bearer $(cyber-asana auth token)" \
https://app.asana.com/api/1.0/users/me