Handling empty included results due to authorization

Hi; I’m looking for advice in re: how best to represent data that may not be available due to authorization limits. For example:

I have a Person datatype, and that person can have many friends. You can search for people, and you’ll get a response along the lines of:

{
  "type": "person",
  "id": "1",
  "links": {
    "self": "/persons/1"
  },
  "attributes": {
    "name": "Johnny Rotten"
  },
  "relationships": {
    "friends": {
      "links": {
        "self": "/persons/1/friends"
      }
    }
  }
}

… friends may or may not be available to the requestor, depending on whether they have rights on person 1’s account.

Now, let’s say I don’t have permission to see person 1’s friends. If I call “/persons/1/friends”, I’ll get a 401 response. But what should happen if I call “/persons/1?include=friends”? It’s only the additional information that isn’t allowed, not the main resource, so it feels very weird to respond with a 401. Similarly, it seems wrong to claim that person 1 has no friends by handing back "data": [] in the friends relationship block, since it implies something that may or may not be true.

The only thing I can think of doing would be to hand back an empty array, and also hand back a meta field that somehow calls out the information isn’t available to the caller.

Thoughts?

maybe it could be considered as a partial success in this case?
see this post

206 doesn’t seem apropos. It’s a nice idea, but it seems fairly tied to range requests, and therefore inappropriate.

I’m in the same situation, having implemented a permissions system where after user A comments on user B’s post, user B might make that post private. /api/comments/{comment_id} returns a comment like:

{
    "data": {
        "type": "comments",
        "id": 123,
        "attributes": {
            ...
        },
        "relationships": {
            "author": {
                "data": {
                    "type": "users",
                    "id": 456
                }
            },
            "post": {
                "data": {
                    "type": "posts",
                    "id": 789
                }
            }
        }
    }
}

So if I visit /api/…/comments/{comment_id}?include=posts I’m not sure what to put in the “included” array after user B’d post 789 becomes private. I think my choices are:

  1. return the relationship’s post’s id but don’t include the post in the “included” array when ?include=posts is requested (I think this violates JSON API wanting every included item for corresponding relationship ids to be listed when requested)

  2. return 200 for non-include requests but return “400 Bad Request” for include requests if the server can’t fulfill the request because the included post is private: http://jsonapi.org/format/#fetching-includes (however this makes returning collections of comments brittle because one private post could kill the whole response)

  3. don’t return the comment at all (have the comment inherit the post’s privacy), however this makes it hard for users to delete their own comments after related posts become private (because they can’t see their own comments after that)

  4. list the post in the included array but only include the type and id, leaving out attributes (this could crash clients that aren’t expecting this behavior)

  5. don’t include the “post” key in relationships, which avoids it being included (this could crash clients that aren’t expecting this behavior)

  6. include the post in “included” but set all of the attributes to their default values (empty strings etc) to obscure them. this prevents clients from crashing but could be confusing for users

I’m leaning towards #1 and making clients check for the posts’s existence in the “included” array. If they forget to check, their app will crash if it’s expecting an included post there. This is how my ORM is behaving currently due to implementing permissions.

Update - this message recommends failing completely, however that would be brittle for collection responses: Multi-status responses (partial success in particular)