2

The way I created my rest api is the following:

/api/users/{id}
/api/users/{id}/items/{itemId}

But I also have URIs like this one:

/api/items/{itemId}

It's a bit confusing to me how to handle the item authorization in this case.

I don't want to send every request for a resource to the /api/users/{id}/items/{itemId} URI, but I also want to make sure that a user can't access an item it's not associated with.

My idea is to use AOP, and for every request to /api/items/{itemId}, get the user from the JWT authentication token, and decide whether or not the user is authorized to access the given item.

Is this approach ok, or are there better alternatives?

  • 1
    if you think about it you have the same problem in the first example too – Ewan Apr 2 '17 at 11:51
  • @Ewan Yes, indeed. – user1437649 Apr 2 '17 at 12:00
3

Yes, your approach is OK and commonly used.

In fact, if you model your code right, you are likely to be using the same code for access authorization for both cases anyway.

Very simplified example:

public Item getUserItem(int userId, int itemId) {
    Item item = loadItem(itemId);

    if (userId != item.ownerId()) {
        // fail, access not allowed
    }

    return item;
}

// URI: /api/users/{id}/items/{itemId}

Item getForUser(int id, int itemId) {
    return getUserItem(id, itemId);
}

--------------------------------

// URI: /api/items/{itemId}

Item get(int itemId) {
    return getUserItem(
        JwtParser.parse(headers.Authorization).userId,
        itemId
    );
}
  • Well, that's not exactly AOP, but It's a easier solution. – Laiv Apr 2 '17 at 17:13
1

You could use a REST policy enforcement point (PEP) that would call out to an external policy decision point (PDP) (authorization engine) that would decide for you based on the user ID and the resource ID whether access should be granted. The REST PEP could either be a message interceptor or an annotation on the code.

0

In the first case, what is preventing me as user 1 from sending /api/users/2/items/121442 and get an item I have no access to?

If you're sending credentials as http headers (for example) as is common there's no need to send them in the request as well. So you'd have /api/items/121442 and request headers USER_ID=Johndoe and USER_PASSWORD=12345 (encrypted of course, and use https). There's no need to send the userid in the request uri as well as it's already known, and better yet your authentication system can change it from an id (say a username like here) to an id (1) that's known only to your internal system, providing extra security.

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.