Storing secrets or passwords using manage package in Salesforce – Video

Salesforce supports Encrypted Field out of the box on standard or custom objects. However, users with appropriate profile or permission set can easily view content of those fields. If we want to store secure information like passwords (of external systems), then there is no direct way to achieve this. If we think about passwords, no one should be able to view it. If we forget password, then instead of system sending old password, it forces us to reset it.

We will create same behaviour in Salesforce where stored password cannot be viewed by anyone.

Storing Passwords in Salesforce
Storing Passwords in Salesforce

We will need a developer org with any namespace. In my case, namespace is “Livecoding”. Namespace can be created from “Setup | Build | Create | Packages | Developer Settings | Edit”. We need namespace so that manage package can be created. Idea is to have a protected custom setting. Protected custom setting can only be accessed in manage package and we will create global class, which can be used in subscriber (Client) org to perform various operations related to storing and getting passwords.

I have created custom setting by name “Livecoding__secrets__c” (Livecoding is namespace added by default in API name). Field of type text is created to store password by name “Livecoding__Password__c”.

To perform various operations, below global class is created with three methods:

/**
 * 	@Author			:	Jitendra Zaa
 * 	@Date			:	13-Feb-2016
 * 	@Description	:	Various operations to be performed on passwords	
 * 
 * */
global class Operations {
    
    /**
     * To store username and secret, use this method
     * */
    global static void addSecrets(String username, String password){
        
        Livecoding__Secrets__c obj = new Livecoding__Secrets__c(name = username, Livecoding__Password__c= password);
        insert obj;
    }

	/**
	 * This method checks if password entered is correct or not 
	 * */    
    global static boolean isPasswordCorrect(String username, String password)
    { 
        //read custom setting using SOQL
        List<Livecoding__Secrets__c> lstRecords = [SELECT ID FROM Livecoding__Secrets__c WHERE Name = :username AND  Livecoding__Password__c =: password ];
        
        if(lstRecords.isEmpty())
        {
            return false;
        }
        return true;
    }
    
    /**
     * Reset password of existing user 
     * */
    global static boolean resetPassword(String username, String password){
        
        //read custom setting without SOQL
        Livecoding__Secrets__c userRecord = Livecoding__Secrets__c.getValues(username);
         
        if(userRecord == null)
        {
            return false;
        }
        
        userRecord.Livecoding__Password__c = password ;
        update userRecord; 
        
        return true;
    } 
}

To create manage package, we must need to have minimum 75% of test coverage. Below test class gives 100% test coverage to our manage package.

/**
 * 	@Author			:	Jitendra Zaa
 * 	@Date			:	13-Feb-2016
 * 	@Description	:	Test class for "Operations"
 * */

@isTest
public class OperationsTest {
	
    
    @testSetup 
    static void setupCustomSetting() {
        Livecoding__Secrets__c obj = new Livecoding__Secrets__c(name = 'abc@livecoding.tv', Livecoding__Password__c= 'sample1');
        insert obj;
	}
    
    
    static testMethod void addSecrets_Test(){
        Operations.addSecrets('xyz@livecoding.tv','xyz');
        
        List<Livecoding__Secrets__c> lstCustomSettings = Livecoding__Secrets__c.getAll().values();
        System.assertEquals(lstCustomSettings.size(), 2);  
    }
    
    static testMethod void isPasswordCorrect_No_Test(){
        boolean retValue = Operations.isPasswordCorrect('abc@livecoding.tv', 'password') ;
        System.assertNotEquals(retValue, true) ;        
    }
    
    static testMethod void isPasswordCorrect_Yes_Test(){
        boolean retValue = Operations.isPasswordCorrect('abc@livecoding.tv', 'sample1') ;
        System.assertEquals(retValue, true) ;        
    }
    
    static testMethod void resetPassword_No_Test(){
        boolean retValue = Operations.resetPassword('abc@livecoding.com', 'password') ;
        System.assertEquals(retValue, false) ;  
    }
    
    static testMethod void resetPassword_Yes_Test(){
        boolean retValue = Operations.resetPassword('abc@livecoding.tv', 'password') ;
        System.assertEquals(retValue, true) ;  
        
        retValue = Operations.isPasswordCorrect('abc@livecoding.tv', 'password') ;
        System.assertEquals(retValue, true) ;    
    }    
}

In above test class, we have used @testSetup method. It is used to create a common test records being used by all testmethod. This method is implicitly called before each testmethod in class.

It’s time to create Manage package now. Navigate to “Setup | Build | Packages | New”. This manage package will have below three components

  1. Protected public setting
  2. Global Apex class to perform operations on Custom Setting
  3. Test class for Apex to cover minimum 75%

If we need to store password in any org, we can install above manage package in that org. To perform operations related to password, we can use any of three global methods available in manage package.

Other resources:

Posted

in

by


Related Posts

Comments

2 responses to “Storing secrets or passwords using manage package in Salesforce – Video”

  1. Tobias Avatar
    Tobias

    Hi.
    I’ve created a managed package with a custom setting, and a UI to store some credentials in that settings.
    The problem is that after I refresh from production, the sandbox is bringing the package, with the custom setting, but also with the data loaded.

    Any idea how to avoid that behavior?

    Thanks in advance,
    Tobias

  2. Yury Pritzker Avatar
    Yury Pritzker

    This approach only works when you STORE and retrieve data in the target org. In case you want to deploy a secret such as the encryption key, you have to use custom metadata instead of a custom setting. Custom Metadata in the Managed package will be deployed to the target org.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Jitendra Zaa

Subscribe now to keep reading and get access to the full archive.

Continue Reading