Authentication & Security

How you authenticate with deplo.ai (GitHub OAuth → JWT, or a CLI token), how deplo.ai authenticates with your providers (encrypted per-user credentials), and why the trust model means you can walk away at any time.

Signing in with GitHub#

GitHub OAuth is the only sign-in method — signing in creates your account, so there is no separate registration. The flow runs entirely through the frontend domain (the rewrite proxy forwards it to the backend):

  1. Authorize

    The app sends you to GET /api/v1/auth/github, which redirects to GitHub's authorize page with deplo.ai's client ID and the scopes below.

  2. Callback

    GitHub redirects back to GET /api/v1/auth/github/callback with a one-time code. The backend exchanges it for a GitHub access token, upserts your user record, and stores the GitHub token AES-256-GCM encrypted — it is needed later to read repository trees and file contents during analysis.

  3. JWT issued

    The backend signs a JWT and redirects to the dashboard's /auth/callback page, which stores the token and takes you to your dashboard.

Requested scopes#

ScopeWhy deplo.ai needs it
read:userYour profile (name, avatar) for the account.
user:emailYour email address, used for deployment lifecycle emails.
repoReading repository trees and file contents during analysis and deployment, including private repos.
admin:repo_hookRegistering deploy webhooks on repositories (covers organization repos too).

JWT properties#

  • Signed with HS256, valid for 7 days — after that you sign in again; there are no refresh tokens.
  • Stored in localStorage (not a cookie) and sent as Authorization: Bearer <jwt> on every API call.
  • Requests are same-origin (www.deplo.in/api/v1/…); the Vercel rewrite forwards the header to the backend verbatim. Because auth is header-based rather than cookie-based, CSRF and SameSite concerns do not apply.

CLI tokens#

A 7-day browser JWT is wrong for a terminal, so the CLI uses long-lived, revocable tokens instead. They authenticate the exact same REST API — the auth middleware sees the dpl_ prefix on the bearer token and resolves it as a CLI token instead of verifying a JWT.

  • Format: dpl_ followed by 40 hex characters, generated from cryptographically secure random bytes.
  • The raw token is shown exactly once, at creation. Only its SHA-256 hash is stored, so a database leak never exposes usable credentials.
  • Tokens are named (so you know which machine is which), record when they were last used, and are revocable individually in Settings → CLI tokens or via the CLI tokens API. Revocation is immediate.

How deplo login works#

deplo login uses a browser hand-off so the token never transits anywhere except your own machine:

  1. CLI opens the browser

    The CLI starts a loopback listener on 127.0.0.1 and opens www.deplo.in/cli-auth with the loopback port, a random state nonce, and your machine's hostname. If you are not signed in, the page bounces you through GitHub OAuth first and returns.

  2. You explicitly authorize

    The page shows exactly what will happen — “This creates a CLI token for your-machine” — and mints the token only when you click Authorize. The token is named after the machine (e.g. CLI · macbook-pro) so it is recognizable in Settings.

  3. Loopback delivery

    The browser redirects to http://127.0.0.1:<port>/callback with the token and the state nonce — a loopback address only, never a remote host. The CLI verifies the state and stores the token locally.

On headless machines (SSH, CI) there is no browser to hand off to: create a token in Settings → CLI tokens and pass it with deplo login --token. See CLI Authentication.

Provider credentials#

deplo.ai deploys with credentials you connect, stored per user in a single ProviderConnection table with the credential AES-256-GCM encrypted at rest:

ProviderCredentialHow it's obtainedValidated
GitHubOAuth access tokenSign-in flow aboveBy the OAuth exchange itself
VercelIntegration OAuth tokenOne-click integration install (redirect secured with a signed JWT state parameter)Token exchange + account info check before storing
RenderPersonal API key (rnd_…)You paste it in Dashboard → Integrations (Render has no third-party OAuth)Live call to Render's GET /v1/owners before storing — invalid keys are never saved
  • Credentials are decrypted only inside the deployment orchestrator, at deploy time, and are never logged.
  • No API ever returns a stored credential. GET /integrations returns connection status and workspace metadata only; the UI shows a masked key (rnd_••••) that is never revealed again.
  • Rotation is just reconnecting with a new key; disconnecting deletes the connection. You can also revoke from the provider side at any time — the Vercel integration in your Vercel dashboard, the API key in Render.

Platform security posture#

  • All API traffic is rate limited to 200 requests per 15 minutes per IP.
  • Helmet security headers, a strict CORS allowlist, and JSON body limits on the backend; security headers on the frontend.
  • SQL access goes exclusively through Prisma's parameterized queries.
  • Secrets never appear in logs or in the repository; env vars are validated at boot.

The trust model, summarized#

deplo.ai's job is to act on your behalf, revocably — never to hold your infrastructure:

what deplo.ai holds vs. what you own
deplo.ai holds            you own
────────────────          ─────────────────────────────
GitHub OAuth token         the repository
Vercel OAuth token         the Vercel account + projects
Render API key             the Render workspace + services
  (all AES-256-GCM         the domains, the traffic,
   encrypted, revocable)   the provider bill

Your applications run in your Vercel and Render accounts; deplo.ai is not in the serving path and hosts nothing. Revoke the GitHub authorization, the Vercel integration, and the Render key, and deplo.ai can touch nothing of yours — while everything it ever deployed keeps running untouched. That is the point: the platform is useful because it can act for you, and safe because you can stop it at any time.