Start tracking your progress
Trailhead Home
Trailhead Home

Use Platform Features for Secret Protection

Learning Objectives

After completing this unit, you’ll be able to:

  • List the options and recommended practices for storing secrets within managed packages.
  • Create named credentials to securely define callout endpoints and their associated authentication parameters.
  • Describe how protected custom settings and protected custom metadata API fields can be leveraged for storing secrets.

Store Application Secrets in Salesforce

In the first unit, we learned how to identify secrets and who should have access to them. The next step is to learn how to protect them.

Luckily, in Salesforce this is easy! The Salesforce platform has a number of features that can be used to store secrets.

  • Named credentials
  • Custom settings (protected, unprotected, unmanaged, and managed)
  • Custom metadata types

In this unit, we explain each of these options for storing secrets, so you can ensure that sensitive information is appropriately restricted.

Named Credentials

A named credential specifies the URL of a callout endpoint and its required authentication parameters in one definition. Salesforce manages all the authentication for Apex callouts that specify a named credential as the callout endpoint, and you don’t have to add more authentication logic in your Apex code. Named credentials can be defined to provide a more secure and convenient way of setting up these kinds of callouts. Once created, you can replace URL references in your code with references to the named credentials instead, which results in cleaner, simpler, and more secure code.

Named credentials are particularly useful when it comes to defining callout endpoints referenced in your managed package. Without them, in order to set up an authenticated callout, the developer needs to perform these additional tasks.

  • Reference the URL as the callout endpoint
  • Register the URL in your Remote Site Settings
  • Add custom code to take care of any associated authentication tasks

For example, let’s say you have an application that regularly connects to an external service to pull data. However, this external service requires that every single request includes an API key for authentication.A common way that developers satisfy this requirement is to hard-code that key into the source code so it can be used in each request. Consider the following code example.

 String key = ‘supersecurepassword’; HttpRequest req = new HttpRequest(); req.setEndpoint('https://www.example.com/test?APIKEY='+key); req.setMethod('GET'); Http http = new Http(); HTTPResponse res = http.send(req); return res.getBody(); 

While hard-coding secrets is indeed a straightforward solution, there are three main problems with this approach.

  1. Anyone who can view the source code can also view the embedded secrets.
  2. If a secret is updated, you will need to change all instances of it throughout the source code.
  3. Porting this secret between applications can create many other complications as well.

Here’s where named credentials can save the day! Rather than hard-coding the value into your code, you can leverage named credentials to store secrets, allowing you to refer to the named credential to access the secret value, as if it were any other variable in your code.

If you use a named credential instead of the value itself, only users with the System Administrator profile and those with View All Data and Modify All Data permissions can access the value.

Named Credentials Benefits

In addition to providing a way of restricting access to your application secrets, named credentials also make maintaining these secrets a breeze. After you configure a named credential, you can easily change it whenever needed by modifying it in your settings. This way, any instances in your code referring to the secret never retain outdated values, since they reference the named credential directly.

Additionally, named credentials can be created via Setup with just a few clicks. Let’s try this out now.

Using Named Credentials

In our Kingdom Management org, we have an app that communicates with an external service. We create a named credential to secure this communication.

  1. Log in to the Kingdom Management org and select the Secret Storage app.

  2. Click the Named Credentials Demo tab.

    learn-about-platform-secret-protection

  3. This app is used by citizens of the kingdom to open a magic portal to the elusive Fountain of Youth. However, this portal is protected by a magical spell, and only those who provide the correct secret password can go through the portal. We always want the kingdom’s royal family to have safe passage through the portal at all times, so let’s set up a named credential for them.

  4. From the Home tab in Setup, enter Named Credentials in the Quick Find box, then select Named Credentials.

  5. Click New Named Credential.

  6. Create a named credential to store our magic portal access code, using these parameters.

  7. Label
    MagicPortal
    Name
    MagicPortal
    URL
    https://secret-storage.herokuapp.com/
    Certificate
    Blank
    Identity Type
    Named Principal
    Authentication Protocol
    Password Authentication
    Username
    MagicWords
    Password
    hocus-pocus

    Screenshot of the Named Credential

  8. Click Save.


Now that we’ve configured our credentials, we can add it to our application.

  1. Navigate back to the Named Credentials tab.
  2. Click the Apex Controller link at the bottom of the page.
  3. Update the getOpenPortal function to use our newly configured credentials.

  public void getOpenPortal() { 
    HttpRequest req = new HttpRequest(); 
    req.setEndpoint('callout:MagicPortal'); 
    req.setMethod('GET'); Http http = new Http(); 
    HTTPResponse res = http.send(req); 
    portalStatus res.getBody(); 
  }


