This page explains how to use Stream's permissions version 1, if you are looking for version 2, go here:

In this version, permissions are associated to channel types only. There are 5 channel types which come built-in automatically, which also have default permissions - commerce, livestream, gaming, messaging, and team. These permissions can be customized if needed, and additional channel types can be created with their own separate set of permissions too.

Permission Checking

Copied!

Before we dive into more detail on how permission policies are structured, let's explain how permission checking works in general.

Permissions checking only happens on client-side calls. Server-side allows everything so long as a valid API key and secret is provided.

Permission checking is performed taking into account these parameters:

  • API Request: the action the user is performing (e.g. send a message, edit a message, etc.)
  • User Role: the role of the user making the request
  • Channel Type: the channel type
  • Resource: the resource involved in the API call (e.g. a channel, a message, a user, etc.)
  • Ownership: whether or not the resource is owned by the user (when applicable)

Every time a user performs an API request the following steps happen:

  1. The policies for the channel type are loaded

  2. The list of policies is iterated based on priority (highest first)

    1. If the policy matches the current request, then the request is either accepted or discarded

    2. If there is not match, continue iterating until one policy matches

Here's what a list of permissions look like:

  1. Admin users can perform any action

  2. Anonymous users are not allowed

  3. Users can modify their own messages

  4. Users can create channels

  5. Members of a channel can read and send messages

  6. Anything not matching the previous list should not be allowed

Let's now see how this would play out and introduce a couple of users: Tommaso and Thierry. Tommaso is an admin and Thierry a user. Thierry is also a member of the "Sailing" channel.

  1. Thierry posts a message on channel "soccer"

  2. Tommaso edits a message from Thierry

  3. Thierry creates a channel called "founders"

  4. An anonymous user opens the "Sailing" channel

Here's what the outcome of these requests would be:

  1. 🙅‍♂️ Only the last policy matches and it denies this action

  2. 👌 Tommaso is an admin, 1st policy is a match

  3. 👌 Thierry is a user, 4th policy is a match

  4. 🙅‍♂️ Anonymous users are discarded

Permission Policy Structure

Copied!

Now that we have a better idea about how the permission system works, let's define more precisely the structure of a permission policy.

Name

API Name

Description

Example

Name

name

The name of the policy, this serves as a human readable placeholder to remember the policy is all about

"Channel Member Permissions"

Resources

resources

The list of resources this policy applies. This field cannot be empty but you can set it to ["*"] if you want to match any resource.

["ReadChannel", "CreateMessage"]

Roles

roles

The list of roles this policy applies. Same as the resources field, this must not be empty and can be set to ["*"] to match any user role.

["channel_member"]

Owner

owner

This is an optional field that you can use to match actions performed on objects that the user owns. Ownership only applies to some resources like messages and channels. When set to true the policy will only match if the user is owner of the resource part for the request (when applicable).

true

Action

action

The action to perform if the policy matches on resource, role and ownership. This field can either be set to either "Allow" or "Deny".

0

Priority

priority

The priority field defined the position of the policy in the list. Permission policies are evaluated in consistent order from the highest priority to the lowest.

99

Example list

Copied!

Let's now write the example from before into a list of real policies.

Name

Resources

Roles

Owner

action

priority

Admin users can perform any action

["*"]

["admin"]

-

1 (Allow)

600

Anonymous users are not allowed

["*"]

["anonymous"]

-

0 (Deny)

500

Users can modify their own messages

["UpdateMessage"]

["user"]

true

1 (Allow)

400

Users can create channels

["CreateChannel"]

["user"]

-

1 (Allow)

300

Members of a channel can read and send messages

["ReadChannel", "CreateMessage"]

["channel_member"]

-

1 (Allow)

200

Anything not matching the previous list should not be allowed

["*"]

["*"]

-

0 (Deny)

100

User Roles

Copied!

User Roles are how permissions are grouped together and assigned to a user. Each user role can have separate permissions for different channel types. For example, a moderator for a livestream channel could have different permissions from a moderator for a messaging channel.

Stream maintains a user role for each user_id at an Application level and a Channel level. This is to allow flexibility and to cover a wider range of use cases.

Application User Roles

Copied!

This is the role assigned to users which applies across the entire application, and gives permissions for things which are outside of a channel's context, for example, being able to create channels, or search for users.

Role

Description

Permissions

Anonymous

Does not require a JWT and does not require a user_id registered with Stream

Lowest

Guest

Does not require a JWT but does require a user_id registered with Stream. Guests can read channels but not post messages

Low

User

A registered user on the app with a JWT provided by a trusted source (server)

Normal

Moderator

A registered user with elevated permissions

High

Admin

A registered user with elevated permissions granted from a trusted source (server)

High

Server-side

Not technically a user role. This is the client instantiated with the app key and secret. This is the highest level of administration and is run on the server

Highest

Channel User Roles

Copied!

This is the role assigned to a user once they are added to a channel. This role is unique to that channel and a user could have a different role in each channel which they are a member

Roles

Description

Permissions

channel_member

A typical member of a channel and the default user role for an Application User

Normal

channel_moderator

Elevated permissions on a channel. Granted to channel members through this method

High

Owner is not an official role, but whoever is the creator of a channel, or a message, gets additional permissions for objects they created versus objects created by someone else, this is managed on the permissions level.

Change a User Role

Copied!

Add Moderators to a Channel

Copied!

Remove Moderators From a Channel

Copied!

Custom Roles

Copied!

You can also create custom roles if the built-in roles are not enough to cover all your use cases. This requires an upgrade to Permissions version. Please contact support for help with this upgrade.

Permission Resources

Copied!

Permissions policies can match one or more resources. Here is the complete list of permissions available. Please keep in mind that this only applies to API calls done by clients, API requests performed from your backend do not need to pass a permission check.

ResourceDescription
AddLinksAllows to add URLs into messages
BanUserAllows to ban users
CreateChannelAllows to create a new channel
CreateDistinctChannelForOthersAllows to create new distinct channel for other users (e.g. user A creates channel for users B and C)
CreateMessageAllows to send a new message
CreateReactionAllows to add a reaction to a message
DeleteAttachmentAllows to delete uploaded files and images
DeleteChannelAllows to delete a channel
DeleteMessageAllows to delete a message
DeleteReactionAllows to delete a reaction
PinMessageAllows to pin a message
ReadChannelAllows to read messages from the channel
ReadMessageFlagsAllows to access messages that have been flagged
RemoveOwnChannelMembershipAllows to remove own channel membership (leave channel)
RunMessageActionAllows to run an action against a message
SendCustomEventAllows to send custom events to a channel
SkipChannelCooldownAllows to bypass existing cooldown in a channel
SkipMessageModerationAllows to bypass automatic message moderation
TruncateChannelAllows to truncate a channel
UpdateChannelAllows to update channel data
UpdateChannelCooldownAllows to set and unset cooldown time for a channel (slow mode)
UpdateChannelFrozenAllows to freeze and unfreeze a channel
UpdateChannelMembersAllows to add, modify and remove channel members
UpdateMessageAllows to update a message
UploadAttachmentAllows to upload files and images
UseFrozenChannelAllows to send messages and reactions to a frozen channels

Default Permissions

Copied!

The five built-in channel types ship with default permission setting.

messaging

Resourceadminmoderatoruserchannel_memberchannel_moderatorowner
AddLinks✖️✖️
BanUser✖️✖️✖️
CreateChannel✖️
CreateDistinctChannelForOthers✖️
CreateMessage✖️✖️
CreateReaction✖️✖️
DeleteAttachment✖️✖️
DeleteChannel✖️✖️✖️✖️
DeleteMessage✖️✖️
DeleteReaction✖️✖️
PinMessage✖️✖️
ReadChannel✖️
ReadMessageFlags✖️✖️✖️
RemoveOwnChannelMembership✖️✖️
RunMessageAction✖️✖️✖️✖️
SendCustomEvent✖️✖️
SkipChannelCooldown✖️✖️✖️
SkipMessageModeration✖️✖️✖️
TruncateChannel✖️✖️✖️✖️
UpdateChannel✖️✖️
UpdateChannelCooldown✖️✖️✖️
UpdateChannelFrozen✖️✖️✖️
UpdateChannelMembers✖️✖️
UpdateMessage✖️✖️
UploadAttachment✖️✖️
UseFrozenChannel✖️✖️✖️✖️✖️✖️

livestream

Resourceadminmoderatoruserchannel_memberchannel_moderatorguestanonymousowner
AddLinks✖️✖️
BanUser✖️✖️✖️✖️✖️
CreateChannel✖️✖️✖️
CreateDistinctChannelForOthers✖️✖️✖️
CreateMessage✖️✖️
CreateReaction✖️✖️
DeleteAttachment✖️✖️✖️✖️
DeleteChannel✖️✖️✖️✖️✖️✖️✖️
DeleteMessage✖️✖️✖️✖️
DeleteReaction✖️✖️✖️✖️
PinMessage✖️✖️✖️✖️
ReadChannel
ReadMessageFlags✖️✖️✖️✖️✖️
RemoveOwnChannelMembership✖️✖️✖️✖️✖️✖️✖️
RunMessageAction✖️✖️✖️✖️✖️✖️
SendCustomEvent✖️✖️
SkipChannelCooldown✖️✖️✖️✖️✖️
SkipMessageModeration✖️✖️✖️✖️✖️
TruncateChannel✖️✖️✖️✖️✖️✖️✖️
UpdateChannel✖️✖️✖️✖️✖️✖️✖️
UpdateChannelCooldown✖️✖️✖️✖️✖️
UpdateChannelFrozen✖️✖️✖️✖️✖️
UpdateChannelMembers✖️✖️✖️✖️✖️✖️✖️
UpdateMessage✖️✖️✖️✖️
UploadAttachment✖️✖️
UseFrozenChannel✖️✖️✖️✖️✖️✖️✖️✖️

team

Resourceadminmoderatoruserchannel_memberchannel_moderatorowner
AddLinks✖️✖️
BanUser✖️✖️✖️
CreateChannel✖️
CreateDistinctChannelForOthers✖️
CreateMessage✖️✖️
CreateReaction✖️✖️
DeleteAttachment✖️✖️
DeleteChannel✖️✖️✖️✖️
DeleteMessage✖️✖️
DeleteReaction✖️✖️
PinMessage✖️✖️
ReadChannel✖️
ReadMessageFlags✖️✖️✖️
RemoveOwnChannelMembership✖️✖️
RunMessageAction✖️✖️✖️✖️
SendCustomEvent✖️✖️
SkipChannelCooldown✖️✖️✖️
SkipMessageModeration✖️✖️✖️
TruncateChannel✖️✖️✖️✖️
UpdateChannel✖️✖️
UpdateChannelCooldown✖️✖️✖️
UpdateChannelFrozen✖️✖️✖️
UpdateChannelMembers✖️✖️
UpdateMessage✖️✖️
UploadAttachment✖️✖️
UseFrozenChannel✖️✖️✖️✖️✖️✖️

commerce

Resourceadminmoderatorchannel_memberchannel_moderatorguestowner
AddLinks✖️
BanUser✖️✖️✖️
CreateChannel✖️
CreateDistinctChannelForOthers✖️
CreateMessage✖️✖️
CreateReaction✖️✖️
DeleteAttachment✖️✖️
DeleteChannel✖️✖️✖️✖️✖️
DeleteMessage✖️✖️
DeleteReaction✖️✖️
PinMessage✖️✖️
ReadChannel✖️
ReadMessageFlags✖️✖️✖️
RemoveOwnChannelMembership✖️✖️
RunMessageAction✖️✖️✖️✖️
SendCustomEvent✖️✖️
SkipChannelCooldown✖️✖️✖️
SkipMessageModeration✖️✖️✖️
TruncateChannel✖️✖️✖️✖️✖️
UpdateChannel✖️✖️✖️
UpdateChannelCooldown✖️✖️✖️
UpdateChannelFrozen✖️✖️✖️
UpdateChannelMembers✖️✖️
UpdateMessage✖️✖️
UploadAttachment✖️
UseFrozenChannel✖️✖️✖️✖️✖️✖️

gaming

Resourceadminmoderatorchannel_memberchannel_moderatorowner
AddLinks✖️
BanUser✖️✖️
CreateChannel✖️✖️✖️✖️
CreateDistinctChannelForOthers✖️✖️✖️✖️
CreateMessage✖️
CreateReaction✖️
DeleteAttachment✖️
DeleteChannel✖️✖️✖️✖️
DeleteMessage✖️
DeleteReaction✖️
PinMessage✖️✖️
ReadChannel✖️
ReadMessageFlags✖️✖️
RemoveOwnChannelMembership✖️
RunMessageAction✖️✖️✖️
SendCustomEvent✖️
SkipChannelCooldown✖️✖️
SkipMessageModeration✖️✖️
TruncateChannel✖️✖️✖️✖️
UpdateChannel✖️✖️✖️✖️
UpdateChannelCooldown✖️✖️
UpdateChannelFrozen✖️✖️
UpdateChannelMembers✖️✖️✖️✖️
UpdateMessage✖️
UploadAttachment✖️
UseFrozenChannel✖️✖️✖️✖️✖️