CLI browser login
Sign the Masko CLI in through your browser instead of pasting an API key. Install it with the terminal quickstart; server integrations use API keys.
Sign in from the terminal
masko login # Open browser, approve, return automatically
masko login --no-browser # Open the printed URL yourself on this computer
masko login --device --no-browser # Device code for SSH or a remote terminal
masko login --scope read # Request read-only access
masko whoami # Account, workspace, access, credits
masko logout # End this CLI sessionSign in on Masko, choose the workspace and click Connect; the CLI completes sign-in with PKCE (Control+C cancels). Without server support for browser sign-in, it shows an error and never falls back to API-key login.
- Team authorization requires an owner or admin.
- Access tokens last 15 minutes; refresh tokens rotate automatically and are stored in macOS Keychain.
- Sessions last 90 days. See them, and sign one out, under Signed-in computers in Developers → API keys.
Choosing a workspace
Your choice (Personal workspace or a team) sets which projects, mascots, canvases, assets and jobs the session reaches and which balance pays. Run masko login again to switch; membership and project restrictions still apply.
IDs from another workspace return 404, as with API keys, while public mascot releases stay public. Unattached uploads, user templates, creator profiles and listings, and webhook registrations stay account-owned; source assets for mascot creation, references and template extraction must pass workspace checks.
An older CLI that gets 410 at login needs an update; API keys stay valid. MASKO_API_KEY overrides a saved session, and an invalid key fails rather than switching accounts. Save a key with masko login --api-key (asks for it) or --api-key-stdin.
masko logout removes the login on this Mac even when Masko cannot be reached; the session then stays valid until you sign it out under Signed-in computers.
Browser authorization (PKCE)
GET /v1/auth/config returns the authorization_endpoint and supported grants. The client masko-cli opens it with:
client_id=masko-cli,response_type=code,device_name, andscope=read|write.redirect_uri=http://127.0.0.1:PORT/oauth/callback, using a temporary local port between 1024 and 65535. Other hosts, paths, query strings and fragments are rejected.- Independent random
stateandcode_verifiervalues generated from 32 random bytes, base64url encoded. Send onlystate,code_challenge=BASE64URL(SHA256(code_verifier)), andcode_challenge_method=S256in the browser URL. Keep the verifier in memory.
After approval, check the exact callback path and state, then send client_id, grant_type: "authorization_code", code, the same redirect_uri and code_verifier as JSON to POST /v1/auth/token. Codes expire after 120 seconds and work once.
The callback never carries a token or API key. Cancelling returns error=access_denied with the original state; the CLI closes its listener on completion, cancellation or timeout (10 minutes at most).
Device-login REST contract
For masko login --device, when the browser runs on another computer:
POST /v1/auth/device:{ "client_id": "masko-cli", "device_name": "My Mac", "scope": "write" }. Returnsdevice_code,user_code,verification_uri,verification_uri_complete,expires_in(600 seconds), andinterval(5 seconds) underdata.POST /v1/auth/token: sendclient_id,grant_type: "urn:ietf:params:oauth:grant-type:device_code", anddevice_code. Poll at the returned interval: keep waiting onauthorization_pending, add 5 seconds to all later intervals onslow_down, and stop onaccess_denied,expired_tokenorinvalid_grant.- On success,
datacontainsaccess_token,refresh_token,token_type: "Bearer",expires_in,session_id, andsession_expires_at. Never log these tokens. - Refresh at the same endpoint with
client_id,grant_type: "refresh_token"andrefresh_token, one refresh at a time, replacing the pair securely. Reusing a consumed refresh token revokes the session; if a refresh response is lost, log in again. GET /v1/auth/sessionidentifies the current key or session without secrets.POST /v1/auth/revokewith{ "refresh_token": "..." }ends only that session, immediately and idempotently.
These endpoints use Masko's JSON bodies and {data} / {error} envelopes, not a general third-party OAuth server or form-encoded token endpoint. All auth responses are no-store, and masko-cli is the only registered client.