As we can see, it’s as easy to use named credentials as it is to configure them. By simply including the callout:MagicPortal as our http endpoint, the Apex code sends along our preconfigured credentials to the external system. Once an admin (or someone with the Modify All Data permission) creates the named credentials in the system, developers don’t need to know what the secret values are in order to reference them in Apex code.
They only need the name of the named credentials containing those values.

  1. Navigate back to the Named Credentials Demo tab.

  2. Click Cast Spell.

Screenshot showing a successful connection to the fountain via the portal

Nice! Using our named credentials, we opened the portal. Now our royal family and their loyal companions will be young forever!

Where should and shouldn’t I use named credentials?

Even though it’s fairly simple to set up named credentials, they’re not necessarily a good solution for every use case.Named credentials are best suited for simple authentication schemas, such as username and password or OAuth 2.0.

Named Credentials are designed to make life easy and secure for Admins and Developers in your Org. That said, they aren't always the best choice. Because users with Modify all Data or Author Apex can modify or make callouts to the Named Credential, they'll also be able to access the data protected by the Named Credential. Or, if they're clever, they might be able to extract the credentials themselves. If you need to protect against these use-cases like you're an ISV building a package that needs to privately talk to your own cloud services, then consider other options like Managed protected custom settings or managed protected custom metadata types. You can read more about those below!

Secure Distributed Secrets

Named credentials are perfect for situations where callouts are being made to external services in an org where admins are allowed to access the associated authentication secrets. But what do you do when you have to prevent admins from seeing the data, or when you want to distribute secrets across multiple Salesforce orgs?

In situations like these, code should be deployed in the form of a managed package. You can easily spin up a free Developer Edition org to serve as a packaging org for your code. If you’re a AppExchange Partner, DE orgs can be created via your Environment Hub. You can also visit the  Developer Edition signup page. Within your packaging org, you can wrap up Apex classes, Visualforce pages, Apex triggers, Salesforce objects, and other common forms of metadata into a managed package, which allows it to be easily deployed to any other Salesforce instance or org. You can think of a managed package as a more complex version of a zip file.

From a security perspective, using managed packages (as opposed to unmanaged packages, or loose code) comes with many significant benefits.

  • They have the mechanics required to push automatic updates, patches, and fixes if security vulnerabilities are identified.
  • They have obscured source code (with the exception of explicitly exposed global Apex classes) meaning that any fundamental business or program logic can’t be altered so that it’s broken inadvertently, or modified in a malicious way and redistributed. Obscured code also prevents secrets contained in the package from being seen.
  • Since you must define a unique namespace for your managed package, it prevents conflicting namespace issues. It also segregates your package from the local namespace, further protecting the secrets contained in your package. By default, package secrets cannot be accessed by code that runs outside of managed package.

For more information about packaging applications and metadata, check out the AppExchange App Development module.

Managed Protected Custom Settings and Custom Metadata Types

While simply packaging up your code in a managed package has a lot of security benefits, using a managed package also grants access to two other features available for storing and distributing information: protected custom settings and protected custom metadata.

Custom settings can be created to store almost any kind of data, and are extremely flexible in terms of their potential uses and contents. In summary, custom settings let you create custom sets of data that are exposed to the application cache, so you avoid repeated queries to the database and increase the efficiency of your app. For example, a custom setting can be used to store a set of data that is used to personalize user experiences with an application. Or perhaps a custom setting can be created to store a list of product names that are referenced on numerous different pages, in order to provide quick and easy access. In terms of application security, custom settings can be used to store sensitive information, or secrets.

Custom settings can have different levels of visibility. A protected custom setting contained in a managed package is not visible to subscribing organizations through Apex or the API, making it a good place to store certain kinds of secrets. Custom settings set to public visibility or contained in an unmanaged package are visible through the Enterprise WSDL, which is why it’s important that protected custom settings be encapsulated in a managed package when housing sensitive information.

Custom metadata fields can be utilized for secret storage in a similar way to custom settings. For proper secrecy, set their visibility to ‘protected’ and contain them within a managed package. Protected custom metadata API fields are a great choice for storing API keys or other secret keys, for example.


In regard to visibility settings, both custom settings and metadata fields have several options.

  1. Public (Local)
  2. Protected (Local)
  3. Public (Managed)
  4. Protected (Managed)

