Auth & Permissions

Last Edit: Jul 07 2020

Stream APIs can be used both server-side or directly from the frontend (web apps, mobile apps). Both approaches have pros and cons, and very often, a mixed approach is used.

Server-Side Integration:

On a pure server-side integration, everything related to feeds is done on your backend. Your front-end will interact with Stream APIs through your APIs. If you use something like RoR or Django, this is likely the most straightforward approach as you may already have BE / FE APIs for your application (additionally, we support backend frameworks with excellent libraries).

Frontend Integration:

On a frontend integration, most of the integration with Stream happens on the mobile or web app directly. The main advantages of this type of integration are that you can directly call Stream APIs (no extra hop through your backend), and you can also take advantage of Stream's UI components. Keep in mind that there will always be some code on your backend infrastructure that will be responsible for providing auth tokens to your users.

Auth and permissions work differently server-side than on the frontend. The fundamental idea is that while your backend is a trusted environment, your web or mobile applications are not considered safe and require more checks.

Because of this assumption, permission checking for backend integrations is straightforward: Stream APIs will always allow API calls that use server-side authentication once confirmed to be valid.

API calls done by the front-end, on the other hand, are always done by a user and not by your server. For this reason, permission checking will be done to avoid security issues like user impersonation, access control to content, etc.

Most real-world applications take a mixed approach and run the most complex integration parts on the backend (e.g. data synchronizations, content moderation, etc.) and all user-related interactions on the frontend directly.

Server Side Auth

Server-side auth is very simple to use, and is the default for all SDK clients that only work server-side like Python, Ruby, PHP, etc. The only thing you need to do is to initialize your Stream client with API key and secret, after that the client will take care of the rest.

Because server-side auth does not have permission checking, it is up to you to enforce logic on your backend such that users cannot access or modify resources that they should not be allowed to. This is done in the same fashion you would use for a web-page or any object on your database.

Client-Side Auth

User authentication works very differently than server-side authentication. When you use server-side auth, we assume the API call originates from a trusted environment and do not apply any permission checks.

This is not the case for web and mobile applications where API calls are performed on behalf of a user. The recommended solution is to provide unique auth tokens for all your users and have Stream perform permission checks to enforce security and avoid abuses.

The recommended flow is the following:

  1. Server-side: setup a Stream API client

  2. Client-side: call your backend to request a user token for the current user

  3. Server-side: generate a user token and return it to the client

  4. Client-side: perform API calls to Stream using the user token

User Tokens

User tokens are JWT tokens that include the "user_id" as payload and that are signed using your Stream API Secret. Optionally you can have tokens expire after a certain amount of time. By default all SDK libraries generate user tokens without an expiration time.

You MUST not include the API secret in your web/mobile application, Official SDK libraries will return an error if you try to create user tokens client-side.

// Server-side
const client = stream.connect(
  'YOUR_API_KEY',
  'API_KEY_SECRET',
  'APP_ID',
  { location: 'us-west' },
);

client.createUserToken(user.id);

// Client-side
client = stream.connect(
  'apikey',
  userToken,
  'appid',
);
                    

Permissions

When API requests are made with user tokens, Stream applies a permission check to avoid common integration mistakes and enforce that users cannot perform certain actions even if they manage to circumvent your application UI.

Default Permissions

By default, all applications are created with a set of policies to guarantee that users have access to only their data, and that they can only create activities on their behalf. Below the code block is the list of permissions.

How to Change Permissions

At the moment, it is not possible to edit your permission policies from the API or Dashboard. If you would like permissions changed for one of your feed groups, please reach out to support@getstream.io with the application ID, feed group name, and requested permission change (global read -or- global read/write). The request must come from an email address with Admin permissions in your Stream organization. We typically respond within 12-24 hours.

Don't Impersonate Other Users

When a user adds an activity to a feed, the actor must contain a reference to the same user.


// ✓ Allowed
feed.add_activity({
  actor: client.currentUser,
  ...other_fields
});

// ✓ Allowed
feed.add_activity({
  actor: client.user(user.id),
 ...other_fields
});

// ⨯ Not Allowed
feed.add_activity({
   actor: user.id,
  ...other_fields
});
                    

Allow Own Feeds

A user can do any operation to any feed that has user id matching its ID. For example:

A user with id tommaso can add activities to feeds like: user:tommaso, timeline:tommaso, notification:tommaso.

Allow Reading Any User Feed

Any feed from the group user is readable by any user. For example, user:jack can read feed user:tom.

Allow Reading Any Activity Detail

Any activity can be read by its ID.

Add Mentions to Any Notification Feed

Any user can add an activity to any feed from the notification group.

Allow Follows & Un-Follows

A user can follow any other feed; the follower feed must match the id of the user. For example: user tommaso can create a follow relationship between timeline:tommaso and user:jack but not the other way around. In simpler terms – you can follow anyone but you can't get them to follow you.

Allow Reading Information of All Users

User data is readable by any other user.

Allow Creating, Updating, and Deleting Your Own User

A user can manage its own user data.

Allow Uploading Files & Images

Any user can update files and images.

Allow Deleting Own Files & Images

A user can only delete files or images that they uploaded.

Allow Processing Own Images

A user can only apply image processing to images that they uploaded.

Allow Creating Reactions and Collection Entries

Users can create reactions and collections. Both must have user_id equal to the ID of the user. For example: user tommaso can create a reaction: "tommaso likes activity XYZ"

Allow Updating and Deleting Your Own Reactions and Collection Entries

Users can create and delete the reactions and collections they created.

Allow Reading All Reactions From All Users

Reactions are readable by any user.

Allow Reading All Collection Entries

Collections are readable by any user.

Allow Scraping Websites for Open Graph Information

Any user can request Open Graph data for any URL.

Any other API call that does not match any of these policies is rejected with a permission error.