CredentialRefreshDriver contract
Overview
CredentialRefreshDriver mints and re-mints the tokens of refresh-type
credential sources. A refresh type, such as an
OAuth2 client-credentials source, has an issuer and long-lived refresh
material, such as a client secret or refresh token. The Driver holds that
material, obtains an access token from the issuer, and obtains a new one before
it expires. The Agent keeps the same placeholder throughout, so running
processes need no restart.
OpenClaw Control Plane (OCC) owns the source record, its Secret references, and authorization. The paired Credential Gateway owns the source's stored record and applies the current token to the Agent's requests. This Driver owns issuer exchange, refresh material, and minted tokens. OCC calls it for setup, device authorization, incident rotation, status, and removal. Configuration discovery uses the Gateway's access-token callback; OpenShell may refresh during retrieval without an OCC refresh call.
Selection is optional. The only implementation is the bundled
OpenShell Credential Refresh,
which must belong to the same openshell Backend as the
selected Credential Gateway. See Driver selection.
Without it, the gateway's catalog offers no refresh types.
Interface
The shared interface requires every method below. Startup rejects a Driver that omits one.
| Operation | Inputs and preconditions | Result or side effects | Failure or absence |
|---|---|---|---|
configureRefresh |
A source the gateway registered, its config, resolved refresh material, and a UUID request ID. | Replaces the source's refresh material. Replaying a successful request ID applies nothing new. | A throw leaves the outcome unknown; OCC never retries it with a new request ID. |
rotate |
A configured source and a UUID request ID. | Forces one mint and returns the refresh status. It does not revoke the old token at the issuer. | Only ready confirms a usable minted token. |
refreshStatus |
An existing source. | Current refresh status. | Missing state is pending before device authorization, otherwise failed. |
removeRefresh |
Source record. | Deletes the stored refresh material. Already-absent material counts as removed. | A throw keeps the OCC record deleting for retry. |
CredentialRefreshStatus carries only state (pending, ready, or
failed), the token's expiresAt, nextRefreshAt, and lastRefreshAt times,
an implementation-owned failureCode, and a recoveryAction of retry,
reauthorize, fix_configuration, or investigate. It never carries a token,
refresh material, or text from the issuer.
A CredentialSourceType whose rotation is refresh needs this Driver. The four refresh methods are required; device authorization adds optional hooks.
Device authorization
A type declaring deviceAuthorization.harnessId requires this Driver's
startDeviceAuthorization(context) and pollDeviceAuthorization(context, privateState).
OCC first registers an empty source with the Gateway; it defers refresh setup
until authorization supplies a grant. Start returns device instructions and an
opaque handle. Poll returns pending or ready only, never issuer credentials.
The Refresh Driver performs the exchange, configures gateway-owned refresh, and
confirms a usable token before reporting ready.
OCC fences polling with Secret compare-and-swap and binds the session to its actor,
source, and both Gateway and Refresh Driver IDs. It rechecks those bindings and
authority after external completion. A changed selection or uncertain exchange
requires reconnecting; it never replays the exchange. Closing the session removes
only its handle. Existing sources remain usable by their authorized Agents.
Device-source PATCH is refused: create a new login source rather than reseeding
a rotating refresh grant.
IAM
The selected IAM Driver authorizes each OCC operation before the Driver is called:
- Registration and update need the same grants as for any source:
credential_source:createorupdate, andsecret:operateon every Secret OCC reads for the refresh material. - A forced rotation needs
credential_source:updateon the exact source. It reads no Secret, so it needs nosecret:operate.
The Driver receives only authorized, exact-Namespace sources. It must never log, return, or persist refresh material or tokens outside its own store. Issuer credentials belong to the source, not to OCC.
Lifecycle
The API and worker construct the Driver at startup from trusted Installation configuration; only the API calls it. The interface has no initializer or destructor.
- Registration. OCC calls the gateway's
registerSourcewith config only; resolved Secret values go only to this Driver. After it succeeds, OCC callsconfigureRefreshand thenrotateto mint the first token. Both request IDs derive from the source ID, so a replay of the same step is not applied twice. The source becomesreadyonly oncerotatereportsready. On any failure, OCC callsremoveRefreshand the gateway'sremoveSource, as for a failed static registration. Device-authorized types register without configuring or minting; their first mint occurs during the device completion above. - Background refresh. The Driver re-mints before expiry without OCC. A failure appears in the source's status with its recovery action.
- Update.
PATCHreads the current or replacement Secret values and callsconfigureRefresh, thenrotate. OCC commits replacement Secret references only after areadymint. The update is not atomic: afterconfigureRefreshsucceeds, a failed mint returns503but the Driver keeps the new material, and the source staysreadywith the failure in its status. OCC restores nothing; supply corrected Secrets. An update must name a different Secret for a catalog field markedissuerRotated, such asrefresh_token, because the Driver may hold a newer value. On OpenShell, running Agents need a redeploy after any update that reachesconfigureRefresh; see its limits. - Rotation.
POST …/rotatecallsrotatefor incidents such as a suspected token leak. Running Agents keep their placeholder and need no redeploy. - Status. Reading a source adds the Driver's
refreshStatusto the gateway's status. A source whose type the catalog no longer offers keeps its gateway status without refresh status. Listing sources reads no status. - Deletion. OCC calls
removeRefresh, then the gateway'sremoveSource.
Limits
- One Credential Refresh Driver can be selected per Installation, and only on the selected Credential Gateway's Backend.
- OCC does not poll refresh status or audit background refresh failures; read the source to see them.
- The experimental
codex-oauthmodel source uses device authorization; OAuth2 tool sources receive their initial material through Secret references. - Installed Credential Refresh packages are unsupported.
Troubleshooting
| Symptom | What to check |
|---|---|
| A refresh type is missing from the catalog | Select drivers.credential_refresh and declare it on the gateway's Backend. |
Registration or rotation returns 503 naming a failure code |
The issuer refused the material or was unreachable. Read the source's status.refresh and follow its recoveryAction. |
status.refresh.recoveryAction is reauthorize |
The issuer revoked the refresh token. For a device source, reconnect with a new source. For a Secret-backed type, store new material in a Secret and PATCH its reference. |
status.refresh.recoveryAction is fix_configuration |
Check the source's token_url, client_id, scope, and client secret against the issuer. |
Rotation returns 409 |
The source is static. Update its Secret values instead. |
Implementations
- OpenShell Credential Refresh: bundled; configures OpenShell's gateway-owned refresh on the provider the OpenShell Credential Gateway registered.
