Status: research only, nothing implemented. Read from each provider’s public docs on 2026-10-15.
No app was registered, no account created, no sign-in attempted. Today oneapi-agent takes a
provider API key from an environment variable or from oneapi-agent login <provider> (OS
password store); see gpu-testing.md.
remote-test needs a credential that can: read the account, list/price GPUs, create a
machine, read its state, delete it, and (DigitalOcean only) add and remove a throwaway SSH
key. A sign-in flow is only worth building if it can grant that and nothing more.
| Provider | OAuth / browser sign-in for third-party CLIs | Device flow | Fine-grained access | Verdict |
|---|---|---|---|---|
| DigitalOcean | Yes. OAuth 2.0 authorization code + PKCE for public clients, Dynamic Client Registration, loopback redirects on any port | Not documented | Yes: token scopes such as droplet:create |
Feasible now |
| Vultr | Yes, but heavier. OAuth 2.0 / OIDC apps, PKCE, consent screen, app review | Not documented | Yes, through an IAM policy attached to the app | Feasible after Vultr approves an app; several gaps in the docs |
| Runpod | No public flow. Runpod’s own flash login opens the console and saves a key, but no third-party API is documented |
No | API keys: All / Restricted / Read Only | Not possible with public docs; keep API keys |
| Vast.ai | No. API keys only | No | Scoped API keys (permissions JSON) | Not possible; keep API keys, recommend a scoped key |
Docs: https://docs.digitalocean.com/reference/api/oauth/, scopes: https://docs.digitalocean.com/reference/api/scopes/, user tutorial: https://www.digitalocean.com/community/tutorials/how-to-use-oauth-authentication-with-digitalocean-as-a-user-or-developer.
S256;
they get no client secret. Endpoints:
https://cloud.digitalocean.com/v1/oauth/authorizehttps://cloud.digitalocean.com/v1/oauth/tokenhttps://cloud.digitalocean.com/v1/oauth/revokehttps://cloud.digitalocean.com/.well-known/oauth-authorization-serverPOST
https://cloud.digitalocean.com/v1/oauth/register that returns a client id (no secret) and a
registration_access_token for managing it. One to five redirect URIs; loopback redirects
(127.0.0.1, [::1], localhost) match on any port, so a CLI can listen on an ephemeral
local port.login does today).remote-test needs: account:read, droplet:read, droplet:create,
droplet:delete, ssh_key:create, ssh_key:delete (plus ssh_key:read if listing keys).
Without scope, the consent screen lets the user pick granular scopes.scope parameter. GPU droplet sizes may need extra scopes (e.g. regions:read,
sizes:read); not checked. No device flow is documented, so a headless machine (CI, SSH
box) cannot use this; it would keep using OCEAN_API_KEY.Docs: https://docs.vultr.com/platform/iam/oauth, https://docs.vultr.com/platform/iam/oauth/access-tokens/how-to-integrate-a-third-party-app-with-vultr-oauth, https://docs.vultr.com/platform/iam/oauth/access-tokens/how-to-use-pkce-with-vultr-oauth, https://docs.vultr.com/platform/iam/oauth/authorizations/how-to-authorize-a-third-party-oauth-application.
POST /v2/oidc/provider), registers a client (POST /v2/oauth/clients, with callback URLs;
the client secret is shown once) and attaches a permission set (POST
/v2/oauth/clients/{id}/scopes with an IAM policy id). Customers consent in the Vultr
console; the code (single use, 10 minutes) is exchanged at POST
https://api.vultr.com/v2/oidc/provider/{provider-id}/token. The access token is a JWT sent
as Bearer, like an API key. Vultr creates a dedicated role limited to what the customer
approved, and the customer can revoke it later.https callback URL, at least one scope,
and Vultr’s approval; until then only a draft-mode allowlist can authorize it.remote-test needs instance
create/read/delete, plan and region reads, and account read; the exact IAM action names were
not checked.http://localhost
callbacks are accepted (only https is stated as a publishing requirement), the access
token lifetime, and any device flow (none documented). The authorize call is documented as
an API POST; the console consent URL a CLI would open in a browser is not given.Docs: https://docs.runpod.io/get-started/credentials, https://docs.runpod.io/flash/cli/login, https://docs.runpod.io/runpodctl/reference/runpodctl-config.
flash login: it opens
“the Runpod console authorization page”, waits for approval (default 600 s; --no-open
prints the URL) and saves an API key to ~/.runpod/config.toml. The docs do not say whether
this is OAuth, what endpoints it uses, or whether other apps may use it. Using an
undocumented flow is not an option.runpodctl itself only takes an API key (runpodctl config --apiKey, or runpodctl doctor).flash login flow to third parties (would need to ask Runpod).Docs: https://docs.vast.ai/cli/authentication, https://docs.vast.ai/guides/reference/api-keys.md, https://docs.vast.ai/api-reference/authentication.md.
vastai set api-key
(stored in ~/.config/vastai/vast_api_key) or VAST_API_KEY.vastai create
api-key --permissions '{...}'. A key with instance management but no billing or key
management would be the least-privilege choice for remote-test.remote-test needs (offer search, rent, show,
destroy, users/current for providers); the permissions reference
(https://docs.vast.ai/api-reference/permissions) was not read in detail.oneapi-agent login as the default for all four providers, and
recommend least-privilege keys in the docs (Vast scoped key, Runpod where possible).OCEAN_API_KEY.