1

In the process of getting a managed package reviewed by Salesforce and it has been flagged for Insecure Storage of Sensitive Data and they highlight the following xml.

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <customSettingsType>List</customSettingsType>
    <enableFeeds>false</enableFeeds>
    <fields>
        <fullName>Client_Id__c</fullName>
        <deprecated>false</deprecated>
        <externalId>false</externalId>
        <label>Client Id</label>
        <length>100</length>
        <required>false</required>
        <trackTrending>false</trackTrending>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>Client_Secret__c</fullName>
        <deprecated>false</deprecated>
        <externalId>false</externalId>
        <label>Client Secret</label>
        <required>false</required>
        <trackTrending>false</trackTrending>
        <type>TextArea</type>
    </fields>
    <label>ConnectedApp</label>
    **<visibility>Public</visibility>**
</CustomObject>

Notes Sensitive data like Client_Id__c and Client_Secret__c which is use in api call, should be stored in a protected custom setting or named credential.

Related Code

public class CRMA_AuthenticationCheck {
    ...
    @AuraEnabled
    public static ResponseWrapper authorizeCRMA(String session_id, String userId, String consumerSecret){
        ResponseWrapper rw = new ResponseWrapper();
        string successMsg;
        string crmaUrl;
        ConnectedApp__c conApp;
        try{
            Boolean isStaging = [SELECT Id, IsSandbox FROM Organization LIMIT 1].IsSandbox;
            if(isStaging){
                crmaUrl = 'https://salesforcestaging.mydummysite.com/index.php/logincb/';
            }else{
                crmaUrl = 'https://salesforce.mydummysite.com/index.php/logincb/';
            }
            conApp = ConnectedAppCreator.createConnectedApp(crmaUrl+userId);
            Boolean isSuccess = false;
            if(String.isBlank(consumerSecret)){
                consumerSecret = conApp.Client_Secret__c;
            }
            if(String.isBlank(consumerSecret)){
                rw.StatusCode = 120;
                rw.ResponseMessage = 'Please Enter the Consumer Secret from Connected App with name Foo Connected App' ;
                rw.toastType = 'dismissable';
                return rw;
            }else {
                conApp.Client_Secret__c = consumerSecret;
            }
            if(conApp != null && String.isNotBlank(conApp.Client_Id__c)){
                successMsg = ConnectedAppDetailsToCRMA.connectedAppDetails(conApp.Client_Id__c, consumerSecret,UserInfo.getOrganizationName(), userId, session_id);
                
                if(successMsg == 'SUCCESSFUL'){
                    isSuccess = true;
                }
            }
            ...
        }
        ...
        return rw;
    }
    ...
}

Given that the managed package is generated and we are not specifically defining ConnectedApp, don't see how we can modify the field visibility to private or protected. Any link or relevant samples are appreciated. Thank you !

djXplosivo
  • 11
  • 4
  • Where do the values of the Client Secret and Client Id come from? The fact that you're returning them to the front end is also a cause for concern. – David Reed Aug 05 '21 at 18:34
  • The values are assigned by Salesforce after they generate the Connected app. It takes some time for the connected app to be created and we prompt users to enter the client id after it becomes available. This SF Connected app allows our users to authenicate and create a direct link from their SF account to our external app. This client secret and id is encrypted and then used by a backend service (server to server) to fetch SF data, perform some business logic and then push custom fields back to SF on a scheduled basis. – djXplosivo Aug 05 '21 at 19:22
  • Why are you creating a Connected App for every org instead of using a global one? – David Reed Aug 05 '21 at 19:59
  • In order to create the link with the external app, we have to set up a callback URL that is unique for reach user Example: https://salesforce.mydummysite.com/index.php/logincb/mytestuser1 – djXplosivo Aug 06 '21 at 00:15
  • Onboarding flow: - User installs managed package on their org. - User navigated to welcome screen and enters exernal app username/password - Once external app authenticates their access, lightning app creates a the connected app (gen client id/secret) and incorporates username in the callback URL. - Lighting app makes a 2nd API call to external app which stores client id and secret over https. - User logs into external CRM to complete SF authentication. SF API oauth call passes stored client id/secret. SF promps user to login and now the account mapping completed. – djXplosivo Aug 06 '21 at 00:23
  • @DavidReed we tried to explore a generic solution but it wasn't an option since each salesforce user has their own account/db on the external app mapped to their SF org. – djXplosivo Aug 10 '21 at 04:26

0 Answers0