0

I am doing an integration with some third party where user enters Client Id and Client secret key and based on that it authenticates and all the flow works. My Client id and Client secret key are Encrypted field at object level.

In other lightning component I am trying to read these two fields in controller

result.sObject

basically in result.sObject will have the value to some particular record. Now if I do console.log(result.sObject) in console it return the the value of sObject where value of client id and client secret is readable even though it is encrypted. Do I have to do it at server side only rather client side to protect it?

1 Answer 1

3

Lightning components don’t automatically enforce CRUD and FLS when you reference objects or retrieve the objects from an Apex controller. This means that the framework continues to display records and fields for which users don’t have CRUD access and FLS visibility.

So all security checks must always be performed server-side). You must explicitly check for for isAccessible(), isUpdateable(), isCreateable(), isDeletable() prior to performing these operations on sObjects.

Here is the example

public with sharing class ExpenseController {


    @AuraEnabled
    public static List<cObject__c> get_UNSAFE_Expenses() {   //vulnerable
        return [SELECT Id, ClientId__c,Client_Secret__c FROM cObject__c];
     } 

    @AuraEnabled
    public static List<cObject__c> getExpenses() { //safe

        //check for encrypted permission
        boolean hasEncryptData = userHasEncryptedData(UserInfo.getUserId());

        @AuraEnabled
        public static Account getEncryptedField(String recId){

            Map<String,Schema.SObjectField> m = Schema.SObjectType.cObject__c.fields.getMap();

            // API Names for describes are returned in all lowercase
            Set<String> cObjectFieldsToRetrieve = new Set<String>{'id', 'ClietId__c','ClietSecret__c'};

            cObject__c objC = [SELECT Id,ClietId__c,ClietSecret__c
                            FROM cObject__c
                            WHERE Id = :recId];    


            // Iterate over describe results
            for(String val : m.keySet()){

                // Check that it is in fields that are cared about
                if(m.get(val).getDescribe().isAccessible() && cObjectFieldsToRetrieve.contains(val)){

                    // Check if it is an encrypted string and if so, sanitize
                    // else return the original value
                    if(m.get(val).getDescribe().getType().name() == 'ENCRYPTEDSTRING'){
                        objC.put(val, sanitizeEncryptedData(hasEncryptData, (String)objC.get(val)));
                    } else {
                        objC.put(val, (String)objC.get(val));
                    }

                }
            }

            return objC;

        }



        /***********************************************************
         * Description: Return if user has View Encrypted Data permission.
         * 
         * @param: userId - userId to check if has encrypted data permission
         * 
         * @return: boolean
         * ********************************************************/
        public static boolean userHasEncryptedData(Id userId){
            List<PermissionSetAssignment> psaEncrypt = [SELECT Id
                                                       FROM PermissionSetAssignment
                                                       WHERE PermissionSet.PermissionsViewEncryptedData = true
                                                       AND AssigneeId = :userId];

            if(psaEncrypt.isEmpty()){
                return false;
            } else{
                return true;
            }
        }

         /***********************************************************
         * Description: Sanitize the string if the user does not have view encrypted data permission.
         * 
         * @param: hasEncryptedData - if the user has encrypted data permission
         * @param: stringToSanitize - the string to santitize before returning to client
         * @param: fieldType - this is the type of field to sanitize, only perform if encrypted string
         * 
         * @return: boolean
         * ********************************************************/
        public static String sanitizeEncryptedData(boolean hasEncryptedData, String stringToSanitize){
            if(!hasEncryptedData && stringToSanitize != null){
                String mask = 'X';
                return mask.repeat(stringToSanitize.length());
            } else{
               return stringToSanitize;
            }

        }   
 }

Referece:

Lightning Security

CRUD and Field-Level Security (FLS)

Methods

5
  • Thanks for very quick reply. I was aware of FLS but was not aware of encrypted. while before querying the data I am checking the discoverability of fields and based on that querying the result. Commented Dec 27, 2017 at 13:28
  • I checked the apex controller also... where I am returning the result in apex class if I do system.debug(sObject) then it will be encrypted only with masking also.. but same it is decrypted and unmasked at controller. Commented Dec 27, 2017 at 13:50
  • Can you update question with your code?
    – Himanshu
    Commented Dec 27, 2017 at 13:51
  • @Sagar last link in my answer already point to that
    – Himanshu
    Commented Dec 28, 2017 at 6:17
  • String query = 'SELECT id, Name, client_id__c, client_secret__c FROM integration__c'; List<Sobject> SobjList = Database.query(query); if you iterate though the list and try to get the client_id__c and client_secret__c it will be masked only. Commented Dec 28, 2017 at 6:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .