Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

Date:

Author:

Version:

Changes:

Completed

Ext.

Int.

Is in Core

Jira Ref.

0.1

Doc. created

Yes/No

x

 

N/A

 

 

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 customizable: 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 considered open for access. The Authentication protocol used is OAUTH2  and the implementation used is from Spring Framework.

In order to call REST resources that require Authorization, the calling client has to provide an Access Token. Obtaining an Access Token can be done by calling a specific URL. There are three strategies/scenarios to obtain an Access Token.

  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):

    Authorization URL
    https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=password
    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"
    
    where:
    #myusername, #mypassword are taken from Users table
    myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
    Angular example
    function login(credentials) {
          var data = 'username=' +
            encodeURIComponent(credentials.username) +
            '&password=' +
            encodeURIComponent(credentials.password) +
            '&grant_type=password&scope=read%20write&' +
            'client_id=myclientid';
          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
    myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
  2. Operator-authentication - this correspnds to a Customecare 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=cc_password value):

    Authorization URL
    https://host:port/appcontext/oauth/token?username=#myusername&password=#mypassword&grant_type=cc_password
    CURL example
    CURL example:  curl -v -X POST -u myclientid:myclientsecret http://host:port/appcontext/oauth/token -H "Accept: application/json" -d "grant_type=cc_password&username=#myusername&password=mypassword"
    
    where:
    #myusername, #mypassword are taken from Operators table
    myclientid, myclientsecret are taken from OAUTH_CLIENT_DETAILS table
  3. Trusted app-authentication - this corresponds to a "backend" use-case scenario. The authentication is done by validation username/password in the OAUTH_CLIENT_DETAILS table. An URL example for this scenario is (note grant_type=client_credentials value):

    Authorization URL
    https://host:port/appcontext/oauth/token?grant_type=client_credentials
    CURL 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

    Attention!

    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.

    Swagger

    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

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.

  • 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

Both AccessController and AccessRestrictor use the resource path (URL) in order to determine what kind of access control to apply. The mappings are stored in a map structure as in the example below:

Access 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));

In a customer project, additional mappings need to be added and this can be achieved by implementing the com.cdrator.selfcare.model.security.ownershipcontrol.AccessByOwnershipConfigurationBuilder (respectively com.cdrator.selfcare.model.security.ownershipcontrol.RestrictForOwnershipConfigurationBuilder) interface(s) and using the ServiceLoader feature to load the implementation(s).

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:

CORS
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
rest.api.cors.exposed-headers=
rest.api.cors.max-age=3600 

  • No labels