Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

 

Date:

Author:

Version:

Changes:

Completed

Ext.

Int.

Is in Core

Jira Ref.



0.1

Doc. created

Yes/No


x 


N/A


22 November 2018Emil Ifrim0.2Brand EnablingYes/Nox 
N/A 

...


15 January 2019SD0.3Download pdf-file




17 March 2023Emil Ifrim04Fine Grain Security 





Overview

This page describes the security layers of the REST web app. There are two security layers:

  1. Authentication
    1. Client-authentication: The database table OAUTH_CLIENT_DETAILS describes the servers, which are allowed to make calls to the REST web app. (Typically this will be the selfcare web app and, when in development, the Swagger UI)
    2. User/Operator/App-authentication: A username/password based security layer that upon each requests matches a token from the request against an in-memory map from token to logged in users.

  2. Authorization: A fine grained access rights control implemented in all resources that shall have limited access. This layer is customizablecustomizabile: The customer can register their own rules. The default rules are all based on "ownership": Account-ownership, BillingGroup-ownership and Subscription-ownership.

 

Authentication

Authentication is triggered by the Authorization layer. If a resource does not require Authorization, then it 's is considered open for access, unless brand access check is in place. The Authentication protocol used is OAUTH2  OAUTH2  and the implementation used is from Spring Framework.

...

  1. User-authenticatio - 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
    titleAuthorization Authentication URL
    https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=password&brand_key=#myBrandKey


    Code Block
    titleCURL 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&brand_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
    titleAngular example
    function login(credentials) {
          var data = 'username=' +
            encodeURIComponent(credentials.username) +
            '&password=' +
            encodeURIComponent(credentials.password) +
            '&grant_type=password&scope=read%20write&' +
            'client_id=myclientid&' +
            'brand_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


  2. Operator-authentication - this correspnds to a Customecare 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=ccoperator_password value):

    Code Block
    titleAuthorization URL
    https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=ccoperator_password&brand_key=#myBrandKey


    Code Block
    titleCURL example
    CURL example:  curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=ccoperator_password&username=#myusername&password=mypassword&brand_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
    Trusted app-authentication - this corresponds to a "backend" use-case scenario. The authentication is done by validation username/password in the 


Authorization

Authorization is done in two steps:

  1. 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. An URL example for this scenario is (note grant_type=client_credentials value):

    Code Block
    titleAuthorization URL
    https://host:port/appcontext/oauth/token?grant_type=client_credentials

    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 brand_key (uppercase) that the respective client has access to. The brand_key parameter should be sent as QUERY parameter in the request for the token.

    Example of registered client:

    CLIENT_IDRESOURCE_IDSCLIENT_SECRETSCOPEAUTHORIZED_GRANT_TYPESWEB_SERVRE_REDIRECT_URIAUTHORITIESACCESS_TOKEN_VALIDITYADDITIONAL_INFORMATIONAUTOAPROVE
    swagger-ui
    swagger-ui-secretread,writepassword,operator_password
    ACCESS_BRAND_BRAND_X600



    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
    titleCURL example
    CURL example:  curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=client_credentials"
    
    where:
    myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
    Info
    titleAttention!

    Use this scenario in a secure setup (both apps behind a firewall, where only access from the trusted app is allowed). The reason behind this is that the clientid and the client password are send using Base64 encription.

    Info
    titleSwagger

    To configure swagger to use this authentication scenario, an additional parameter has to be set in Properties.txt file:

    rest.swagger.auth.flow=client_credentials

 

Authorization

  1. operator_password&username=#myusername&password=mypassword&brand_key=RATOR_X"
    


  2. 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

...

  • AccessController: Implementations must implement a single method called assertAccessible(AccessContext), which returns a boolean. This method is called before entering the resource.
  • AccessRestrictor:  Implementations must implement a single method called restrict(List<?>). This is called before returning Lists of objects, and provided the customer with an opportunity to filter away restricted resources (such as Subscriptions, for which the caller does not have some sort of ownership over.

Customizations

...

  1. 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
languagejava
titleAccess Configuration
// 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:

Code Block
languagebash
titleEnable brand access check for public endpoints
rest.api.security.public.brand_access_check=true

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 "operator_password" grant type. 


Code Block
titleAuthorization URL
https://host:port/appcontext/oauth/token?grant_type=operator_password&username=#myusername&password=mypassword&brand_key=a_valid_brand_key


Code Block
titleCURL 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&brand_key=#myBrandKey"

where:
myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
#myBrandKey is taken from the Brand table


Info
titleSwagger

To configure swagger to use this authentication scenario, an additional parameter has to be set in Properties.txt file:

rest.swagger.auth.flow=operator_password


Info
titleSwagger UI and proxy

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

CORS

In order to be able to access both the AUTH app and REST app from Javascript clients, CORS parameters need to be configured. Below there is an example of how that can be done:

Code Block
titleCORS
rest.auth.cors.allowed-origins=*
rest.auth.cors.allowed-methods=GET, PUT, POST, DELETE, OPTIONS
rest.auth.cors.allowed-headers=*
rest.auth.cors.exposed-headers=
rest.auth.cors.max-age=3600 

rest.api.cors.allowed-origins=*
rest.api.cors.allowed-methods=GET, PUT, POST, DELETE, OPTIONS
rest.api.cors.allowed-headers=Origin, X-Requested-With, Content-Type, Accept, Authorization, X-RATOR-brand-key
rest.api.cors.exposed-headers=
rest.api.cors.max-age=3600 

...