Skip to content

Logout does not revoke the API token server-side #1243

Description

@AntoineGirard

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.gosession/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

  1. The token ID returned at token creation is never stored locally, so there is nothing to reference at logout time.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions