Summary
When running scalingo logout, the CLI only removes the locally stored credentials. It never asks the Scalingo Auth API to revoke/delete the token that was created at login. As a result, every token ever created by login remains valid forever on the server, even after the user believes they've logged out.
This depends on Scalingo/go-scalingo#513, which adds the missing TokenDelete method to the SDK.
Current behavior
Login (session/login.go, config/auth.go) creates a named API token via the SDK, e.g. in tryAuth (config/auth.go#L255-L257):
apiToken, err = c.TokenCreateWithLogin(ctx, scalingo.TokenCreateParams{
Name: "Scalingo CLI - " + hostname,
}, loginParams)
The SDK's Token struct includes an ID, but only the raw token string is persisted locally, via StoreAuth (config/auth.go#L77-L112):
c[authHost] = auth.CredentialsData{
Tokens: &auth.UserToken{
Token: token,
},
User: user,
}
UserToken (config/auth/config.go#L34-L36) only has a Token field — the token ID returned by the API is discarded and never saved locally.
Logout (cmd/logout.go → session/destroy.go):
func DestroyToken(ctx context.Context) error {
authenticator := &config.CliAuthenticator{}
err := authenticator.RemoveAuth(ctx)
if err != nil {
return errors.Wrap(ctx, err, "remove local authentication credentials")
}
// also clears the local regions cache (see #1057), unrelated to the token itself
err = config.DeleteRegionsCache(ctx, config.C)
...
}
RemoveAuth (config/auth.go#L171-L197) simply deletes the host entry from the local JSON auth file and rewrites it. No HTTP request is made to revoke the token.
Root cause
- The token
ID returned at token creation is never stored locally, so there is nothing to reference at logout time.
- The
go-scalingo SDK (currently vendored at v11.1.1) has no TokenDelete/revoke method — tracked separately in Scalingo/go-scalingo#513, even though the Auth API already supports DELETE /v1/tokens/:token_id.
Proposed fix
Once go-scalingo ships TokenDelete(ctx context.Context, id string) error:
- Store the token
ID alongside the token value in auth.UserToken (config/auth/config.go) at login time, and bump the local auth config version to migrate existing auth files gracefully.
- In
session.DestroyToken (session/destroy.go), call TokenDelete with the stored token ID before wiping the local auth file, so the server-side key is actually revoked.
- Handle failure gracefully (e.g. token already revoked, network error): a failed revocation shouldn't block local logout, but the user should probably be warned that the remote token may still be active.
Summary
When running
scalingo logout, the CLI only removes the locally stored credentials. It never asks the Scalingo Auth API to revoke/delete the token that was created at login. As a result, every token ever created byloginremains valid forever on the server, even after the user believes they've logged out.This depends on Scalingo/go-scalingo#513, which adds the missing
TokenDeletemethod to the SDK.Current behavior
Login (session/login.go, config/auth.go) creates a named API token via the SDK, e.g. in
tryAuth(config/auth.go#L255-L257):The SDK's
Tokenstruct includes anID, but only the raw token string is persisted locally, viaStoreAuth(config/auth.go#L77-L112):UserToken(config/auth/config.go#L34-L36) only has aTokenfield — the tokenIDreturned by the API is discarded and never saved locally.Logout (cmd/logout.go → session/destroy.go):
RemoveAuth(config/auth.go#L171-L197) simply deletes the host entry from the local JSON auth file and rewrites it. No HTTP request is made to revoke the token.Root cause
IDreturned at token creation is never stored locally, so there is nothing to reference at logout time.go-scalingoSDK (currently vendored atv11.1.1) has noTokenDelete/revoke method — tracked separately in Scalingo/go-scalingo#513, even though the Auth API already supportsDELETE /v1/tokens/:token_id.Proposed fix
Once
go-scalingoshipsTokenDelete(ctx context.Context, id string) error:IDalongside the token value inauth.UserToken(config/auth/config.go) at login time, and bump the local auth config version to migrate existing auth files gracefully.session.DestroyToken(session/destroy.go), callTokenDeletewith the stored token ID before wiping the local auth file, so the server-side key is actually revoked.