While the first three options are viable for storing data in general, everyone in the org can see data values when you use these settings. Use them only when you’re storing publicly accessible data. For sensitive data, like application secrets, use the managed protected configuration option. 

The obscured visibility option, ease of access, and caching functionality make custom settings and metadata fields viable and appealing options for secret storage.

Creating Managed Protected Custom Settings

You can create a managed protected custom setting named Kingdom Secrets that can be used to store secrets securely. Create a protected custom setting in Setup by going to Quick Find -> Custom Settings, and then clicking New. Define a label, object name, setting type, and visibility (set this to Protected). More details about these field types are available here. Once you click Save, you’re ready to add custom fields to store the secrets.

Screenshot of the custom settings

Finally, enter your secrets inside your protected custom fields. Because only settings definitions are included in the package, you need Apex or an API script to populate the secrets for you once the package is installed on the targeted or subscriber org.

How to Use Managed Protected Custom Settings

You can reference custom settings in the same ways you reference custom objects. To access custom settings, you can use formula fields, Apex custom settings methods, SOAP API, validation rules, flow, and so on. References to the protected custom setting can only be made from within the same managed package (that is, the same namespace). Some common Apex methods for referencing custom settings are:

  • getAll()
  • getValues()
  • getOrgDetauls()
  • getInstance(Profile_ID)

Here’s an example that uses getAll() to access secrets stored as a custom setting component.

Map<String_dataset_name, CustomSettingName__c> mcs = CustomSettingName__c.getAll();


Pretty simple, right? To learn more about custom settings and how to set them up, consult the  Apex Developer Guide.

Custom Metadata Types

Protected custom metadata types can also be defined to hold secrets, similar to the way we just defined the custom setting. As we explained, these should be designed for inclusion within a managed package in order for them to be effectively obscured and protected. The main difference, as the term suggests, is that data contained in custom metadata types represents metadata in your app. This can often prove to be advantageous, as we explain in this section.

Imagine that you’re a developer creating a new app in your Developer Edition packaging org. This app has all kinds of cool features, including an external API integration with example.com. In order to make callouts to example.com, you need to store an API key somewhere. One option is to store the API secret key inside a custom field. This works fine within your own DE org, but what’s wrong with this approach? Besides being an insecure solution, there’s an issue when it comes to redeployment. When you try to move all your code and customizations to your production org, the value of your secret key doesn’t get pushed at the same time. As you learned if you completed the Change Management module, data isn’t moved to production with your change set. You have to insert the key value into the field manually, or you have to write a script to populate it for you. With a custom metadata type, on the other hand, your API secret key is treated just like any other customization and is moved to production. So you don’t have to insert it again yourself.

As we mentioned earlier, to load data in a custom setting, you have to write some kind of postinstall script. But you don’t have to write scripts with protected custom metadata types. The data contained in a custom metadata type is available to you as separate metadata, which you can add to the package. Awesome, right?

One of the nicest things about custom metadata types is that you can grab them using SOQL, like with any custom object. The only difference is metadata types have a suffix of __mdt instead of __c. So if you need to select a custom metadata type, write a query like this.

SELECT Cavalry__c, Infantry__c, Weapon__c , Armor__c FROM Secret_Defenses__mdt 

This line retrieves all values of Secret_Defenses__mdt. Easy peasy!


For more information on implementing custom metadata types in a managed package, check out the Custom Metadata Types module.

Compare Custom Settings and Custom Metadata Types

While you can use either custom settings or custom metadata types to secure secrets, there are some differences between the two that are worth noting.

Use protected custom settings when:

  1. The secret needs to be updated frequently and must be available immediately.Since metadata types need to be enqueued and deployed, updated secrets in metadata types aren’t available right away, making a custom setting the better option here.
  2. You want to specify which profiles and users can access which secrets.Metadata types don’t offer the granularity of custom settings hierarchy type, which you can specify to which profiles or users the secrets should be available. Thus, it is better to use a custom setting here.

Use custom metadata types when:

  1. You want to deploy a common secret without extra configuration steps.
  2. Custom metadata secrets can be easily migrated, for example, from a sandbox or dev environment to a production environment by using Salesforce Change Management. Whereas in custom settings, admins need to either write postinstall scripts or create Visualforce pages and manually enter and store secrets in new the environment, typically when migrating from a sandbox to production environment.

Resources

Apex Developer Guide: Named Credentials as Callout Endpoints

Salesforce Developers Blogs: How to use custom metadata types 

Apex Developer Guide: Custom Settings Methods

retargeting