Elevating Permissions on Service Files
Caution: this content was last updated over 4 years ago
Permissions govern who or what can access the data and features in NetSuite. When working on web stores, you sometimes need access to data that the current user may not have access to. In these scenarios, you can explicitly create exceptions and elevate the permissions on your service files.
As a reminder, services are a special kind of SuiteScript file that handle HTTP requests sent by the frontend. They are primarily used to process create, read, update and delete (CRUD) operations on data stored in your NetSuite account.
The sample code in this tutorial uses SuiteScript 1.0 and service controllers. This is fine for newer versions, but versions older than Vinson (2016.2) will not be able to run it as-is. However, the concept of elevated permissions still applies.
What Happens When a Service Runs
Service files can be sent requests like RESTful endpoints, and, in terms of Backbone architecture, are usually attached to models and collections via their url
and urlRoot
properties.
When this happens, NetSuite executes the request using the service against the role of the user, which for shoppers will likely be some form of Customer Center role. Customer Center roles have pre-defined access to certain kinds of records and actions — this will be quite limited, to things we expect shoppers to do. If the user isn’t logged in, then the default will also likely be a Customer Center role.
If the user is allowed to perform the action, it executes successfully; if they are not, it doesn’t and a permission violation is returned.
Permission Violations
If you are reading this, then it’s likely you’ve come across this problem. You’ve written a service that tries to access a record the user is not allowed to access, or you’ve tried to perform an action not permitted by their role.
When this happens, you’ll see the following error in your browser’s developer tools:
{"errorStatusCode":"403","errorCode":"ERR_INSUFFICIENT_PERMISSIONS","errorMessage":"Insufficient permissions"}
General Approach
When the violation happens, the first thing you should do is double-check whether they need to be performing this action on the record. There will be a good reason why the action is not permitted, so you should make sure you’ve written your service correctly and they’re trying to access the right record in this way.
Next, the general solution is to elevate the permissions. What this means is that you grant access beyond the normal scope of their role. When you do this, it is important that you maintain high standards of security and provide the narrowest additional access required.
Broadly speaking, this can mean:
- Assigning a user a specific additional role
- Customizing (or creating a custom version of) the current user role and applying it to all users of that type
- Elevating the permissions of the specific service file, so that this one service runs at a higher permission
As you can infer from this article’s title, we recommend the third for most scenarios because it is the most narrow.
When you elevate the permission of a service file, you tell that specific file to run at higher permissions. This has the benefit of not granting blanket access to the record or that action throughout the entire web store — it applies only to this specific service file.
To give you an example, location records are used to store information on things like your warehouses, offices, retail locations, etc. These are not typically available to shoppers using the Customer Center role. But, for the store locator functionality to work, it needs to access these records. Well, we certainly don’t want to grant shoppers access to all of these records, so what do we do?
Well, we create a special service file which contains our SuiteScript for implementing the store locator functionality. It requests location records of the kind we specify and nothing more. When it has been deployed, we create a new role that grants access to those records. Then, rather than apply this role to the shopper user, we apply it to the service file, so we’re saying, “You access these records, but only when you use this service” — and that service is set up only to search for retail store locations.
Example: A Simple Location Service
To test this, we will need to do four things:
- Deploy source code that tries to access records not typically available to customers (such as GETs on location records)
- Set up some locations in your NetSuite account
- Create or use a role that grants access to these records (there is a default role called Advanced Customer Center that does this)
- Modify the record for the service file so that this role is specified in Execute As Role
- For the purposes of this tutorial, we will also need to use Run Script Without Login because we will be allowing anonymous users use this service
For brevity, the source code for this example is available in /samples/2017-2-kilimanjaro/ExampleLocation@1.0.0 in the GitHub repo. It’s written for the Kilimanjaro (2017.2) release of SuiteCommerce Advanced, but it is compatible with a number of versions and can be adapted for any version released after Mont Blanc (2016.1). Make sure you put it in your source code, update your distro.json to include it in modules
, ssp-libraries
, and shopping.js
, and deploy it up to your test site. If you’re using an extension, eg for SuiteCommerce, then you can adapt the code to fit your site.
To set up some locations, you will need to go to Setup > Company > Locations if you don’t already have them. For the purpose of this tutorial, they will need to have values for at least Name, Longitude and Latitude.
For the role, you should already have a role called Advanced Customer Center. If you do not, you will need to create a new role in Setup > Users/Roles > Manage Roles, which has only the Permissions > Lists > Locations > View permission.
Before elevating the permissions, quickly look at the code. You can see in the router that we set up a new route for examplelocation/:id. This’ll trigger a model and view, which calls the service. You can see in the backend model, we’re going to perform a record search using the ID passed in the URL.
Accordingly, if you have deployed the code, you can hop right over to the URL on the frontend of your site, substituting the :id with an internal ID of a location record in your application.
It should fail. If you look in your browser’s developer tools, you should see the XHR for ExampleLocation.Service.ss has failed, returning the familiar ERR_INSUFFICIENT_PERMISSIONS
error. Thus, the server understood and attempted our request, but the application denied it because of the current user’s permissions.
To remedy this, we will now elevate the permissions of this service file.
- Look up the service file in the application (eg search for Example.Location.Service.ss) and edit its record
- Go the Permission tab
- Check Enabled
- Select Advanced Customer Center (or your custom role) in the Execute as Role dropdown
- Check Run Script Without Login (this is required for services you want to offer that do not require a user to log in)
- Click Save
Back on the frontend, if you hit your URL again, you should see the service cool succeed and your location’s data appear.
For more information, see the following documents in SuiteAnswers:
- Set Execute as Role Permissions for .ss and .ssp Files
- Records that Support Execute as Role Permissions
Security Reminder
As a reminder, elevating permissions on a service file is usually the preferred way of dealing with this sort of problem. It is a lot more surgical as it gives access to record data only in the specific scenario that it is requested. If you were to apply the additional permissions to all users in a certain role, for example, you risk exposing data in scenarios you didn’t intended and that could cause serious security problems.
As mentioned above, this should be used carefully and only when you’re sure it should be used in this way.
When specifying which role to use, the role should be as custom and specific as possible. It is perfectly fine to create a new role which has the single permission the service file needs for this one scenario. Be careful when allowing users to do anything other than view/search records.
Finally, with Run Script Without Login, remember that this means that anyone who can access your site will be able to access the specified records. Consider requiring the user register/login first.
Code samples are licensed under the Universal Permissive License (UPL), and may rely on Third-Party Licenses