Authentication
Device code flow (RFC 8628), API tokens, token scopes, and web OAuth on mog.md.
mog uses two authentication systems: the web app uses OAuth (GitHub/Google) via NextAuth, while the CLI and API use a device code flow designed for headless environments and autonomous agents.
Device code flow (CLI & API)
The device code flow follows RFC 8628. It lets a CLI or agent authenticate without ever opening a browser on the host machine — ideal for CI, Docker containers, and agent runners.
How it works
- The CLI calls
POST /v1/auth/device/start— no credentials needed. The API returns adeviceCode(used internally), a shortuserCode(shown to the user), averificationUri, and a pollinginterval. - The CLI displays the code and URL to the user. It tries to open the browser automatically, but this is best-effort (it's fine if the environment is headless).
- The user opens
mog.md/devicein any browser, signs in with GitHub or Google, and enters the code. - The CLI polls
POST /v1/auth/device/polleveryintervalseconds. When the user approves, the poll response includes a Bearer token. - The CLI stores the token locally and uses it for all future API requests.
Flow diagram
CLI API Browser
| | |
|-- POST /auth/device/start ->| |
|<-- { deviceCode, userCode } | |
| | |
| (display userCode to user) | |
| | |
|-- poll /auth/device/poll -->| user visits /device |
|<-- { status: pending } |<-- POST /auth/device/approve |
| | { userCode } |
|-- poll /auth/device/poll -->| |
|<-- { status: approved, | |
| token: "mog_..." } | |
Code expiry
Device codes expire after 15 minutes (expiresIn: 900). If the user doesn't approve in time, the poll returns { "status": "expired" } and the CLI exits with an error. Run mog auth again to start a new flow.
API tokens
Tokens returned by the device flow are API tokens. They are stored as SHA-256 hashes in the database — the plaintext token is only returned once, at issuance time. Store it securely.
Token format
Tokens come in two forms:
- Signed JWT-like tokens: Created by the device flow. Verified by HMAC using the
JWT_SECRET. - API tokens: Created from the dashboard. Stored hashed in the database and looked up on each request.
Using a token
Authorization: Bearer mog_your_token_here
All protected API endpoints accept this header.
Token scopes
Tokens have one or more scopes that limit what they can do. The device flow issues tokens with all scopes by default; tokens created from the dashboard can be restricted.
| Scope | Grants access to |
|---|---|
read | GET /v1/users/me, GET /v1/entitlements, POST /v1/listings/.../reviews |
purchase | POST /v1/purchases |
download | POST /v1/downloads |
sell | All /v1/vendor/* endpoints |
For an autonomous agent that only needs to install packages, you can restrict the token to read, purchase, and download scopes — preventing it from uploading new releases or modifying vendor settings even if compromised.
Revoking a token
# Via CLI
mog auth --logout
# Via API
POST /v1/auth/token/revoke
Authorization: Bearer <token>
→ { "ok": true }
Revocation is immediate. Any subsequent request with the revoked token returns HTTP 401.
Spend policies on tokens
API tokens can be attached to a spend policy that limits autonomous purchasing. This is the recommended setup for agent tokens:
- Create a spend policy in your dashboard
- Create or update an API token, attaching the policy ID
- Give the token to the agent
The policy is enforced server-side on every purchase request made with that token, regardless of what the client sends.
Web app authentication
The web app at mog.md uses Auth.js v5 (NextAuth) with OAuth providers:
- GitHub: OAuth app, callback URL:
https://mog.md/api/auth/callback/github - Google: OAuth client, callback URL:
https://mog.md/api/auth/callback/google
Web sessions are separate from API tokens. When you sign in to the web app, the web app internally issues an API token on your behalf for browser-based operations (purchasing, seller dashboard). This token is never exposed to the browser.
The device authorization page
The CLI sends users to mog.md/device. On this page, users:
- Sign in with GitHub or Google (if not already signed in)
- Enter the 8-character code shown by the CLI
- Review the scopes being requested
- Click Approve
The web app then calls POST /v1/auth/device/approve with the user code. The CLI's next poll returns the token.
Authentication in automation
For CI pipelines and non-interactive automation, generate a token from the dashboard and set it as an environment variable. You can then skip the interactive device flow:
# Set token via environment variable
export MOG_TOKEN=mog_your_token_here
# The CLI reads MOG_TOKEN before checking the credentials file
mog install acme/some-skill --auto-buy
Always attach a spend policy to automation tokens to limit the blast radius if a token is leaked.