Device Tokens: Expiry, Revocation and Rotation

A device is not a user
An app that pairs a device to a backend holds a long-lived credential that nobody types. It can expire, be revoked by an administrator, or belong to a device that was suspended. If the app treats all of these as "something went wrong", the person using it cannot tell what to do next.
Name every failure
Give each backend answer its own state: token missing, invalid, expired or revoked, and device revoked, inactive or suspended. Map them in one place, so every screen shows the same, correct message and offers the right action: pair again, wait for reactivation, or contact an administrator.
Rotate without locking the device out
Rotation replaces the credential before it becomes a problem. The order is what keeps the device connected: receive the new token, store it securely, then refresh the session state. Clearing the local session is a separate, deliberate action. It removes what is on the device and says so before it does, and it does not pretend to revoke anything on the server.
Never show the token
A token must not appear in the interface, in logs, or in an error message. Screens read a presentation status from the mapper instead of raw backend text or headers, which removes the easiest way for a secret to leak.
Two credentials, two jobs
When a person operates a device, there are two identities: the device and the person acting through it. Keep two credentials with documented rules for which request carries which, and never let the person's token stand in for the device's.
Keep command polling honest
Before a real background runtime exists, a foreground poll is the honest version. It runs on a visible timer while the screen is open, stops when the session is no longer authenticated, executes only commands it understands, and reports the rest as unsupported instead of guessing.
In our own products
Rveta Connector, still in development, follows this: seven distinct token and device states, rotation that stores the new token before refreshing, a local clear that does not touch the server, separate actor and device credentials, and a 30-second foreground poll that runs only ping and a status refresh. It has no native gateway runtime yet, and its pages say so.
Enjoyed this article? Share it with your network.