tunnelctl
Concepts

Authentication & tokens

How the CLI authenticates with SSO, and the two kinds of tokens involved.

tunnelctl uses your organization's identity provider (OIDC, e.g. Keycloak) for authentication. There is no separate tunnelctl password — you sign in with SSO.

User authentication (OIDC)

When you run tunnelctl login, the CLI authenticates via OIDC — Authorization Code + PKCE on a desktop, or the Device Authorization Grant (RFC 8628) on headless environments; the default --auth-flow=auto picks the right one:

The CLI opens the identity provider in your browser (PKCE), or prints a short code + verification URL you open on any device (device flow).
After you sign in, the CLI obtains an access token and a refresh token — PKCE via the local callback redirect, the device flow by polling the token endpoint.
Tokens are stored at ~/.config/tunnelctl/oidc.json with mode 0600.
The access token is short-lived (~5 minutes); the CLI refreshes it automatically before each API call.

The access token is sent as Authorization: Bearer <token> to the control-plane API, which validates its signature, issuer, audience, and expiry, and derives your permissions from provider-specific claims.

Connection tokens

Authenticating you to the API is separate from authorizing an FRP client to serve a specific endpoint. For that, the server issues a per-tunnel connection token (a signed JWT) when you bring a tunnel up. The CLI stores it alongside the tunnel's metadata in ~/.config/tunnelctl/tunnels/<name>.json (<name> is the slug for HTTP, tcp-<port> / udp-<port> for L4).

The tunnel edge validates each connection by checking three things, so a leaked token can't be used to hijack an endpoint:

  1. Signature — the token is signed by the server.
  2. Serial — the token's serial must match the tunnel's current serial; rotating the token bumps the serial and invalidates older ones.
  3. Endpoint agreement — the protocol and endpoint (HTTP slug, or TCP/UDP remote port) in the signed token, the database row, and the client's requested proxy must all match.

Rotation, not expiry

Connection tokens don't rely on short expiry — they're revoked by rotating the serial. Issuing a fresh token (e.g. via the server's rotate operation) immediately invalidates the previous one.

API keys (automation)

For non-interactive use, the server can issue scoped API keys (signed JWTs) to a caller that is already authenticated via OIDC. An API key can only carry a subset of the issuing user's permissions, so it can't be used to escalate privileges.

On this page