Device Credentials
A device's identity (its stable token) is kept separate from its credentials — the material it presents to authenticate. A device can hold several credentials and rotate them without changing its identity.
Available. Credentials are managed from the device detail page's Credentials tab in the console, or over the device-management GraphQL API.
Credential types
| Type | The device presents | Stored secret |
|---|---|---|
ACCESS_TOKEN | a bearer token (the credential id) | none — possession of the id is the proof |
MQTT_BASIC | a username (the credential id) + password | the password |
X509_CERTIFICATE | a certificate subject/fingerprint (the credential id) | none — possession is proved out of band |
Reading a credential requires device:write
Where a type carries a secret (the MQTT_BASIC password), that secret is write-only: it is submitted when the credential is registered and is never returned on read. The console shows it once, at creation time, and the API returns null for it thereafter.
That protects the MQTT_BASIC password, and nothing else. ACCESS_TOKEN and X509_CERTIFICATE store no secret to withhold: the credentialId is itself the bearer — the table above says so for the access token, and the per-event check accepts a certificate credential on its id alone as well — and credentialId is a plainly readable field. So reading a device's credentials hands you what you need to authenticate as that device, whatever the type.
Every query that returns a credential is therefore gated on device:write, not device:read: a read-only user cannot list a device's credentials, which is why the console's Credentials tab is not shown to one. The gate takes nothing from a device:write holder — they can already register a credential for any device in the tenant and impersonate it. What it stops is that capability reaching the read-only baseline every enabled tenant member receives.
How a device presents a credential
Credentials ride in the event body, on any transport (see Connecting a Device):
{
"device": "sensor-001",
"credentialType": "ACCESS_TOKEN",
"credentialId": "5f989616-2a0d-4160-8ae1-da5fad2898b2",
"eventType": "Measurement",
"payload": { "entries": [ { "measurements": { "temperature": "21.5" } } ] }
}
MQTT_BASIC additionally carries "credentialSecret": "<password>".
The platform resolves the credential to its owning device and verifies it — honoring expiry and revocation by disabling the credential. An instance's device-auth mode governs enforcement:
disabled— the self-asserteddevicetoken is trusted (no credential needed).optional— a presented credential is authoritative; without one the device token is trusted.required— a valid credential must be presented or the event is rejected. This is the default.
When a credential authenticates, the resolved device is authoritative: a device token naming a different device is rejected, so one authenticated device cannot impersonate another.
Two layers: the connection and the event
The credential above is the per-event check. In addition, MQTT/NATS connections are authenticated at the broker itself:
- The MQTT and NATS listeners are TLS — a device connects over TLS with the instance CA.
- A NATS auth-callout authenticates the connection and binds it to that one device's subjects — not its tenant's — so a device can publish its own events and read its own commands, and nothing else. For an
MQTT_BASICdevice, the connection presents MQTT username{tenant}:{credentialId}and the credential password — the same credential that authenticates its events — so a device that can't authenticate can't even connect. - The connection must also present the MQTT client id
{instanceId}:{tenant}:{deviceToken}; any other value is refused. The client id is the key the broker files a device's session under, so leaving it to the device would let one device take over another's session.
See Connecting a Device for the transport details.
Register a credential (console)
- Open the device's detail page and select the Credentials tab.
- Choose the credential type and fill the fields for that type (generate or paste an access token; enter a username + password for MQTT-basic; enter a certificate id for X.509).
- Click Add credential. For a secret-bearing type, copy the secret now — it will not be shown again.
Delete a credential from its row; the device can no longer authenticate with it.
Register a credential (GraphQL)
mutation {
createDeviceCredential(request: {
token: "b2e1…", # a fresh unique credential token
deviceToken: "sensor-001",
credentialType: "ACCESS_TOKEN",
credentialId: "5f989616-2a0d-4160-8ae1-da5fad2898b2",
enabled: true
}) { id token credentialType credentialId enabled }
}
For MQTT_BASIC, also pass credentialValue: "<password>" (write-only). Registering a credential and listing a device's credentials both require the device:write authority — see above.