Skip to main content
MQTT clients can sign in with an access token from an OIDC identity provider instead of a password stored on the broker. The broker checks the token, then applies the same LoT (Language of Things) rules it uses for a local user.
Like a badge that expires. The client shows a badge (the access token) at the door. The broker checks the badge with the issuer, lets the person in as the identity printed on it, and asks them to leave when the badge expires.

When to use token authentication

Use it when people and services already have identities outside the broker:
  • Coreflux accounts — Operators sign in to Coreflux HUB with their organization account and connect to a broker in the fleet. The HUB presents that account’s access token. The broker accepts it only after enrollment has bound the broker to the same organization.
  • A provider you run — Point Issuers at an identity provider that publishes a discovery document over HTTPS and signs access tokens with RS256.
Leave it off when every client uses a username and password in the broker’s user store. It is off by default. Local users keep working. A CONNECT whose password is not a token is still checked against the user store.
Token checks run at MQTT CONNECT. Enabling them is a broker configuration change, and the broker reads that configuration at startup.

Quick Start

A broker enrolled in a Coreflux organization accepts account tokens for that organization. Enrollment fills BoundOrg; until that succeeds, token logins are refused and local users still connect.
Replace Issuers with the issuer URL of the account tokens you accept. List every client_id exactly — hub-desktop is the id the broker’s account-token contract uses for the desktop HUB. There is no wildcard. With enrollment turned on and BoundOrg still empty, the broker starts and refuses token logins until enrollment writes the organization id. With enrollment off, set BoundOrg yourself or the broker will not start. Restart after editing the file.
There is no COREFLUX_OIDC_* environment variable on the broker. These fields live in the broker configuration file (the same JSON as ports and TLS). BoundOrg is the exception: a successful enrollment writes the organization id into it.

What the client sends

On CONNECT, put the access token in the password. An optional Bearer prefix is accepted. The broker does not read the CONNECT username as the identity — the identity is the token’s subject claim (sub unless you change UsernameClaim). A password that is not shaped like a token (three non-empty segments separated by .) stays on the local user-store path. The Coreflux HUB does this when you Connect on a fleet row. See Account, fleet, and Cloud mode. Use MQTT over TLS (mqtts:// or wss://) whenever the token leaves the broker host. OIDC does not encrypt the MQTT connection. A plaintext listener carries the access token in the CONNECT password. Mutual TLS is a separate check — it does not replace the token, and the token does not replace it. See TLS Server Certificate.

How the broker decides

When Oidc.Enabled is true and the password looks like a token:
  1. The broker loads the issuer’s discovery document over HTTPS and checks the RS256 signature, the issuer, and the expiry.
  2. It requires token_use = access. An ID token is refused.
  3. It requires the client_id claim to be in ClientIdAllowlist.
  4. If RequiredScope is set, that exact scope must appear in the token’s space-separated scope list. Coreflux account tokens from the HUB request coreflux-broker/connect.
  5. If RequiredClaimsVersion is set (default 1), the coreflux:claims_version claim must match it.
  6. If BoundOrg is set, that organization id must appear in the space-separated coreflux:orgs claim. An empty BoundOrg refuses the token unless the issuer is listed in DedicatedIssuers.
  7. Groups and roles are read from coreflux:groups and coreflux:role. On a bound broker they must be prefixed with the organization id (org_…:engineers). The broker strips that prefix and authorizes the plain name.
A discovery or key outage refuses the connection. It does not fall through to anonymous access.

Identity and rules

The session is not written to the local user store. HUB User Management and -listUsers still show local accounts only. The display name (preferred_username by default) is written to login logs. Rules never match it. A rule written against an email address does not match a subject id.
Custom rules like this one require a Growth or Enterprise license. On Community, set AdminRoles or AdminGroups instead: a matching token receives AllowedSystemConfiguration, AllowedUserManagement, and AllowedLogManagement, which the shipped rules already allow. Both lists are empty by default, so a Coreflux account is not an administrator until you name the role or group. Use the plain name (owner), not org_…:owner. Group and role changes apply on the next token. The live session keeps the groups it connected with until it is disconnected. See RBAC with LoT Rules.

Token lifetime

DisconnectOnExpiry is on by default. When the access token expires, the broker waits ExpiryGraceSeconds (default 30) and then disconnects the client. On MQTT 5 the disconnect reason is NotAuthorized. The client connects again with a fresh token. That window is how a revoked account loses MQTT access: there is no separate revocation list. Signature checks allow ClockSkewSeconds of clock difference (default 60).

Configuration reference

All fields sit under Oidc in the broker configuration file. Restart the broker after a change. Turning Enabled on forces AnonymousLogin off, even if the file still says true.
An enabled configuration with no issuer, more than one issuer, an empty ClientIdAllowlist, or a shared issuer and an empty BoundOrg refuses to start. The exception is enrollment: if enrollment is on and BoundOrg is not known yet, the broker starts, serves local users, and refuses token logins until enrollment writes the organization id. See Licensing and Enrollment.

Failure modes

Login attempts are published on $SYS/Coreflux/Comms/Logins. For a token login, Username is the subject and DisplayName is the display-name claim. The password is not included.

How this fits with the portal

portal.coreflux.org is where an organization gets a license and registers brokers. Enrollment tells this broker which organization it belongs to (BoundOrg). The HUB fleet view lists those brokers for people signed in with an account in that organization. Connect on a fleet row sends that account’s access token to the broker. LoT rules then see the groups on the token. A license plan and an organization binding are different steps. The plan is activation. The binding is enrollment. Token login needs the binding when the issuer is shared.

Best practices

Subject ids are opaque. Write USER IN GROUP rules for the names your identity provider puts on the token, and keep UsernameClaim on sub.
The access token is the CONNECT password. Expose 8883 and 443 on the broker host, and keep 1883 off untrusted networks.
Every id in ClientIdAllowlist can present a token this broker will try to accept. Add a service client only for the job that needs MQTT.
MCP Server bearer tokens are minted by the broker for HTTP /mcp. They are not OIDC access tokens, and an OIDC token is not an MCP token.
The broker accepts RS256 access tokens only, and it requires the token_use claim to equal access. There is no setting to allow another algorithm or to skip that claim. An identity provider that omits token_use or client_id cannot authenticate MQTT clients until its tokens include them.

Next Steps

Account, fleet, and Cloud mode

Sign in to the HUB with a Coreflux account and connect to brokers in the organization.

RBAC with LoT Rules

Authorize token sessions with groups and permission flags.
Last modified on October 21, 2026