JWT Authentication
JWT authentication is a token-based authorization mechanism that does not rely on the server retaining client authentication or session information. With the possession of keys, authentication information can be issued in bulk, making it the most straightforward method of authentication.
Note
JWT authentication is not supported in EMQX Serverless deployments.
How JWT Authentication Works
Clients carry the JWT in either the username or password fields (depending on the module configuration) when initiating a connection. EMQX Platform uses the key or certificate configured to decrypt the JWT. If the decryption is successful, authentication is considered successful; otherwise, it fails.
If the signature verification is successful, the JWT authenticator proceeds to check the claims. The JWT authenticator actively checks the validity of the JWT based on these claims, such as iat
(Issued At), nbf
(Not Before), and exp
(Expiration Time). Additional custom claims can also be specified for verification. The client is granted access only if both the signature and claims verifications are successful.
With the default configuration, once JWT authentication is enabled, connections can be made using any username and the following password, which verifies against the default key field emqxsecret
:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJFTVFYIENsb3VkIiwiaWF0IjoxNTE2MjM5MDIyfQ.-k9Ggc6L_Jxq4uUf9xwdJpwRrS3PquL-JZKtAJoOvBo
The JWT Token provided above is for testing purposes only. You can generate a JWT token tailored to your business needs using appropriate tools. See How to Generate JWT for details.
How to Generate JWT
This section provides step-by-step instructions to generate a valid JWT for authenticating clients in EMQX.
Prerequisites
- A secret key (for HMAC algorithms) or a private key (for RSA/ECDSA)
- A JWT generation tool or code library (e.g., jwt.io, jjwt, mkjwk, Python, Node.js)
- Know which algorithm EMQX expects (
HS256
,RS256
, etc.)
JWT Structure
A JWT is composed of three parts:
JWT = base64UrlEncode(Header) + "." + base64UrlEncode(Payload) + "." + Signature
Header specifies metadata about the token, such as the algorithm and token type, e.g.:
json{ "alg": "HS256", "typ": "JWT" }
Payload contains claims (info about the user) like
username
,exp
, orclient_attrs
, e.g.:json{ "username": "emqx_user", "exp": 1719830400, "client_attrs": { "role": "admin", "sn": "device-001" } }
Signature validates that the token has not been tampered with, generated by signing the header and payload using the secret or private key.
Steps
Define the JWT Header. For example (for HMAC SHA-256):
json{ "alg": "HS256", "typ": "JWT" }
For RSA/ECDSA, replace
"alg"
withRS256
,ES256
, etc., depending on your key type.Define the JWT Payload. The payload contains claims used by EMQX. Common fields include:
json{ "sub": "mqtt_client", // Subject: optional, used for identification "username": "emqx_user", // Optional: used if bound in EMQX config "clientid": "client_123", // Optional: used for client restrictions "exp": 1719830400 // Required: expiration time (Unix timestamp) }
Important:
exp
is required. Without it, EMQX may reject the token.username
andclientid
can be added if EMQX is configured to verify them in the token.- You may also include custom claims like
acl
orclient_attrs
.
Base64Url encode the Header and Payload. You can do this manually or use a JWT library.
Sign the JWT. Use your secret or private key to generate the signature:
- For HMAC (e.g.,
HS256
):HMACSHA256(base64Url(header) + "." + base64Url(payload), secret)
- For RSA/ECDSA (e.g.,
RS256
): Use a private key with the appropriate signing algorithm.
- For HMAC (e.g.,
Assemble the JWT. Concatenate the encoded header, payload, and signature with periods:
<header>.<payload>.<signature>
Verify the JWT (optional but recommended). Use jwt.io or your development tools to decode and validate the token before use.
Example Using Python (pyjwt
)
import jwt
import datetime
secret = "your_shared_secret"
payload = {
"username": "emqx_user",
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}
token = jwt.encode(payload, secret, algorithm="HS256")
print(token)
For RS256
, replace secret
with your private key and provide the RS256
algorithm.
Result
You now have a signed JWT token that can be used in the MQTT CONNECT
packet, either in the username or password field, based on your EMQX configuration.
For detailed instructions on generating a JWT token for complex business use cases, refer to the blog post JWT Authentication and JWKS Endpoint in MQTT: Principle and a Hands-on Guide.
Access Control List (Optional)
The Access Control List (ACL) is an optional extension of an authentication result to control the client's permissions after login. The JWT can include an acl
field to specify the client's permissions.
See Access Control List (ACL) for more information.
Client Attributes
Starting from EMQX v5.7.0, you can use the optional client_attrs
field in the JWT Payload to set client attributes. Please note that both the keys and values must be of string type.
Example:
{
"exp": 1654254601,
"username": "emqx_u",
"client_attrs": {
"role": "admin",
"sn": "10c61f1a1f47"
}
}
Configure JWT Authentication
In the deployment, click Access Control - Extended Authentication, then click JWT Configure Authentication to create a new authentication.
You can complete the related configurations as follows:
When choosing JWT as the Authentication Method:
- JWT From: Specify the location of the JWT in the client connection request; options: password, username (corresponding to the
Password
andUsername
fields in the MQTT clientCONNECT
packet, respectively) - Algorithm: Specify the JWT encryption method, options:
hmac-based
,public-key
;- If selecting
hmac-based
, i.e., JWT uses a symmetric key for generating and verifying signatures (supports HS256, HS384, and HS512 algorithms), you should also configure:- Secret: The key used to verify the signature, the same key used for generating the signature.
- Secret Base64 Encode: Configure whether EMQX needs to decode the
Secret
using Base64 before verifying the signature; options: True, False, default: False.
- If selecting
public-key
, i.e., JWT uses a private key for generating signatures, and a public key is needed for verification (supports RS256, RS384, RS512, ES256, ES384, and ES512 algorithms), you should also configure:- Public Key: Specify the PEM-formatted public key used for verifying the signature.
- If selecting
- Disconnect After Expiration: Configures whether to disconnect clients after their JWT expires, enabled by default.
- Payload: Add custom Claims checks; users need to add keys and corresponding values to Claim and Expected Value, respectively, supporting
${clientid}
and${username}
placeholders. Keys are used to find the corresponding Claim in the JWT, and values are used to compare with the actual value of the Claim.
If selecting JWTS as the authentication method:
In addition to the above configurations, you should also configure:
- JWKS Endpoint: Specify the server endpoint address for EMQX to query JWKS. The endpoint should support GET requests and return a JWKS that conforms to standards.
- JWKS Refresh Interval: Specify the refresh interval for JWKS, i.e., the interval at which EMQX queries JWKS. Default value: 300 seconds (s). Click Create to complete the related configurations.
- Headers: Specify any additional HTTP headers that must be included in the requests to the JWKS server. Adding these HTTP headers ensures that the requests to the JWKS server are properly formatted according to your server's requirements. This configuration allows users to add key-value pairs, for example:
- Key:
Accept
- Value:
application/json
- Key:
TIP
- If the current deployment is a dedicated edition, create a VPC Peering Connection, and use the internal network address as the server address.
- If the current deployment is a BYOC edition, you need to create a VPC Peering Connection in your public cloud console. For details, refer to the section Create BYOC Deployment - VPC Peering Connection Configuration. Use the internal network address as the server address.
- If you see an "Init resource failure!" message, please check if the server address is correct and if the security group is open.