[Article] An Overview of Scope Management with WSO2 API Manager
- Chamin Dias
- Associate Lead - Marketing - WSO2
Introduction
Today, most organizations expose their services via an API-driven business model. Some of these APIs might need to be used by both internal and external consumers. Since an organization cannot expose all services of an API to the public, they need to restrict access to the most valuable services only to authorized parties.
If revenue is generated by exposing APIs, it’s important to make sure that only allowed parties have access to the respective resources. In this scenario, securing APIs is an important task because unauthorized access to resources will affect revenue and eventually have a negative impact on the organization. Even though it may seem difficult to do, it’s mandatory to have a security solution that can facilitate fine-grained access control to every resource of an API. WSO2 API Manager has addressed this complex requirement with its ability to secure APIs and associated resources using OAuth 2.0 scopes.
Overview of OAuth scopes
When managing distributed web authorization, OAuth 2.0 becomes a very useful standard. This way, authorization is implemented using an access token. Users need an access token to consume the respective resources. A scope allows you to specify what type of access is specifically required per resource. The scope of an access token defines what the access token can do and what resources it can access.
In other words, a scope will limit access for OAuth tokens, but it will not grant any additional permission levels beyond what the user has already.
When it comes to securing resources of an API, scopes can be a useful mechanism. A scope enables fine-grained access control for each resource of the API based on specific consumer roles. This way, when a consumer invokes the API with an access token, it will ensure that only the allowed resources can be accessed by the consumer.
Scope management in WSO2 API Manager
WSO2 API Manager provides a way to enforce role-based access control mechanism. This will facilitate its users to implement a role-based access control mechanism for each resource in their API.
Example scenario
Here is an example that explains the use of scopes via a real-world scenario:
There is an API named “ShoppingCartAPI” to handle some operations related to a supply chain. This API can be used to view and update an item list. Moreover, it can handle orders as well (creating and viewing orders). The API has been designed to facilitate those requirements. It has GET and POST resources for both orders and items.
In this scenario, the management has decided to implement role-based API resource access to ensure fine-grained access control for each of these API resources. Management has decided to assign roles to the users based on their job. They have used WSO2 API Manager to manage the users and roles as well.
Refer to the official documentation of WSO2 API Manager to find more information about creating users, creating roles and assigning roles to users.
There are four users in this example namely Alex, Paul, Rick, and Harry. They will be consuming “ShoppingCartAPI” to carry out the tasks assigned to them. These users have the following roles assigned to them. They are the consumers of “ShoppingCartAPI” to perform specific tasks.
- Manager role - Alex
- Agent role - Paul
- Customer role - Rick
- Manager role and agent role - Harry
Management console of WSO2 API Manager addresses these types of requirements. For example, the administrator can assign “manager” and “agent” roles to Harry, as shown in Figure 1.
Figure 1: Assigning roles to users
Based on the decision of the management, they will allow access to each API resource as depicted in the following table.
API | ShoppingCartAPI | |||
Resource | Orders (/orders) | Items (/items) | ||
Action | GET | POST | GET | POST |
Roles | manager, agent, customer | agent | manager, agent | manager |
Table 1: Details of API
API developers in the company have created and published the API using WSO2 API Manager. This API needs to have four resources based on the requirement. Corresponding HTTP verbs are used in the resources section of the API.
Figure 2: HTTP verbs and resources of the API
Here is the mapping between scopes and roles:
Scope key | Roles |
item_view | manager, agent |
item_add | manager |
order_view | manager, agent, customer |
order_add | agent |
Table 2: Scope to role mapping
To bind each scope with each API resource, API creators should create scopes by clicking “Add Scopes” in the “Manage” tab while creating the API. The following details need to be filled to add a scope.
- Scope Key - This is a unique key for identifying the scope. Usually, it is not meant to be reader-friendly. Some users prefer to use a part of the API name as a prefix of the scope key for uniqueness.
- Scope Name - This is a human-readable name for the scope. Usually, it will tell you what the scope does.
- Roles - This is where the roles are listed (scope to role mapping). If there are multiple roles, those should be specified in a comma-separated list.
- Description - If needed, a longer description about the scope can be mentioned here.
Figure 3: Adding scope for viewing items
Figure 4: Scope for adding items
Figure 5: Scope for viewing orders
Figure 6: Scope for adding orders
Once the scopes are added, it will be shown as follows.
Figure 7: Scope list for the API
Then API publisher can include the corresponding scope in front of the respective HTTP verb. Here, the scope name is shown when adding scopes for each HTTP verb.
Figure 8: Add corresponding scope for each resource
Once that is done, and when the API is published, we can see that the scope key is displayed in front of each HTTP verb and resource combination.
Figure 9: Scope keys for each resource
We have completed the API creation.This API is now available in the API Store of WSO2 API Manager.
To consume the API, you would need to obtain an access token. To this end, as the next step, we need to create an application in the API Store of WSO2 API Manager, subscribe that application to “ShoppingCartAPI” and generate the relevant consumer-key and consumer-secret. This is a task that needs to be carried out by an application developer. Once the consumer-key and consumer-secret is generated (for the application), we can proceed and obtain a token for “ShoppingCartAPI”.
In this example, we will be using password grant type to obtain the token. WSO2 API Manager has a token API to handle key generation related scenarios. Refer to official documentation to find out more information about token generation and grant types.
When generating the access token, API consumers have to mention the scopes very clearly. This is where the real usage of scopes comes into play. In other words, requesting for scopes is a part of the token generation logic.
In this example, there are four users who consume the API (i.e. API consumers). According to Table 1 and Table 2, we can come up with the following:
- “GET” orders is allowed to Alex, Paul, Rick, Harry
- “POST” orders is allowed to Paul and Harry
- “GET” items is allowed to Alex, Paul, Harry
- “POST” items is allowed to Alex and Harry
Let’s explore how WSO2 API Manager ensures that users can consume the allowed resources only.
Sending a request to the token API (this token is already embedded in WSO2 API Manager server) and will be as follows:
For a token with a single scope
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=<scope key>" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Here we can specify the scope(s) in the request. If there is a need to obtain a token with multiple scopes, the request would be in the following format. This way, a user can get a single access token that can be used to consume multiple resources in the API.
For a token with multiple scopes
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=<scope key 1> <scope key 2>" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Obtain a token with a single scope
- To consume the “GET” orders resource, each user can request a token in the following manner:
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=order_view" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Sample response will be similar to the following:
{"scope":"order_view", "token_type":"bearer", "expires_in":3600, "refresh_token":"55bd3d5521bd55df393154ca244fb3", "access_token":"01877d1d9e242a3e77a019c5f30857"}
All four users are allowed to obtain a token with the above method. They can consume the “GET” orders resource with the access token they obtained.
- To consume the “POST” orders resource, Paul and Harry can request a token in the following manner:
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=order_add" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Sample response will be similar to the following:
{"scope":"order_add", "token_type":"bearer", "expires_in":3600, "refresh_token":"21bd55df393154c55bd3d55a244fb3", "access_token":"9e242a3e77a019c5f3001877d1d857"}
Paul and Harry can consume the “POST” orders resource with the access token they obtained.
- To consume the “GET” items resource, Alex, Paul and Harry can request a token in the following manner.
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=item_view" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Sample response will be similar to the following:
{"scope":"item_view", "token_type":"bearer", "expires_in":3600, "refresh_token":"1bd55df2393154c55bd3d55a244fb3", "access_token":"19c5f9e242a3e77a03001877d1d857"}
Alex, Paul and Harry can consume the “GET” items resource with the access token they obtained.
- To consume the “POST” items resource, Alex and Harry can request a token in the following manner:
curl -k -d "grant_type=password&username=<username>&password=<password>&scope=item_add" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Sample response will be similar to the following:
{"scope":"item_add", "token_type":"bearer", "expires_in":3600, "refresh_token":"44fb1bd5154c55bd3d55df23935a23", "access_token":"7a030019c5f9e21877d1d85742a3e7"}
Alex and Harry can consume the “POST” items resource with the access token they obtained.
In some cases, it is important to prevent using a resource accidently even though he has access rights. To understand this let us consider user “Harry”. He has “manager” and “agent” roles that have usage rights to all resources. According to the mapping between scopes and roles (Table 2), he can create tokens for each scope separately.
The request for generating an access token for “item_view” will be as follows:
curl -k -d "grant_type=password&username=harry&password=<password>&scope=item_view" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
For “item_add” scope, he can use the following command:
curl -k -d "grant_type=password&username=harry&password=<password>&scope=item_add" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
This way, Harry can keep separate tokens for each scope, so that he can use the “exact” access token that can access the specified resource only.
This will be useful when a user has multiple scopes and wants to make sure that no operation is carried out accidently (e.g. accidently modifying or removing a resource). On the other hand, this mechanism ensures better control over API resource usage as well.
Obtain a token with multiple scopes
On the other hand, we can obtain a single access token for a user who has multiple roles. For example, if Alex wants a single access token for all his operations, he can request a token as follows:
curl -k -d "grant_type=password&username=alex&password=<password>&scope=item_view item_add order_view" -H "Authorization: Basic <Base64(Consumerkey:ConsumerSecret)>" -H "Content-Type: application/x-www-form-urlencoded" https://localhost:8243/token
Sample response will be similar to the following:
{"scope":"item_view item_add order_view", "token_type":"bearer", "expires_in":3600, "refresh_token":"45154c55bd3d55df23934fb1bd5a23", "access_token":"d1d8577a030019c5f9e2187742a3e7"}
Using this single access token, Alex can consume “GET” orders resource, “GET” items resource and “POST” items resource. If Alex tries to consume “POST” orders resource (which is not allowed based on his roles), he will get an HTTP 403 Forbidden error with the following error message:
<ams:fault xmlns:ams="https://wso2.org/apimanager/security"> <ams:code>900910</ams:code> <ams:message>The access token does not allow you to access the requested resource</ams:message> <ams:description>Access failure for API: /sampleShopping, version: 1.0.0 with key: d1d8577a030019c5f9e2187742a3e7 </ams:description> </ams:fault>
Figure 10: Different ways of generating tokens for scopes
Figure 10 shows a pictorial representation of different ways of generating access tokens for multiple scopes.
Conclusion
This article focused on how scope management of WSO2 API Manager can be used to facilitate fine-grained resource usage and access control related to API management. Since WSO2 API Manager is a complete, enterprise-ready solution for managing APIs across the complete API lifecycle, organizations can use it to deploy and expose APIs while ensuring a secure environment for API consumption.
Moreover, this article depicted how scopes can be used when consuming resources of an API. It further described usability of scopes, using scopes to generate access tokens and different ways of using scopes with related concepts.