Status: Implemented
The shim authenticates using AutoGPT's existing OAuth 2.0 provider infrastructure — the same system used by third-party app integrations. No new auth infrastructure needed.
AutoGPT already runs a full OAuth 2.0 Authorization Server:
/auth/authorize— authorization endpoint/api/oauth/token— token endpointintrospect_token()— token validation- Authorization Code + PKCE flow already implemented
Device OAuth would be redundant. The shim registers as an OAuth app and uses Authorization Code + PKCE with a localhost redirect URI.
The shim is a first-party public OAuth application registered in the AutoGPT platform. It uses Authorization Code + PKCE and has no client secret.
Client ID: autogpt-local-executor (well-known)
Client type: public (PKCE; no client secret)
Redirect URI: http://localhost:{port}/callback where {port} ∈ 41899..41910
Scopes: USE_TOOLS
Grant types: authorization_code, refresh_token
Ports 41899–41910 (12 ports) are reserved for the shim's local callback
server. The shim binds the first free port in that range, so a busy 41899
(held by another app, a stale shim process, or a developer's local dev
server) doesn't break first-time auth. The platform's OAuth client
registration MUST accept all ports in this range as valid redirect_uri
values for client_id=autogpt-local-executor — registering only 41899
would defeat the fallback. Listener is always bound to 127.0.0.1; never
to 0.0.0.0. See CROSS_PLATFORM.md → OAuth callback port.
Each platform deployment registers the app once via the existing
oauth-tool CLI inside the backend container:
poetry run oauth-tool generate-app \
--name "AutoGPT Local Executor" \
--client-id "autogpt-local-executor" \
--public \
--description "Local PC shim for the AutoGPT hosted platform" \
--redirect-uris \
"http://localhost:41899/callback,http://localhost:41900/callback,\
http://localhost:41901/callback,http://localhost:41902/callback,\
http://localhost:41903/callback,http://localhost:41904/callback,\
http://localhost:41905/callback,http://localhost:41906/callback,\
http://localhost:41907/callback,http://localhost:41908/callback,\
http://localhost:41909/callback,http://localhost:41910/callback" \
--scopes "USE_TOOLS"The command prints SQL containing the well-known public client ID and an
isPublic=true marker. Replace YOUR_USER_ID_HERE, execute it once per
environment, and keep every callback URI in the registration. Self-hosters
that choose another ID configure it with AUTOGPT_SHIM_OAUTH_CLIENT_ID.
OAuthApplication.isPublic (added in migration
20260604120000_add_oauth_application_is_public) and the
validate_client_credentials(..., code_verifier=...) short-circuit
together implement the OAuth 2.1 best-practice for desktop / mobile /
SPA clients (PKCE, no client_secret).
- Confidential client (default,
isPublic=false):client_secretis required as before. No behavior change. - Public client (
isPublic=true):client_secretis ignored;code_verifieris required and is the only credential. The PKCE challenge/verifier check still happens inconsume_authorization_code(which compares the verifier against the stored code_challenge).
The oauth-tool generate-app --public command sets this field for new shim
registrations. Existing registrations can be migrated with UPDATE "OAuthApplication" SET "isPublic" = true WHERE "clientId" = '<id>'.
Introspect (/api/oauth/introspect) remains confidential-auth-only. Revoke
(/api/oauth/revoke) accepts this registered public client without a secret,
binds each token to the client before revoking it, and returns the RFC 7009
non-disclosing success response. autogpt-shim revoke revokes the access and
refresh tokens before clearing the keychain. The platform also pushes a
SESSION_REVOKED frame to a connected shim (see PROTOCOL.md).
User Shim AutoGPT Platform
| | |
| autogpt-shim auth | |
|---------------------->| |
| | 1. Generate code_verifier |
| | code_challenge = S256(cv) |
| | |
| | 2. Spin up localhost:41899 |
| | |
| | 3. Open browser → |
| | /auth/authorize? |
| | client_id=autogpt-local-executor
| | redirect_uri=http://localhost:41899/callback
| | code_challenge=... |
| | scope=USE_TOOLS
| | |
| [Browser opens] | |
|<====================================================-->|
| [User logs in and approves scopes] |
| | |
| |<-- GET /callback?code=AUTH_CODE
| | |
| | 4. POST /api/oauth/token |
| | grant_type=authorization_code
| | code=AUTH_CODE |
| | code_verifier=... |
| | |
| |<-- {access_token, refresh_token, expires_in}
| | |
| | 5. Store tokens in OS keychain |
| | (keyring library) |
| Auth complete | |
|<----------------------| |
On every WebSocket connect, the shim includes the access token:
GET /ws/local-executor # persistent machine control
GET /ws/local-executor/{session_id} # activated per-chat data channel
Authorization: Bearer {access_token}
Platform validates via introspect_token(access_token):
- Checks token not expired
- On data channels, checks token belongs to the session owner
- On the control channel, registers the online machine under the token's user
- Checks
USE_TOOLSscope present - Returns user_id for the session
The shim refreshes using the stored refresh_token exactly once when the
initial WebSocket upgrade returns 401. An initial 403 is treated as a terminal
session-authorization denial and never rotates credentials. If the post-refresh
retry returns 401 or 403, startup terminates instead of entering the reconnect
loop. The refresh is forced even while the rejected access token remains in the
keychain.
- On refresh failure (expired refresh token), prompt user to re-auth via CLI:
autogpt-shim auth
Tokens stored in OS keychain:
- macOS: Keychain Services via
keyringlibrary - Linux: Secret Service (GNOME Keyring / KWallet) via
keyring - Windows: Windows Credential Manager via
keyring
The public shim client requests USE_TOOLS, an existing AutoGPT
APIKeyPermission. The WebSocket handshake requires that scope in addition to
an active access token and session ownership. Individual executor capabilities
remain opt-in through shim configuration, HELLO capability advertisement,
platform feature flags, and the per-session computer-use consent gate.