Best Practice: Secure API Keys in Salesforce — Example: Google Firebase

Some time ago Salesforce introduced Named Credentials as a new way to secure secrets in Salesforce. In this post I will explain how to secure API Keys in Salesforce and make callouts to external systems without presenting the secret to developers.

1-p0asVKOPdPeMxYoHyTtE-A

In Winter ’16 Salesforce introduced Named Credentials. Before the common way to store passwords and api keys were “Custom Settings”.

Custom settings had the clear downside that username and password as well as API Keys, Tokens and oAuth Secrets where stored openly and accessible for everyone with access to custom settings.

Named Credentials in comparison do not present passwords and secrets to the user or developer.

How secure are Named Credentials?

Salesforce is recommending to use Named Credentials for all types of callouts.

Named Credentials are a safe and secure way of storing authentication data for external services called from your apex code such as authentication tokens. We do not recommend storing other types of sensitive data in this field (such as credit card information). Be aware that users with customize application permission can view named credentials, so if your security policy requires that the secrets be hidden from subscribers, then please use a protected custom metadata type or protected custom setting. For more information, see named credentials in the online help and training guide.
Source: https://developer.salesforce.com/page/Secure_Coding_Storing_Secrets

As mentioned by Salesforce users with “Customize Application Permissions” can view named credentials. This applies for the named credential itself.
However, when it comes to the passwords stored in named credentials, they are not visible to users or developers:

  • Credential Passwords cannot be made visible in the UI
  • Credential Passwords cannot be accessed through API
  • Credential Passwords cannot be made visible in Debug Logs

Only in the moment the HTTP Request to external systems is executed, Salesforce inserts the password into the request and sends the request to the External Service.

The External Service can then use the password or other credentials to verify the request.

Setup Named Credentials: Example Firebase

Firebase is a service by Google that can be used to send push notifications to users. Salesforce can call firebase and send a push notification to specific users.

1-N2PrV3b95tBsRRdUXuHY0A

Step 1: Setup Named Credentials

To setup the API Key I first had to setup a new server key in firebase.
(Firebase → Project Settings → Message Key)

1-zzewkVIuxqc5Lnw6OUfe4g

In Salesforce the Named Credential for Firebase can be created now.
(Setup → Quick Search → Named Credentials)

1-dpiln4cB8W-5hLf-C5qGZQ

The following properties have to be entered:
The Endpoint that has to be called is fcm.googleapis.com.
As Identity Type I have chosen Named Principal, since the API key is the same for the whole org.

  • The Authentication Protocol is “Password Authentication”.
  • As Username I entered a dummy value.
  • The password is the API Key.

To use the password in the header of my request, the tick box “Allow Merge Fields in HTTP Body” must be checked.

Step 2: Callout

To be able to call Firebase, I added Firebase to my “Remote Sites” (Setup → Quick Search → Remote Site).
Sending out a request with Named Credentials is using the same functionality as in any other APEX HTTP request:

String message = ‘XYZ’;
// HTTP Request
HttpRequest req = new HttpRequest();
// Callout extended by /fcm/send
req.setEndpoint(‘callout:Firebase/fcm/send’);
req.setMethod(‘POST’);
// Authentication
req.setHeader(‘Authorization’, ‘key={!$Credential.Password}’);
req.setBody(message);
// send request
Http http = new Http();
HTTPResponse res = http.send(req);
123456789101112

As Endpoint for the HTTPRequest I used callout:Firebase. This indicates to Salesforce that the Named Credential Firebase is used.

During the execution of the HTTP request “callout:Firebase” is getting replace with the URL stored in the Named Credential. The placeholder {!$Credential.Password} is replaced by the password stored in Salesforce.

Step 3: Result

The Debug Log proofs: The request was successfully send to Firebase.

1-Vk8K1ZCDnBBL38-ndWv2gA

Conclusion

Named Credentials are the secure way to store credentials for callouts in Salesforce.