0

Intro

JSON:API is declared as a must-have for decoupled Drupal websites.

While I completely (well, I hope so) understand the built-in Drupal permissions/access restriction system, I have a specific use-case and I would like to understand how can I implement what I need with so much advertised JSON:API approach taking into account potential security issues described below.

Current implementation

So far I was only able to accomplish the task using Views REST display, disabling default JSON:API endpoints and creating my own JSON:API resources, because Views allow me to have hard server-side restrictions while filtering the content and custom JSON:API resource gives me control over the content I deliver.

Disposition

Well, so there are 2 sections on my website:

  1. There is a public section with Articles. Any logged-in user can see all the published articles. I can deliver this page using Views as a separate page, Views REST or JSON:API to some PWA, doesn't matter. So far so good.
  2. There is a restricted section on the website (kind of dashboard) with the list of the articles created by the currently logged in user. Not only the User is able to see the publicly available fields, but some private fields too. User should not be able to see the other users' articles. For the purpose of this question, let's say that seeing all the articles in general via [1] route is not a problem from security standpoint, but seeing all the articles per user is a problem. In general, I do not what the users to know who is the author of each article.

Problem

We need to somehow separate an access restrictions for (1) and (2), even though both operations are going as 'view entity'. But (1) delivers all the articles regardless of the author, (2) delivers articles owned by the currently logged in user only.

I can build a view for a public section, but I like to use a PWA for my dashboard, so the articles are delivered using JSON:API there.

Problem from permissions standpoint

Now I can not use default permissions settings (i.e. adding/removing 'View Article' permission) because this breaks route (1) [means: users without 'View Article' permission can not see the list anymore] At the same time, I can not just rely on the query when returning the articles for the dashboard request (2) of some specific user, because let's say some advanced user sees the parameters I include in the request, he changes those parameters and - boom - sees the articles created by the other user, which is a security breach.

Problem with different fields visibility

Same question applies to the fields. When I show the (1) route (all articles), I might need to output public fields only, while when I deliver the content to (2) [per-user dashboard], I need to deliver all the fields.

Final question number one

So my question is: how can I solve this? How can I deliver same content using JSON:API with checking the owner server-side, not passing the owner as a parameter, and without restricting an access using built-in permissions system?

[EDIT] Final question number two

Is there a way for me to declare a security context (read: declare needed permission to be checked against each entity) before actually outputting/processing the data using JSON:API? Good example would be custom route with custom permissions check, while JSONAPI, as far as I am concerned, only consider CRUD entity-related permissions based on GET/POST/PUT/DELETE method being used.

1
  • Not only the User is able to see the publicly available fields, but some private fields too. If you set custom field permissions so that users can only see the values of private fields on articles for which they are the author, JSON:API will respect this, and you can do everything in JSON:API. For an example of setting up field permissions, check out the Examples module. Sep 24 at 3:23

1 Answer 1

1

JSON:API is declared as a must-have for decoupled Drupal websites.

This is not true. Decoupled Drupal can take many forms, including

  • REST
  • JSON:API
  • GraphQL

JSON:API is pretty great, but if it doesn't fit your use case, you can build a complete decoupled website and never touch it.

For a comparison of these solutions, see the book Decoupled Drupal by Preston So.

How JSON:API handles access control

In Drupal, JSON:API respects whatever permissions/access control is set for users. The system was designed this way so that if you already have a functioning Drupal website with access control properly set up, then you can enable JSON:API and it will have the same access control with no additional work required.

So my question is: How can I deliver same content using JSON:API with checking the owner server-side, not passing the owner as a parameter, and without restricting an access using built-in permissions system?

You need to use the built-in permissions system to restrict content with JSON:API. That's the way it is designed in Drupal. So the answer to "without restricting access using the built-in permission system" is "you can't."

If you want to make arbitrary rules for access, consider REST or GraphQL.

You could alternately use custom JSON:API Resources, but then whatever data you want to hide is probably exposed automatically by JSON:API, so you need to lock it down with JSON:API Extras, and then the question is why are you using JSON:API instead of REST for your particular use case?

2
  • >>This is not true Well, at least Dries says so dri.es/headless-cms-rest-vs-jsonapi-vs-graphql Okay, if I may rephrase the question, how can I declare a security context or declare needed permission to be checked against each entity before actually outputting the data using JSON:API? Good example would be custom route with custom permissions check, while JSONAPI, as far as I am concerned, only consider CRUD permissions based on GET/POST/PUT/DELETE method being used. (also updated the original question). Sep 23 at 17:10
  • @AlexSmirnoff One question per post. This is not a discussion site. Since there is a concept of "accepted answer" here, multiple questions make it impossible to determine the accepted answer. That said, to answer your second question, as you note JSON:API considers the CRUD (entity-level) permissions only. So if you want to do a custom route, you have to block everything that you don't want shown in JSON:API (using JSON:API Extras or custom code) and then create a custom resource, as I said in the last paragraph of my original answer. This is a limitation of JSON:API, but it is by design. Sep 24 at 3:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.