Authorization
SuperMQ allows for fine-grained control over user permissions, taking into account hierarchical relationships between entities domains, groups, channels, and things. The structure and functionality of an authorization system implemented using SpiceDB and its associated schema language. auth
service backed by SpiceDB manages permissions for users, domains, groups, channels, and things.
Domains
Domain contains Things, Channels, and Groups. A User can be a member of a domain with different types of available relations. This relation provides access control to the entities in the domain.
Domain Entities
Overview
In SuperMQ, things, channels, and groups are inherently associated with one particular domain. This means that every group, including its sub-groups, every thing, and every channel is owned by and belongs to a specific domain. Domain acts like a kind of namespace.
Entities within domains have relationships with other entities in hierarchical structure.
Domain Entities Relations
Domain holds entities such as groups
, channels
, and things
.
The entities created in a domain don't have any hierarchical structure between them.
Example: In domain_1
a user creates the following entities group_1
, group_2
, thing_1
, thing_2
, channel_1
, channel_2
. By default, there is no relation between the entities, until the user assigns a relation between the entities
Channel Thing Connect/Disconnect
Thing
represents a device (or an application) connected to SuperMQ that uses the platform for message exchange with other things
.
Channel
is a message conduit between things connected to it. It serves as a message topic that can be consumed by all of the things connected to it.
Things can publish or subscribe to the channel.
Thing and channel can be connected to multiple channels using the following API.
curl -sSiX POST http://localhost/connect -H "Content-Type: application/json" -H "Authorization: Bearer <domain_user_access_token>" -d @- << EOF
{
"thing_id": "<thing_id>",
"channel_id": "<channel_id>"
}
EOF
The below diagram shows thing_1
is connected to channel_1
and channel_2
, then thing_2
is connected to channel_2
. This relationship can be established using the provided request
Channel Group Relation
A group serves as a parent entity that can contain both groups and channels as children. Child groups, in turn, can consist of further child groups or channels, forming a nested hierarchy. Notably, channels, which are distinct entities, cannot have child channels but can connect to multiple things. The concept of parentage signifies the relationship between higher-level entities and their subordinate components. Ancestors in this system refer to entities higher up in the hierarchy, and while a child group can have multiple ancestors, a channel can only belong to a single parent group. This hierarchical arrangement provides a structured and organized framework for managing information within the SuperMQ.
Assigning a group as the parent of a channel can be achieved through the following request.
curl -sSiX POST 'http://localhost/channels/<channel_id>/groups/assign' -H "Content-Type: application/json" -H "Authorization: Bearer <domain_user_access_token>" -d @- << EOF
{
"group_ids" : [ "<group_id_1>", "<group_id_2>" ]
}
EOF
The diagram below illustrates the parent relationship between channel_1
and channel_2
with group_2
. This relationship can be established using the provided request.
Group Group Relation
Groups can establish a parent-child relationship with other groups. The children groups are sub-group and they can also have children groups in nested fashion
Assigning a group as the parent to another group can be achieved through the following request.
curl -sSiX POST 'http://localhost/groups/<parent_group_id>/groups/assign' -H "Content-Type: application/json" -H "Authorization: Bearer <domain_user_access_token>" -d @- << EOF
{
"group_ids": ["<child_group_id_1>","<child_group_id_2>"]
}
EOF
The diagram below illustrates the parent relationship between group_1
and group_2
. This relationship can be established using the provided request.
Domain Entities Relation Examples
An example group with channels, things, and groups (sub-groups) within the domain.
Groups have parent-child relationships, forming a hierarchy where top-level groups (group_1
and group_2
) have groups (sub-groups - group_11
, group_12
, group_21
, and group_22
) or channels (channel_2
) beneath them.
Another example
User Domain Relationship
In SuperMQ, when a new user registers, they don't automatically have access to domains. The domain administrator must invite the user to the domain and assign them a role, such as administrator, editor, viewer, or member.
Domain administrator can invite an existing user in SuperMQ or invite new users to the domain by e-mail ID. After the user registers with SuperMQ, the user can accept the invitations to the domain.
All the users in SuperMQ are allowed to create a new domain. The user who creates a domain automatically becomes the domain administrator.
Users can have any one of the following relations with a domain
Let's take the below domain_1 with entities for explaining about user domain relationship.
Domain Administrator
Users with administrator relations have full control over all entities (things, channels, groups) within the domain. They can perform actions like creating, updating, and deleting entities created by others. Administrators are also allowed to create their own entities and can view and update the ones they have created.
Example: user_1 is administrator of domain_1. user_1 can view all entities created by others and have administrator access to all entities in the domain.
Domain Editor
Users with editor relations have access to update all entities (things, channels, groups) created by others within the domain. Editor are also allowed to create their own entities and can view and update the ones they have created.
Example: user_2 is editor of domain_1. user_2 can view all entities and have edit access to groups and channel entities, view access to thing entities in the domain, and also able to create & manage new things, channels & groups.
Domain Viewer
Users with viewer relations have access to view all entities (things, channels, groups) created by others within the domain. Viewer are also allowed to create their own entities and can view and update the ones they have created.
Example: user_3 can only view entities that are created by others in the domain and also able to create & manage new things, channels & groups
Domain Member
Users with member relations could not view and no access to entities (things, channels, groups) created by others within the domain. Members are also allowed to create their own entities and can view and update the ones they have created. Domain members will not have access by default to any of the entities in the Domain, access shall be granted for specific entities by the domain administrator or individual entity administrator.
Example: user_4 , user_5, user_6, user_7, user_8, user_9 is member of domain_1. These member relation users can able to create & manage new things, channels & groups in the domain. They can have access to the entities to which they have a relation in the domain. They could not view and manage other entities to which they don't have any relation in domain. !!! note "Note: All other users having administrator, editor, viewer relation with domain will also have member relation inherit with domain, which allows them to create new things, channels & groups."
After the user sign-up to SuperMQ, the user is allowed to create a new domain or join an existing domain via invitations, without domain user could not create things, channels, groups.
All operations, including creating, updating, and deleting things, channels, and groups, occur at the domain level. For instance, when a user creates a new thing using an access token, the newly created thing automatically becomes associated with a specific domain. The domain information is extracted from the access token. When the user obtains a token, the user should specify the domain for which they want to operate.
So to do operations on a domain, an access token for the domain is required. This can be obtained in two ways which is explained in next section.
Tokens and Domain Tokens
JWT token are used in SuperMQ for authentication and authorization. The JWT token has domain, exp, iat, iss, sub, type, and user fields.
Example JWT Token:
{
"domain": "",
"exp": 1706544967,
"iat": 1706541367,
"iss": "supermq.auth",
"sub": "",
"type": 0,
"user": "266d00f8-2284-4613-b732-3bd16e7cf8f2"
}
In JWT token, the domain field has domain ID and the user field has user ID.
If the domain field is empty, then with that JWT token following actions are permitted
- User profile update
- Domain creation & listing,
- Accept domain invitations
Actions related to the creation, update, and deletion of things, channels, and groups are not permitted, requests will fail in authorization. SuperMQ operations related to things, channels, and groups take place in domain level. So for these kinds of operations, a JWT token with a domain field containing the operating domain ID is required.
There are two ways to obtain JWT token for a particular domain
Option 1: Passing domain_id while obtaining new token
Request:
curl -sSiX POST 'http://localhost/users/tokens/issue' -H "Content-Type: application/json" -H "Authorization: Bearer <domain_user_access_token>" -d @- << EOF
{
"identity": "user1@example.com",
"secret": "12345678",
"domain_id": "903f7ede-3308-4206-89c2-e99688b612f7"
}
EOF
In this request, if the domain ID is empty or if the field is not added, then in response JWT token will have an empty domain field.
Response:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiI5MDNmN2VkZS0zMzA4LTQyMDYtODljMi1lOTk2ODhiNjEyZjciLCJleHAiOjE3MDY2MDM0NDcsImlhdCI6MTcwNjU5OTg0NywiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiOTAzZjdlZGUtMzMwOC00MjA2LTg5YzItZTk5Njg4YjYxMmY3XzU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiIsInR5cGUiOjAsInVzZXIiOiI1NzQ4ZGU2OS0yYTY2LTQwZGEtYTgyOS0xYjQ3ZjAyZTlhZGIifQ.c8a8HhVAbkdq_qZnd1DWHtkoNDPQc6XJY6-UcqqCygRR9svjgkwetN3rmIOWPNV5CjPh5lqlzWv1cOLruKBmzw",
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiI5MDNmN2VkZS0zMzA4LTQyMDYtODljMi1lOTk2ODhiNjEyZjciLCJleHAiOjE3MDY2ODYyNDcsImlhdCI6MTcwNjU5OTg0NywiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiOTAzZjdlZGUtMzMwOC00MjA2LTg5YzItZTk5Njg4YjYxMmY3XzU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiIsInR5cGUiOjEsInVzZXIiOiI1NzQ4ZGU2OS0yYTY2LTQwZGEtYTgyOS0xYjQ3ZjAyZTlhZGIifQ.SEMvEw2hchsvPYJWqnHMKlUmgjfqAvFcjeCDXyvS2xSGsscEci3bMrUohaJNkNDWzTBiBinV7nEcPrwbxDfPBQ"
}
Option 2: Get new access and refresh token through the refresh endpoint by passing domain_id
In most of the cases user login domain is under determinable. This method will be useful for those kind of cases.
Step 1: Get token without domain ID Request:
curl -sSiX POST 'http://localhost/users/tokens/issue' -H "Content-Type: application/json" -H "Authorization: Bearer <domain_user_access_token>" -d @- << EOF
{
"identity": "user1@example.com",
"secret": "12345678"
}
EOF
Response:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiIiLCJleHAiOjE3MDY2MDM1MjYsImlhdCI6MTcwNjU5OTkyNiwiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiIiwidHlwZSI6MCwidXNlciI6IjU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiJ9.Cc2Qj_z3gcUTjDo7lpcUVx9ymnUfClwt28kayHvMhY27eDu1vWMAZb_twQ85pbSlf12juo8P_YJcWKl3rDEokQ",
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiIiLCJleHAiOjE3MDY2ODYzMjYsImlhdCI6MTcwNjU5OTkyNiwiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiIiwidHlwZSI6MSwidXNlciI6IjU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiJ9.SiVsctItdR0WFhRbg7omZgR_WDPlLfLF2ov2eqkE1EP8c7RruOEv-KST3xVsohY33t2xevrtorwbjMQsl1YV7Q"
}
Decoded Access Token:
{
"domain": "",
"exp": 1706603526,
"iat": 1706599926,
"iss": "supermq.auth",
"sub": "",
"type": 0,
"user": "5748de69-2a66-40da-a829-1b47f02e9adb"
}
Decoded Refresh Token:
{
"domain": "",
"exp": 1706686326,
"iat": 1706599926,
"iss": "supermq.auth",
"sub": "",
"type": 1,
"user": "5748de69-2a66-40da-a829-1b47f02e9adb"
}
In these tokens, the domain field will be empty. As said earlier, this token can be to for user profile update, domain creation & listing, accept domain invitations
Step 2: List domains users have access Request:
curl -sSiX GET 'http://localhost/domains' -H "Authorization: Bearer <ACCESS_TOKEN_FROM_STEP_1>"
Response:
{
"total": 1,
"offset": 0,
"limit": 10,
"status": "all",
"domains": [
{
"id": "903f7ede-3308-4206-89c2-e99688b612f7",
"name": "Domain 1",
"alias": "domain_1",
"status": "enabled",
"permission": "administrator",
"created_by": "5748de69-2a66-40da-a829-1b47f02e9adb",
"created_at": "2024-01-30T07:30:36.89495Z",
"updated_at": "0001-01-01T00:00:00Z"
}
]
}
Step 3: Send Request to Refresh endpoint with domain id Request:
curl -sSiX POST 'http://localhost/users/tokens/refresh' -H "Content-Type: application/json" -H "Authorization: Bearer <REFRESH_TOKEN_FROM_STEP_1>" -d @- << EOF
{
"domain_id": "903f7ede-3308-4206-89c2-e99688b612f7"
}
EOF
!!! note "Note: Same request also used for switching between domains."
Response:
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiI5MDNmN2VkZS0zMzA4LTQyMDYtODljMi1lOTk2ODhiNjEyZjciLCJleHAiOjE3MDY2MDM3MDYsImlhdCI6MTcwNjYwMDEwNiwiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiOTAzZjdlZGUtMzMwOC00MjA2LTg5YzItZTk5Njg4YjYxMmY3XzU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiIsInR5cGUiOjAsInVzZXIiOiI1NzQ4ZGU2OS0yYTY2LTQwZGEtYTgyOS0xYjQ3ZjAyZTlhZGIifQ.3_q4F9CWxmBVjItiE8uR01vlm0du_ISl75E-nfEcc-3IMqHEOLbz1WrDvGbaYcPZ-CQufZuP2j-zqR4lShnu2Q",
"refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJkb21haW4iOiI5MDNmN2VkZS0zMzA4LTQyMDYtODljMi1lOTk2ODhiNjEyZjciLCJleHAiOjE3MDY2ODY1MDYsImlhdCI6MTcwNjYwMDEwNiwiaXNzIjoibWFnaXN0cmFsYS5hdXRoIiwic3ViIjoiOTAzZjdlZGUtMzMwOC00MjA2LTg5YzItZTk5Njg4YjYxMmY3XzU3NDhkZTY5LTJhNjYtNDBkYS1hODI5LTFiNDdmMDJlOWFkYiIsInR5cGUiOjEsInVzZXIiOiI1NzQ4ZGU2OS0yYTY2LTQwZGEtYTgyOS0xYjQ3ZjAyZTlhZGIifQ.KFUEGEx0LZStpokGnQHoMbpPRA5RUH7AR5RHRC46KcBIUoD4EcuWBiSreFwyRc4v-tcbp-CQQaBNGhqYMW4QZw"
}
Decoded Access Token:
{
"domain": "903f7ede-3308-4206-89c2-e99688b612f7",
"exp": 1706603706,
"iat": 1706600106,
"iss": "supermq.auth",
"sub": "903f7ede-3308-4206-89c2-e99688b612f7_5748de69-2a66-40da-a829-1b47f02e9adb",
"type": 0,
"user": "5748de69-2a66-40da-a829-1b47f02e9adb"
}
Decoded Refresh Token:
{
"domain": "903f7ede-3308-4206-89c2-e99688b612f7",
"exp": 1706686506,
"iat": 1706600106,
"iss": "supermq.auth",
"sub": "903f7ede-3308-4206-89c2-e99688b612f7_5748de69-2a66-40da-a829-1b47f02e9adb",
"type": 1,
"user": "5748de69-2a66-40da-a829-1b47f02e9adb"
}
Assign Users to Domain
Domain creator becomes administrator of the domain by default. Domain administrator can assign users to a domain with the following relations administrator, editor, viewer, member. The details about these relations are described in this section
User can be assigned to domain with endpoint /domain/<domain_id>/users/assign
with JSON body like below:
{
"user_ids" : ["<user_id>"],
"relation" : "editor"
}
- user_ids : field contains an array of users' IDs
- relation : field contains any one of the following relations administrator, editor, viewer, member, The details about these relations are described in this section
Example Request:
curl -sSiX POST 'http://localhost/domains/903f7ede-3308-4206-89c2-e99688b612f7/users/assign' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"user_ids" : ["05dbd66a-ce38-4928-ac86-c1b44909be0d"],
"relation" : "editor"
}
EOF
Unassign Users from Domain
User can be unassigned to domain with endpoint /domain/<domain_id>/users/unassign
with JSON body like below:
{
"user_ids" : ["<user_id>"],
"relation" : "editor"
}
- user_ids : field contains an array of users' IDs
- relation : field contains any one of the following relations administrator, editor, viewer, member, The details about these relations are described in this section
Example request:
curl -sSiX POST 'http://localhost/domains/903f7ede-3308-4206-89c2-e99688b612f7/users/unassign' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"user_ids" : ["05dbd66a-ce38-4928-ac86-c1b44909be0d"],
"relation" : "administrator"
}
EOF
User Entities Relationship
Users assigned to a domain with any relationship (administrator, editor, viewer, member ) will have access to create entities (things, groups, channels).
Domain administrator or individual entity administrator shall grant access to domain member for specific entities.
Groups Relations
Like domains, groups also have four types of relations
Group Administrator
Group administrator users have access to update, delete, assign, and unassign to the group and also have access to update, delete, assign, and unassign all of its child entities
From the previous viewer example, let's take user_3 who has viewer relation with domain_1, which means user_3 will be able to view all the entities created by others but cannot make any edits or updates on them. user_3 will have access to create entities in domain_1
user_3 creates new thing_101, channel_101, and group_101.
user_3 request to create thing_101:
curl -sSiX POST 'http://localhost/things' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"credentials": {
"secret": "a1ca33c0-367e-402b-a239-ff1255fdc440"
},
"name": "thing_101"
}
EOF
user_3 request to create channel_101:
curl -sSiX POST 'http://localhost/channels' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"name": "chanel_101"
}
EOF
user_3 request to create group_101:
curl -sSiX POST 'http://localhost/groups' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"name": "group_101"
}
EOF
The user who creates the entity will be the administrator of the entity by default. So user_3 is administrator of thing_101, channel_101 and group_101.
!!! Note "user_3 will also have domain viewer relation to thing_101, channel_101, and group_101"
user_3 can make these entities (thing_101, channel_101, group_101) in a hierarchical structure by assigning relations between entities Example: Connect thing_101 & channel_101, assign group_101 as parent of channel_101.
user_3 request for connect thing_101 & channel_101:
curl -sSiX POST 'http://localhost/connect' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"thing_id": "<thing_101_id>",
"channel_id": "<channel_101_id>"
}
EOF
user_3 request for assign group_101 as parent of channel_101:
curl -sSiX POST 'http://localhost/channels/<channel_101_id>/groups/assign' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"group_ids" : [ "<group_101_id>" ]
}
EOF
Members of domain 1 will not have access by default to any of the entities in domain 1, access shall be granted for specific entities by domain administrator or individual entity administrator.
Administrator of group_101 (user_3), assigns user_4 with administrator relation. When domain member user_4 becomes an administrator of group_101, user_4 can able to update, delete, assign, and unassign to group_101. Since group_101 has channel_101 and thing_101 as children. The user_5 has administrator access on group_101 child entities channel_101 and thing_101.
user_3 request for assign user_4 as administrator for group_101:
curl -sSiX POST 'http://localhost/domains/<DOMINA_1_ID>/users/assign' -H "Content-Type: application/json" -H "Authorization: Bearer <DOMAIN_ACCESS_TOKEN_>" -d @- << EOF
{
"user_ids" : ["<user_4 ID>"],
"relation" : "administrator"
}
Group Editor
Group editor users have access to view, update, assign, and unassign to the group and also have access to view, update, assign, and unassign all of its child channel and group entities, group editor have only view access to child thing entities in group
Administrator of group_101 (user_3/user_4), assigns user_5 with editor relation. When domain member user_5 becomes an editor of group_101, user_5 can able to update, assign, and unassign to group_101. Since group_101 has channel_101 and thing_101 as children. The user_5 has editor access to the group child entities channels, things, and groups. In this case, user_5 has editor access to group_101, and also has edit access to its child entities channel_101 and thing_101
Group Viewer
Group viewer users have access to view group and also have access to view all of its child entities
When domain member user_6 becomes a viewer of group_101, user_6 can able to view all the child and nested child entities in group_101. user_6 can assign child entities under group_101 and also assign child entities under any other group and channels that are children of group_101.
Examples
Domain Viewer with Channel & Thing
user_6 creates new channel and thing with the names channel_201 and thing_201 respectively. Then connects both channel_201 and thing_201.
Now user_5 can able to assign group_101 as a parent for channel_201
When channel_201 was assigned as a child of group_101, all the administrators, editors, and viewers of group_101 got the same access (relation) to channel_201 and thing_201
Multiple Domain Members with Group, Channel & Thing
user_8 creates a new group with the name group_301 user_9 creates a new thing and channel with the names thing_301 and channel_301 respectively, then connects both thing and channel.
user_8 can able to assign channel_301 as a child of group_301 When channel_301 is assigned as a child of group_301, then the administrators, editors, and viewers of group_301 get the same respective access to channel_301. The administrator, editor, and viewer of channel_301 get the same respective access to thing_301. So here user_8 becomes the administrator of both channel_301 and thing_301
user_5 can able to assign group_301 as a child of group_101
When group_301 becomes a child of group_101, then the administrator, editor, and viewer of group_101 get the same respective access to group_301. The administrator, editor, and viewer of group_301 get the same respective access to channel_301. The administrator, editor, and viewer of channel_301 get the same respective access to thing_301. So here user_5 becomes the editor of group_301, channel_301, and thing_301, user_4 becomes administrator of group_301, channel_301, and thing_301. user_8 has administrator access only to group_301 and its child entities channel_301 and thing_301.
User Registration
There are two ways to user get registered to SuperMQ, self-register and register new users by super admin. User registration is self register default which can be changed by following environment variable:
SMQ_USERS_ALLOW_SELF_REGISTER=true
SuperMQ Personal Access Token (PAT) Authentication
PAT Overview
Personal Access Tokens (PATs) in SuperMQ provide a secure method for authentication and authorization, similar to JSON Web Tokens (JWTs). PATs enable fine-grained access control with customizable scopes and permissions.
PAT Fields
PATs have the following fields:
- ID: Unique identifier for the token
- User: User ID associated with the token
- Name: User-defined name for easy identification
- Description: Explanation of the token's purpose
- Secret: Securely hashed token for authentication
- Scope: Defines the precise permissions and access levels
- IssuedAt: Timestamp of token creation
- ExpiresAt: Timestamp when the token becomes invalid
- UpdatedAt: Last modification timestamp
- LastUsedAt: Timestamp of most recent token usage
- Revoked: Boolean indicating token's active/inactive status
- RevokedAt: Timestamp of token revocation
Scope Structure
The PAT scope defines granular permissions across different system components:
- Users: Operations that can be performed by users
- Domains: Permissions for entities within domains (groups, channels, clients)
- Dashboard: Dashboard-related operations
- Messaging: Publish and subscribe permissions
Example Scope JSON
{
"users": {
"create": ["*"],
"read": ["*"],
"list": ["*"],
"update": ["*"],
"delete": ["*"]
},
"domains": {
"domain_1": {
"entities": {
"groups": {
"create": ["*"] // this for all groups in domain
},
"channels": {
// for particular channel in domain
"delete": [
"0241e6fe-2113-4731-9cfa-5c74626652b8",
]
},
"clients": {
"update": ["*"] // this for all clients in domain
}
}
}
}
}
PAT Endpoint Operations
SuperMQ exposes a couple of endpoints that allow the user to create,retrieve, update, delete and list pats.
- Create PAT:
Endpoint: POST http://localhost:9001/pats
Example Request:
curl --location 'http://localhost:9001/pats' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {JWT Token}' \
--data '{
"name": "clients pat",
"description": "for creating any client",
"duration": "20h",
"scope": {
"domains": {
"{domainID}": {
"entities": {
"clients": {
"create": [
"*"
]
}
}
}
}
}
}'
Expected response:
{
"id": "ec562a21-3341-4776-81ea-165afc2a8a57",
"user": "1e16c130-6f65-4ee8-80ac-e3ee76854878",
"name": "clients pat",
"description": "for creating any client",
"secret": "pat_HhbBMG9lTuiArOPudoVIeOxWKiEzQUd2geoWWvwqilc=_ZdO$M3-DT3Kz32nrLJ2IPY!jakoT9qTlEQ=1mgQC5^Y+hMxtkH%w$mJ5MOy2*Q-^4aTn148n$Zd|fwZssxgaW5@wv=lv!v4EJK%|",
"scope": {
"domains": {
"71133f11-8763-4c43-93b8-852ba7313109": {
"entities": {
"clients": {
"create": "*"
}
}
}
}
},
"issued_at": "2024-12-06T12:57:32.239599201Z",
"expires_at": "2024-12-07T08:57:32.239599201Z",
"updated_at": "0001-01-01T00:00:00Z",
"last_used_at": "0001-01-01T00:00:00Z",
"revoked_at": "0001-01-01T00:00:00Z"
}
- Retrieve PAT:
Endpoint: GET http://localhost:9001/pats/{patID}
Example Request:
curl --location 'http://localhost:9001/pats/{patID}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {JWT Token}'
Expected response:
{
"id": "ec562a21-3341-4776-81ea-165afc2a8a57",
"user": "1e16c130-6f65-4ee8-80ac-e3ee76854878",
"name": "clients pat",
"description": "for creating any client",
"scope": {
"domains": {
"71133f11-8763-4c43-93b8-852ba7313109": {
"entities": {
"clients": {
"create": "*"
}
}
}
}
},
"issued_at": "2024-12-06T12:57:32Z",
"expires_at": "2024-12-07T08:57:32Z",
"updated_at": "0001-01-01T00:00:00Z",
"last_used_at": "0001-01-01T00:00:00Z",
"revoked_at": "0001-01-01T00:00:00Z"
}
- Update PAT:
Endpoint: PATCH http://localhost:9001/pats/{patID}/name
Example Request:
curl --location --request PATCH 'http://localhost:9001/pats/{patID}/name' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {JWT Token}' \
--data '{
"name": "new client pat"
}'
Expected response:
{
"id": "ec562a21-3341-4776-81ea-165afc2a8a57",
"user": "1e16c130-6f65-4ee8-80ac-e3ee76854878",
"name": "new client pat",
"description": "for creating any client",
"scope": {
"domains": {
"71133f11-8763-4c43-93b8-852ba7313109": {
"entities": {
"clients": {
"create": "*"
}
}
}
}
},
"issued_at": "2024-12-06T12:57:32Z",
"expires_at": "2024-12-07T08:57:32Z",
"updated_at": "2024-12-06T16:42:18Z",
"last_used_at": "0001-01-01T00:00:00Z",
"revoked_at": "0001-01-01T00:00:00Z"
}
- Delete PAT:
Example Request:
Endpoint: DELETE http://localhost:9001/pats/{patID}
curl --location --request DELETE 'http://localhost:9001/pats/{patID}' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {JWT Token}'
With this lets use the PAT token/secret in platform to create a client and channel and connect them.
lets create a PAT that can create any client and channel:
curl --location 'http://localhost:9001/pats' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {JWT Token}' \
--data '{
"name": "clients & channels pat",
"description": "for creating any client or channel",
"duration": "20h",
"scope": {
"domains": {
"{domainID}": {
"entities": {
"clients": {
"create": [
"*"
]
}
"channels": {
"create": [
"*"
]
}
}
}
}
}
}'
Authentication and Authorization Process
- Authentication: The system first verifies that the PAT was legitimately issued by the platform.
- Authorization: The system then checks if the requested API operation is permitted by the token's defined scope.
Example of Using PAT
- Creating a client using PATs:
curl --location 'http://localhost:9006/{domainID}/clients' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer pat_HhbBMG9lTuiArOPudoVIeEvY94LEeE86jgoIzvk3vDs=_wdRegJONu9SpmfjS^tDy0$fG-2jp&$^yLgQr5Fse@eb6IBCatDv-R+4#Tpc%dHomiWN%NKYe6|J40KTYnmXmG-NAVNlogw*U4%!Q' \
--data '{
"name": "client",
"tags": [
"tag1",
"tag2"
],
"metadata":{"units":"km"},
"status": "enabled"
}'
- Creating a channel using PATs:
curl --location 'http://localhost:9005/{domainID}/channels' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer pat_HhbBMG9lTuiArOPudoVIeEvY94LEeE86jgoIzvk3vDs=_wdRegJONu9SpmfjS^tDy0$fG-2jp&$^yLgQr5Fse@eb6IBCatDv-R+4#Tpc%dHomiWN%NKYe6|J40KTYnmXmG-NAVNlogw*U4%!Q' \
--data '{
"name": "channel",
"description": "long channel description",
"metadata": {
"location": "London"
},
"status": "enabled"
}'
- Connecting both using the created PAT:
curl --location 'http://localhost:9005/{domainID}/channels/connect' \
--header 'accept: */*' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer pat_6ofqnFdFTH2qbgzDl8Dhn07ode5Sgk4BsCR1qgzFJoo=_9u=^tyQn0aJ$Jco1ZvJnPizYaN1W|Ij5F4y0A=MQr&cBQ*Woa4DI7GBn&E6BDFLgXDpb-Og@h1rWshzFtn7K4PTq|A*5+g1aiwQj' \
--data '{
"client_ids": ["{clientID}"],
"channel_ids": ["{channelID}"],
"types": "publish"
}'
Example of Authorization Failure
If the PAT used above with client and channel creation permissions attempts to create a group, the request will be denied and the expected is error:
{
"error": "",
"message": "failed to authorize PAT"
}