Hi everyone!
I’m stuck with roles management. I want to implement a very basic case:
Revoke access for everything from the mobile clients SDK except custom service invocation.
I found the following article:
Data Security | Limit Data Service API Access to Cloud Code Only where you suggest to remove ‘user-token’ from every API request, that sounds very strange for me. I do want to know the user context of the running request, I do want to run some extra business logic validation depends on the user role. Even more, I do want to use the REST API console in the web portal.
If I allow some operations for my custom role, it became to the security issue. Every user will be able to use Backendless API using the user-token, e.g. retrieve the data from the DB, use any of built-in module from the SDK.
The question is the same with the name of the article above?: Is there a normal way to restrict access for my custom role, but override permissions when the SDK is used from the cloud code? In other words, I want to save the user context for every API query and allow to execute everything from the server (cloud code)?
Thanks in advance!
Let me make sure I understand the scenario:
Suppose there is some API you want to restrict the usage of, say it is Find from a table
, for brevity, let’s call this operation X
. From what I understood, you want to:
- allow invocation of X only to the custom role and Cloud Code
- deny invocation of X for all other use-cases
Is this correct?
Mark
Hello, @mark-piller!
Thank you for the reply. Let me rephrase the initial condition I want to achieve.
- I have the custom API endpoint which queries the DB for some records under the hood (X operation)
- I have a custom user role, let’s call it “Customer”
- Customer has no access to any direct invocations. He can trigger the X operation only (API, but not to query the DB from the mobile SDK)
- X operation is able to query the DB because the action executes from the cloud code with the “Customer” context.
Current behaviour: X operation returns “Permission denied” error because of “Customer” context. But I don’t wan’t to log out that user in every API request. And I do want to save user-token to avoid “anonymous” API invocations.
Thanks!
Let’s start with (3) as the first two points do not require any configuration changes. Do you know how to restrict the role from direct API access? If not, open the Users
screen and select Security Roles
. Select your Customer
role and disable all the operations you do not want the role to be able to use.
That is what has been done already. All permissions are denied:
Now, I’m trying to invoke the endpoint of X when a customer is logged in, and it fails because the customer doesn’t have access to anything (returns an empty array).
The picture when a user is logged in:
The screenshot proves the data exist in the DB (anonymous invocation, where ServerCodeUser applies automatically):
Do you have a test account I can try it with?
Sure. You can you test2@test.com/qwerty account. Try to invoke CustomerService → getRestaurants GET method. It queries the “Restaurant” table where you can see two records. My pictures above show responses for both cases: when a user is logged in and when he is not. In the second case, ServerCodeUser is used in the cloud code that is expected behaviour.
Could you please let me know your application ID?
Replied in Slack. Thanks.
Hi Mark,
I prepared one more example. Please review the screenshot with permissions for two users. The access defined at the table level, that querying in X operation.
- lihachevra@gmail.com
- lihachevra+1@gmail.com
The password for them is the same: 123123qwe
The corresponding API results based on logged in user:
and
To test you can use the following deployed API:
https://api.backendless.com/{AppId}/{CloudCodeId}/services/POSService/list
As you can see, when the user doesn’t have ‘Read’ permission, the database returns nothing. But it was queried from the cloud code (not from the client SDK where it is expected behaviour).
Please help to solve that because it is the blocker for us.
Thanks!
Hi Boris,
I have made the changes to get the scenario working as expected in my app. Would you like me to replicate the changes in yours or just describe what should be done?
Regards,
Mark
Feel free to apply changes for quickly resolution. Btw, the description may be helpful in any case, e.g. for others.
Thanks!
Hi Boris,
I just applied the changes. Here’s what I see:
An unauthenticated user cannot get restaurants by using the direct API:
A logged-in user with the Restaurant
role cannot get restaurants by using the direct API:
An unauthenticated user cannot get data from the API service:
A logged-in user with the Restaurant
role can invoke the API and get the data:
Hope this is what you wanted. Please let me know and I will provide a summary describing the changes.
Mark
@mark-piller,
I’m very sorry, but I’m confused. Could you please configure one more time?
Please notice, the direct API should be not available with any API key, including iOS, Android, etc. (except the Server Code key).
Perhaps, I made wrong changes because I’m still able to view the data
Thanks in advance!
Try now.
Boris Velvetech
The main idea is you have to add GRANT permission for Authenticated user for specific table or on a top level.
Hi, @oleg-vyalyh and @mark-piller!
Thank you for the reply and your help. At the first glance, the solution looks like what we need.
But the resolution is not obvious. In the article prepared by your team in 2019 you suggested to hack the SDK or do not sent the “user-token” in case of API requests. I think the article should be updated… Could you please explain how it works and why granted permission for the specific role and for the authenticated user allows to use direct calls within server-side code, but closes the same behaviour for other security keys?
I let you know if find any more troubles (I want to test the same behaviour with the “Files” module instead of DB queries).
Thank you!
Hi @oleg-vyalyh and @mark-piller!
I decided to start from scratch and stuck again. I created a new table and implemented a simple service, that returns the array with the data of that table.
I tried to configure permissions (Auth role has access to retrieve the data, the Customer role has access to retrieve the data).
The problem occurs when “Customer” role uses the direct DB API. The response contains the data
The cloud code returns the expected result:
The table has the following permission configuration:
If I deny access for the Customer role, the cloud code returns empty response, and Direct access continues working.
If I deny access for the particular user (test4@test.com in the current example), the response contains no data in any case.
What needs to be changed to close direct access to the database?
Please use test4@test.com/123123qwe user for testing purposes if need it.
Thank you!
Hello @Boris_Velvetech
Let’s start with which users or roles you want to keep access to the database?
By prioritizing permissions, the permission for a role will take precedence over the permission for an api key. Therefore, you can disable the Retrieve operation for the CloudCode role at the top level Manage> Security Roles.
At the same level you must allow the “Retrieve” operation for the Customer role. In this way, only authorized users with the Customer role will be able to access table.
Regards,
Inna
Hello, @Inna_Shkolnaya!
I want to keep direct access to the database for the CloudCode only.
I want to restrict direct access for all roles except the CloudCode. I.e. a frontend app (mobile) with the role “Customer” should be able to trigger a custom service and retrieve the result, but should not be able to use a direct API from the SDK to get data from the DB/file storage/etc.
Thanks.