CLI browser login
For server-side REST integrations, start with API keys and workspaces. This guide covers the first-party CLI login and its authorization endpoints. Install the CLI using the terminal quickstart.
Sign in from the terminal
The CLI browser flow is implemented in the developer preview. Production requires the matching backend deployment. If the server does not support browser sign-in, the CLI explains the error. It never silently changes to API-key login.
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 --json # Account, workspace, permissions, credits
masko logout # End this CLI sessionSign in on Masko, choose the workspace, and click Connect. The browser returns a one-time code to the CLI, which completes sign-in using PKCE. No API key needs to be created or pasted. Press Control+C to cancel. Team authorization requires an owner or admin. Access tokens expire after 15 minutes; refresh tokens rotate automatically and are stored in macOS Keychain. Sessions expire after 90 days. Manage individual installations from CLI sessions.
Choosing a workspace
Choose Personal workspace or a team in the browser when running masko login.
That choice determines which projects, collections, mascots, assets and jobs the
session can access, and which credit balance pays for generation. Run masko login
again and select another workspace to change the terminal's saved login.
Team authorization requires an owner or admin. Account membership and project
access restrictions still apply after login.
A resource ID from another workspace returns 404, even if your account belongs
to both workspaces. API keys follow the same rule: use a key issued for the target
workspace. Public mascot releases remain publicly accessible. Unattached uploads,
user templates, creator profiles/listings and webhook registrations retain their
account-level ownership. Source assets for collection creation, reference
attachments and template extraction must pass the workspace access checks.
The legacy /api/auth/cli callback flow has been retired and returns 410 with
instructions to update Masko and run masko login. Existing API keys remain valid.
The current browser flow never sends a reusable credential in a redirect URL.
MASKO_API_KEY takes precedence over a saved browser session. An invalid explicit
key fails instead of falling back to a different account. To save a key explicitly,
use masko login --api-key or masko login --api-key-stdin.
Browser authorization (PKCE)
GET /v1/auth/config returns the browser authorization_endpoint and supported
grants. The registered client masko-cli opens that endpoint 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 browser approval, check the exact callback path and state, then exchange
code at POST /v1/auth/token with a JSON body containing client_id,
grant_type: "authorization_code", code, the same redirect_uri, and
code_verifier. Authorization codes expire after 120 seconds and can be used once.
The callback contains no access token, refresh token, or API key. Cancellation
returns error=access_denied with the original state. The CLI closes its listener
on completion, cancellation, or timeout (at most 10 minutes).
Device-login REST contract
Use this flow 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 only at the returned interval.authorization_pendingmeans keep waiting;slow_downmeans add 5 seconds to all subsequent intervals. Stop onaccess_denied,expired_token, orinvalid_grant.- On success,
datacontainsaccess_token,refresh_token,token_type: "Bearer",expires_in,session_id, andsession_expires_at. Never log these tokens. - Refresh through the same endpoint with
client_id,grant_type: "refresh_token", andrefresh_token. Serialize refreshes and securely replace the pair. Reusing a consumed refresh token revokes that session. If a refresh response is lost, log in again. GET /v1/auth/sessionidentifies the current API key or session without returning secrets.POST /v1/auth/revokewith{ "refresh_token": "..." }ends that session immediately. This operation is idempotent and does not revoke other sessions or API keys.
These endpoints use Masko's JSON request bodies and {data} / {error} envelopes,
with authorization-code/PKCE and device-grant semantics. They are not a general third-party OAuth authorization
server or a form-encoded OAuth token endpoint. All auth responses use no-store.
The only registered client is masko-cli; never embed a developer key in an app.