...
Date: | Author: | Version: | Changes: | Completed | Ext. | Int. | Is in Core | Jira Ref. | |||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0.1 | Doc. created |
| x |
| N/A | ||||||||
22 November 2018Emil Ion Ifrim | Emil Ifrim | 0.2 | Brand Enabling | Yes | x | N/A | |||||||
15 January 2019 | SD | 0.3 | Download pdf-file | ||||||||||
17 March 2023 | Emil Ifrim | 04 | Fine Grain Security |
Overview
This page describes the security layers of the REST web app. There are two security layers:
...
Authentication is triggered by the Authorization layer. If a resource does not require Authorization, then it is considered open for access, unless brand access check is in place. The Authentication protocol used is OAUTH2 and the implementation used is from Spring Framework.
...
User-authentication - this corresponds to a Selfcare use-case scenario. The authentication is done by validation username/password in the USERS table. An URL example for this scenario is (note grant_type=password value):
Code Block title Authentication URL https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=password&brandKeybrand_key=#myBrandKey
Code Block title CURL example CURL example: curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=password&username=#myusername&password=mypassword&brandKeybrand_key=#myBrandKey" where: #myusername, #mypassword are taken from Users table #myBrandKey is taken from the Brand table myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
Code Block title Angular example function login(credentials) { var data = 'username=' + encodeURIComponent(credentials.username) + '&password=' + encodeURIComponent(credentials.password) + '&grant_type=password&scope=read%20write&' + 'client_id=myclientid&' + 'brandKeybrand_key=myBrandKey'; return $http .post('/oauth/token', data, { headers : { 'Content-Type' : 'application/x-www-form-urlencoded', 'Accept' : 'application/json', 'Authorization' : 'Basic ' + base64Service.encode('myclientid' + ':' + 'myclientsecret') } }).success( function(response) { //store the access token return response; }); } where: credentials.username, credentials.password are taken from Users table myBrandKey is taken from the Brand table myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
Operator-authentication - this correspnds to a Customercare use-case scenario. The authentication is done by validation username/password in the OPERATORS table. An URL example for this scenario is (note grant_type=operator_password value):
Code Block title Authorization URL https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=operator_password&brandKeybrand_key=#myBrandKey
Code Block title CURL example CURL example: curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=operator_password&username=#myusername&password=mypassword&brandKeybrand_key=#myBrandKey" where: #myusername, #mypassword are taken from Operators table #myBrandKey is taken from the Brand table myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
...
Brand Access
In order to obtain an access token, the client has to have configured the proper authorization. That is, in the OAUTH_CLIENT_DETAILS table, a client has to have defined proper values in AUTHORITIES column. Those authorities must have the following prefix: ACCESS_BRAND_ .After the prefix there should be the brandKey brand_key (uppercase) that the respective client has access to. The brandKey brand_key parameter should be sent as QUERY parameter in the request for the token.
Example of registered client:CLIENT_ID RESOURCE_IDS CLIENT_SECRET SCOPE AUTHORIZED_GRANT_TYPES WEB_SERVRE_REDIRECT_URI AUTHORITIES ACCESS_TOKEN_VALIDITY ADDITIONAL_INFORMATION AUTOAPROVE swagger-ui swagger-ui-secret read,write password,operator_password,client_credentials ACCESS_BRAND_BRAND_X 600
Example: given a brand key with a value of RATOR_X , the authority tag should be ACCESS_BRAND_RATOR_X .
If a client has access to multiple brands, those should be separated by , (e.g ACCESS_BRAND_RATOR_X, ACCESS_BRAND_RATOR_Y)Code Block title CURL example CURL example: curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=operator_password&username=#myusername&password=mypassword&brandKeybrand_key=RATOR_X"
Fine-grained access control is about limiting the access to specific resources, or even to limit the access to code blocks within a single resource. The current version of the REST app uses our own framework for this. The framework defines two abstract classes, whose implementations stand in a one-to-one relationship with a resource (an @Path annotated method). The two classes reflect the kind of questions/checks needed in the code.
...
the @RatorSecured annotation that can have few input attributes, in orderto define the assesed field or the Role of the logged in user.
Code Block | ||||
---|---|---|---|---|
| ||||
// URL - /accounts/{account-id}/subscriptions
map.put(key(HttpMethod.GET,ResourcePathParent.ACCOUNTS, ResourcePath.ACCOUNTID_SUBSCRIPTIONS),new AccessControllerByOwnership(Ownership.SUB_OR_BG_OR_ACC_OWNER));
//URL - /accounts/{account-id}/documents
map.put(key(HttpMethod.POST,ResourcePathParent.ACCOUNTS,ResourcePath.ACCOUNTID_DOCUMENTS),new AccessControllerByOwnership(Ownership.ACC_OWNER));
//URL - /accounts/{account-id}/documents
map.put(key(HttpMethod.GET,ResourcePathParent.ACCOUNTS,ResourcePath.ACCOUNTID_DOCUMENTS),new AccessControllerByOwnership(Ownership.ACC_OWNER));
//URL - /accounts/{account-id}/billing-groups
map.put(key(HttpMethod.GET, ResourcePathParent.ACCOUNTS,ResourcePath.ACCOUNTID_BILLING_GROUPS),new AccessControllerByOwnership(Ownership.BG_OR_ACC_OWNER)); |
...
@RatorSecured(requiredRole = Role.OPERATOR , assertOn = "subscriptionId")
public Response updateNpFlow(@PathParam("subscription-id") SubscriptionId subscriptionId) {...}
@RatorSecured(requiredRole = Role.SUB_OWNER, assertOn = "userId")
public Collection<ContactPoint> getContactPointsForUser(@PathParam("user-id") UserId userId) {...}
@RatorSecured(requiredRole = Role.OPERATOR, restrictorFactory = OperatorAccessRestrictorFactory.class)
public Collection<Product> getProducts(@Context RESTContext ctx) { ... }
|
Brand Access Check
In case of a multi branded environment it is possible to restrict access to the "public" endpoints by enabling the brand access check in the configuration file (Properties.txt). This is done by setting the following parameter:
...
When the above parameter is in place an access token (Authorization: Bearer access_token) is required to be sent in the request. For public endpoints one can obtain a access token by using the "clientoperator_credentialspassword" grant type.
Code Block | ||
---|---|---|
| ||
https://host:port/appcontext/oauth/token?grant_type=client_credentials&brandKeyoperator_password&username=#myusername&password=mypassword&brand_key=a_valid_brand_key |
Code Block | ||
---|---|---|
| ||
CURL example: curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=client_credentials&brandKeyoperator_password&username=#myusername&password=mypassword&brand_key=#myBrandKey" where: myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table #myBrandKey is taken from the Brand table |
...
Info | ||
---|---|---|
| ||
To configure swagger to use this authentication scenario, an additional parameter has to be set in Properties.txt file: rest.swagger.auth.flow=clientoperator_credentialspassword |
Info | ||
---|---|---|
| ||
To configure swagger to allow testing endpoints when REST is deployed behind a proxy (e.g CI/CD and docker) an additional parameter has to be set in Properties.txt file: rest.swagger.api.context_path=/rator-rest-api/v1 #the valuehas to adjusted according to the proxy configuration |
...