Restricting Access Tutorial

Currently users can only publish to their own feeds. What if you want to prevent users from reading the feeds of other users? This is what we are going to implement in this tutorial.

If you missed the previous tutorial, or wish to view the completed code for this part, you can download it all from the GitHub repo.

Using Private Feeds

In a previous tutorial we created a website where users could log in and post to their own comments wall, backed by Feeds. The problem was that anyone with the URL to a particular user's comments wall would be able to view the comments. In this part of the tutorial we will see how private feeds can be used to restrict subscription access only to the logged in user who the feed belongs to.

In order to make a feed private, its ID must be prefixed with private-. Let's first update all references to feed IDs with this, both when subscribing on the client:

1
2
3
const commentsFeed = new Feeds({
  instanceLocator: "YOUR_INSTANCE_LOCATOR_HERE"
}).feed("private-<%= userId %>");

And publishing on the server:

1
2
3
4
feeds
.publish(`private-${req.params.user_id}`, req.body)
.then(() => res.sendStatus(204))
.catch(err => res.status(400).send(err));

Let's see what happens if we open the page in our browser now.

The feed items no longer load! If we open the browser debug console, we will see the error message:

1
Error: Couldn't get token from /feeds/tokens; got 404 Not Found.

It looks like the Feeds client SDK is making a request to /feeds/tokens on your server to get a token, and it's not finding it.

Authorization Endpoints

The reason the client is making the request to /feeds/tokens is because it is attempting to get permission from your server to subscribe to the feed. These permissions are stored as claims in a JSON Web Token, although you do not need to know the details of this.

So in order to give clients permission to subscribe to the feeds, we need to set up a request handler for /feeds/tokens, and respond with a token. The Feeds server SDK provides a way of generating these tokens.

Note: If you want more detail on the authorization system, then read the documentation on private feeds.

Now we can add the handler for /feeds/tokens requests:

1
2
3
4
5
6
7
8
9
10
11
app.post('/feeds/tokens', (req, res) => {
  const hasPermission = (action, feedId) => {
    return action === 'READ' && feedId === `private-${req.session.userId}`;
  };

  feeds.authorizeFeed(req.body, hasPermission)
    .then(data => res.send(data))
    .catch(err => {
      res.status(400).send(`${err.name}: ${err.message}`);
    });
});

Notice that the authorizeFeed function takes a callback. This is where you decide whether or not to grant permission based on the sessions data, and the particular feed that is being read (subscribed to or queried). In this case it is a matter of checking the logged in user ID matches the feed ID they are subscribing to; in other applications it might involve looking up information in your database (e.g. is the logged in user part of the admin group?).

In this callback you can either return a boolean value, or a Promise that resolves to a boolean (in case you need to perform an asynchronous action like a call to a database).

Note: Currently the only action is "READ", which represents requests to subscribe and query feed items; you should always check action === 'READ'. In the future we may support publishing from the client, at which point the "WRITE" action will be added.

Open the web page again -- the subscription should now succeed. If you then modify the URL to the feed of a different user, the subscription should fail.

If you open the browser debug console when you visit the feed of another user, you will see the error Error: Couldn't get token from /feeds/tokens; got 400 Bad Request.. This means that the client is failing to get permission from your server. The private feeds provides a deeper explanation of what these tokens are.

Congratulations you have finished implementing a fully secure private comments wall based on Feeds!

The full working example can be found here.

You have now finished the tutorial. You should have an idea of the kind of things you can build with Feeds. Your imagination is the limit! If you need any further support, then please chat to us on Slack. We would also love to know what you are building!

Did you find this document useful?

We are always striving to create the most accurate and informative docs as possible. If there is something especially wrong (or right) here then please let us know.