Jump to content
  • Status: Moved to Github

When using the REST API, using an OAuth access token, the API will send data the request shouldn't be able to see. For an example, here on the IPS forums, you have a forum:
"Invision Community 5 Modification Questions

This is your opportunity to ask Invision Community developers how to recreate your v4 applications using the new v5 dev tools. Note, only staff members can see and reply to your topic. We will do our best to answer each question in due course."
When you visit the forum on the site directly, it handles permissions properly. You don't see other member topics. On the REST API, when requesting data from /forums/topics, /forums/topics/{id}, or /forums/topics/{id}/posts, it sends data to the access token for that member, but say the data is not what they should be seeing. Those requests are not being filtered by the API for a particular member using the access token.

Is this a bug or intentional? I do not see a permissions structure, like when using an API key, you get an output of permissions for the items. But an oauth token doesn't, so I assume ICS handles this internally. But I don't see it working correctly. Here's an output of a similar forum where users do not have access to see other users topics or posts, but the api request shows this to a test user of a topic they don't have access to:

{
    "id": "7",
    "title": "testing  title 123",
    "forum": {
        "id": "5",
        "name": "Support",
        "path": "Client Support > Support",
        "type": "discussions",
        "topics": "3",
        "url": "https:\/\/localhost\/devboard507\/forums\/forum\/5-support\/",
        "parentId": "4",
        "club": "0"
    },
    "posts": "6",
    "views": "26",
    "prefix": null,
    "tags": [],
    "firstPost": {
        "id": "62",
        "item_id": "7",
        "author": {
            "id": "2",
            "name": "Donald",
            "title": null,
            "formattedName": "Donald",
            "primaryGroup": {
                "id": "3",
                "name": "Members",
                "formattedName": "Members"
            },
            "joined": "2025-04-08T00:50:24Z",
            "reputationPoints": "0",
            "photoUrl": "data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201024%201024%22%20style%3D%22background%3A%23ac62c4%22%3E%3Cg%3E%3Ctext%20text-anchor%3D%22middle%22%20dy%3D%22.35em%22%20x%3D%22512%22%20y%3D%22512%22%20fill%3D%22%23ffffff%22%20font-size%3D%22700%22%20font-family%3D%22-apple-system%2C%20BlinkMacSystemFont%2C%20Roboto%2C%20Helvetica%2C%20Arial%2C%20sans-serif%22%3ED%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fsvg%3E",
            "photoUrlIsDefault": "1",
            "coverPhotoUrl": "",
            "profileUrl": "https:\/\/localhost\/devboard507\/profile\/2-donald\/",
            "posts": "26",
            "profileViews": "4",
            "customFields": {
                "1": {
                    "name": "Personal Information",
                    "fields": {
                        "1": {
                            "name": "About Me",
                            "value": null
                        }
                    }
                }
            },
            "rank": {
                "id": "2",
                "name": "Apprentice",
                "icon": "https:\/\/localhost\/devboard507\/uploads\/monthly_2025_04\/3_Apprentice.svg",
                "points": "90"
            },
            "achievements_points": "135",
            "allowAdminEmails": "1",
            "completed": "1"
        },
        "date": "2025-04-25T01:01:57Z",
        "content": "<p>testing  description 456<\/p>",
        "hidden": "",
        "url": "https:\/\/localhost\/devboard507\/forums\/topic\/7-testing-title-123\/?&do=findComment&comment=62",
        "reactions": []
    },
    "lastPost": {
        "id": "67",
        "item_id": "7",
        "author": {
            "id": "3",
            "name": "The Guy With The Hat",
            "title": null,
            "formattedName": "The Guy With The Hat",
            "primaryGroup": {
                "id": "6",
                "name": "Moderators",
                "formattedName": "Moderators"
            },
            "joined": "2025-04-25T02:41:03Z",
            "reputationPoints": "0",
            "photoUrl": "data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201024%201024%22%20style%3D%22background%3A%23c46295%22%3E%3Cg%3E%3Ctext%20text-anchor%3D%22middle%22%20dy%3D%22.35em%22%20x%3D%22512%22%20y%3D%22512%22%20fill%3D%22%23ffffff%22%20font-size%3D%22700%22%20font-family%3D%22-apple-system%2C%20BlinkMacSystemFont%2C%20Roboto%2C%20Helvetica%2C%20Arial%2C%20sans-serif%22%3ET%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fsvg%3E",
            "photoUrlIsDefault": "1",
            "coverPhotoUrl": "",
            "profileUrl": "https:\/\/localhost\/devboard507\/profile\/3-the-guy-with-the-hat\/",
            "posts": "2",
            "profileViews": "3",
            "customFields": {
                "1": {
                    "name": "Personal Information",
                    "fields": {
                        "1": {
                            "name": "About Me",
                            "value": null
                        }
                    }
                }
            },
            "rank": {
                "id": "3",
                "name": "Newbie",
                "icon": "https:\/\/localhost\/devboard507\/uploads\/monthly_2025_04\/1_Newbie.svg",
                "points": "0"
            },
            "achievements_points": "10",
            "allowAdminEmails": "1",
            "completed": "1"
        },
        "date": "2025-04-25T02:41:56Z",
        "content": "<p>refgyugboyuafgyuavgciayhdgfaiyfup<\/p>",
        "hidden": "",
        "url": "https:\/\/localhost\/devboard507\/forums\/topic\/7-testing-title-123\/?&do=findComment&comment=67",
        "reactions": []
    },
    "bestAnswer": {
        "id": "63",
        "item_id": "7",
        "author": {
            "id": "2",
            "name": "Donald",
            "title": null,
            "formattedName": "Donald",
            "primaryGroup": {
                "id": "3",
                "name": "Members",
                "formattedName": "Members"
            },
            "joined": "2025-04-08T00:50:24Z",
            "reputationPoints": "0",
            "photoUrl": "data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201024%201024%22%20style%3D%22background%3A%23ac62c4%22%3E%3Cg%3E%3Ctext%20text-anchor%3D%22middle%22%20dy%3D%22.35em%22%20x%3D%22512%22%20y%3D%22512%22%20fill%3D%22%23ffffff%22%20font-size%3D%22700%22%20font-family%3D%22-apple-system%2C%20BlinkMacSystemFont%2C%20Roboto%2C%20Helvetica%2C%20Arial%2C%20sans-serif%22%3ED%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fsvg%3E",
            "photoUrlIsDefault": "1",
            "coverPhotoUrl": "",
            "profileUrl": "https:\/\/localhost\/devboard507\/profile\/2-donald\/",
            "posts": "26",
            "profileViews": "4",
            "customFields": {
                "1": {
                    "name": "Personal Information",
                    "fields": {
                        "1": {
                            "name": "About Me",
                            "value": null
                        }
                    }
                }
            },
            "rank": {
                "id": "2",
                "name": "Apprentice",
                "icon": "https:\/\/localhost\/devboard507\/uploads\/monthly_2025_04\/3_Apprentice.svg",
                "points": "90"
            },
            "achievements_points": "135",
            "allowAdminEmails": "1",
            "completed": "1"
        },
        "date": "2025-04-25T01:02:05Z",
        "content": "<p>gvfuyhfgeuhdcbvadhuvfgeqwf<\/p>",
        "hidden": "",
        "url": "https:\/\/localhost\/devboard507\/forums\/topic\/7-testing-title-123\/?&do=findComment&comment=63",
        "reactions": []
    },
    "locked": "",
    "hidden": "",
    "pinned": "",
    "featured": "",
    "archived": "",
    "poll": null,
    "url": "https:\/\/localhost\/devboard507\/forums\/topic\/7-testing-title-123\/",
    "is_future_entry": "0",
    "publish_date": "2025-04-25T01:01:57Z"
}

User Feedback

Recommended Comments

Nuclear General

Clients

I ended up doing a work-around myself, just so the topic id can't be changed in the url to one they shouldn't have access to, and be able to view the topic, bypassing permissions.
I came up with this:

			// Check if this topic is in the sensitive category (ID 5)
			if (isset($topic['forum']['id']) && $topic['forum']['id'] === '5') {
				// Get current OAuth user info
				$currentUser = Application::whoAmI();
				
				// If we couldn't get user info or user is not logged in
				if (empty($currentUser) || empty($currentUser['id'])) {
					Output::i()->error('api_no_permission', '2M121/9', 403, '');
					return;
				}

				// Initialize permission flag
				$hasPermission = false;
				
				// Check if user is the original author
				if (isset($topic['firstPost']['author']['id']) && $topic['firstPost']['author']['id'] === $currentUser['id']) {
					$hasPermission = true;
				}
				
				// If not the author, check if user is an admin or moderator
				if (!$hasPermission && isset($currentUser['primaryGroup']['id'])) {
					if (in_array($currentUser['primaryGroup']['id'], ['4', '6'])) { // Admin or Moderator groups
						$hasPermission = true;
					}
				}

				if (!$hasPermission) {
					Output::i()->error('api_no_permission', '2M121/10', 403, '');
					return;
				}
			}

Marc

Invision Community Team

What version are you using there? I ask as there is a known issue in 5.0.7 beta 1, which was quickly replaced with beta 2.1

Nuclear General

Clients

Well I was using version 5.0.5 for my testing of the API. I just upgraded that board to the 5.0.7 Beta 2.1, issue still exists. I also noticed, after I upgraded my board to beta 2.1, beta 3 was released. I upgraded to that as well, and issue still exists.

Basically, with the API, you set it up to retrieve your topic and posts for the topic, the url will essentially look like this: module=forums&controller=topics&do=viewTopic&id=7 So, in the url, you change the topic id to one you know you cannot and should not be able to access, and in doing so, you gain access to that topic information, bypassing the permissions of that topic/forum/category or whatever else.

Would you like to see my code for this particular issue, so you can see how it is being done?

Nuclear General

Clients
(edited)

However, I forgot to mention this, when displaying the content on page for a particular forum that has restrictive access, it displays it just fine.

As by this screenshot (I do have an issue with the pagination screwing up, not sure how or why it is doing that, but I will tackle it lol)image.png

And, if you are admin or mod, it shows them all, like it shouldimage.png

Edited by Nuclear General

teraßyte

Clients

The API does have a check if the user has permission to see the topic, but it is only available for requests made using an OAuth Access Token for a particular member, not using an API Key or the Client Credentials Grant Type.

Based on what you're saying, you're using the Client Credentials Grant Type. That won't trigger the permission check because $this->member is empty:

		if ( $this->member and !$item->can( 'read', $this->member ) )
		{
			throw new OutOfRangeException;
		}

Nuclear General

Clients
(edited)

I am using the Authorization Code grant type, not Implicit, not Resource Owner Credentials, or Client Credentials. Only the Authorization:

image.png

Edited by Nuclear General
(it added the image twice, removed it)

teraßyte

Clients

The permission check works only if you use the Resource Owner Password Credentials option. Without that, the API has no idea about the logged-in member's permissions.

Nuclear General

Clients

Ok, so what is the actual difference then between each one? I thought the Authorization Code would be the better option, because it provides server-side security, along with proper permissions?